Простотаданныхзалогпроизводительности

Принимаяучастиевмногочисленныхпроектахязаметилнеприятную,непонятнуюмнетенденцию:“товарищипоцеху”частогородятстрашныеконструкциидляописаниясущностей,вместопростыхданныхиспользуютсложныеструктурыстекстовымиполями,глубокимивложенностями。 Какпримервозьмемпростуюигру“тривряд”,гдеуячеекрасположенныхнаигровомполеприсутствуют,какминимум,трипараметраописывающихих:цвет,тип,состояние。 Вотсамое“безобидное”описаниелогическойячейкичтоявидел:

public struct Cell 
{
public string Type;
public string State;
public Color Color;
}

Этоткусоккодакажетсяпонятнойиправильной,ноэтонетак。 Во-первых,подобныеструктурыплохоразмещаютсявпамяти,фрагметируяеё。 Во-вторых,ихнеудобносравниватьдругсдругом,проверятьпринадлежностьоднойячейкикопределел。 Наконец,сохранениематрицы(прямоугольныймассив)такихданныхвовнешнемфайле,ввеера Проблемдобавляетвозможностьотсутствияуячейкиодногоизпараметров。

Вотвампримеружасненькогокода (来自RL)

 public bool IsSameTypeAndState(Cell a, Cell b) 
{
return a.Type != null && b.Type != null && a.Type.Contains(b.Type) && a.State != null && b.State != null && a.State.Contains(b.State);
}

Ксчастью,существуютметодыболееудачногопредставленияподобныхданных。

Записьбайтами

РассмотримпримерструктурыCellприведеннооовыше。 原始256个数字。 ПриэтомполеColorэтологическийцветячейки。 Тогдаэтуструктуруможнопееноенентерен

 byte color, type, state; 
uint cell = color << 16 | state << 8 | type << 0;

Получаемоченькомпактныйиэкономичныйспособпредставления。 Впамятиданнаязаписьразмещаетсябезлишнейфрагментации。 Какбонус,полноеотсутствиепровероксnull。 Ужасненькоесравнениястрокпревращаетсявпростоесравнениедвухчисел

 if(a == b)... 

,тобыполучитьзаписанноозначение typestate илиcolorнужновсеголишьсдвинутьчислонанеобходимоеколиче。

 color = cell >> 16; 
public bool IsSameTypeAndState(uint a, uint b)
{
return a >> 8 == b >> 8 && (byte) a == (byte) b;
}

“тотметодможноприменятьнетолькокиграмвстиле“тривряд”。 ВсвоейигреBubbly Tapяиспользуюподобныйподходчтобыкомпактнозаписатьисохранитьграфуровня。 Ельмассивнодпредставленныхспомощьюushortгдепервыйбайт–типноды,второйбайт–ёсостояния。 Имассивсвязей,такжеushort,гдевобабайтазаписаныиндексыизмассиванод。 图片:описаниесамогобольшогоуровняпомещаетсявфайлразмером254байта。

Чистыйкод

Вэтомметодеестьодиннедостаток-кодотносительноплохочитается。 Труднозапомнитьбайтовыезначениявсехтипов,цветов,состояний以及самкодможетпревратитесевла Ксчастьюc c# (扩展名方法)枚举枚举ирасширения。

Дляудобства,припомощи枚举можнозаписатьвсевозможныевариантыполей:

 public enum CellColor:byte 
{ None = 0x0, Red = 0x1, Green, Blue, ... }

Спомощьюрасширения(扩展方法)получатьзначениенеобходимогополяизцелогочисла:

 public static CellColor ToColor(this uint value) 
{
return (CellColor)value >> 16;
}

CellColor color = cell.ToColor();

Вывод

Старайтесьиспользоватьпростыепредставленияданных,чемпрощеформатданных,темпроен Думайтеоданныхвпервуюочередь! Оспособеобработкиподумаетевбудущем,когдапоявитсячеткоепредставлениечтонеобхотевоа。 Правильныйподборструктурданныхдаствамприростпроизводительности,

Небольшойбонус,кодреализацииописанноговышеметода:

最初于 2017 年5月31日 发布在 merlinds.com 上。