2015-11-12 3 views
2

Основной тип базового блока моего приложения распадается на тип (класс или структуру), который содержит некоторые стандартные типы значений (int, bool и т. Д.) И некоторые типы массивов стандартных типов значений, где будет небольшой (но неизвестно) количество элементов в коллекции.Как создать коллекцию типов значений в .NET?

Учитывая, что у меня есть много примеров вышеуказанного строительного блока, я хотел бы ограничить использование памяти моего базового типа, используя массив/коллекцию как Тип значения вместо стандартного ссылочного типа. Отчасти проблема заключается в том, что мое стандартное использование будет состоять в том, чтобы массивы, содержащие нуль, один или два элемента в них, и накладные расходы ссылочного типа массива в этом сценарии запретительны.

У меня есть эмпирическое наблюдение, и исследование подтвердило, что сама оболочка массива вводит нежелательные (по мне, в этой ситуации) накладные расходы в каждом случае.

Как создать коллекцию Value Type/Struct в .NET?

Боковое примечание: интересно, что язык Swift от Apple по умолчанию имеет массивы как значения.

упреждающего Комментарий

Я полностью осознаю, что выше не является стандартным способом с помощью платформы .NET и очень плохая практика, и т.д ... так что не надо комментировать по этому поводу. Я просто хочу знать, как добиться того, что я прошу.

+0

Вы хотите иметь массивы типов значений внутри своих структур?Или массивы структур без накладных расходов массива? –

+0

@ThomasBoby Первое - это то, что я спрашивал, но он окажется последним, потому что содержимое массива внутри моей структуры - это сами структуры. Попытка сохранить все как структуру, чтобы избежать давления памяти. – Sam

+0

Вы не можете и не хотите. Почему бы каким-то образом создать ограничение по типу массива с ограничением памяти? Я был бы склонен думать об обратном. – InBetween

ответ

1

Ключевое слово fixed, на которое ссылается in the docs, похоже, является тем, что вы ищете. Он имеет те же ограничения для типов, что и структуры, но для этого требуется unsafe.

internal unsafe struct MyBuffer 
{ 
    public fixed char fixedBuffer[128]; 
} 

Если вы хотите иметь фиксированный массив своей структуры, это будет сложнее. fixed поддерживает только базовые типы значений, поэтому вам нужно будет перейти в ручное распределение памяти.

+0

Проблема с таким решением заключается в том, что '128' или любое другое число фиксировано для определения типа. Для поддержки любого короля переменной длины вам необходимо выделить максимальную ожидаемую длину и потратить много памяти. –

+1

@ V.B. Мне кажется, что невозможно создать структуру с динамическим списком длин, фактически размещенным внутри него, без этого. Структура имеет фиксированный размер в памяти, поэтому у вас либо есть массив с фиксированной длиной, либо вы сохраняете указатель на массив динамической длины вне его. Это не проблема с решением, так как эта ситуация не то же самое. –

1

Сочетание идей от DirectBuffer и BufferPool может работать.

Если вы используете буферный пул, то фиксация буферов в памяти не является большой проблемой, потому что буферы становятся эффективно долговечными и не влияют на уплотнение GC, как если бы вы исправляли каждый новый byte[] без пула.

DirectBuffer использует мухи и добавляет очень мало накладных расходов. Вы можете читать/писать любую blittable структуру напрямую с помощью указателей. Насколько я понимаю, кроме SBE, Flatbuffers и Cup'n Proto используют такой подход. В связанной реализации вы должны изменить делегата так, чтобы он возвращал в пул отложенный byte[].

Большим преимуществом такого решения является нуль-копия, если вам нужно взаимодействовать с собственным кодом или отправлять данные по сети. Кроме того, вы можете выделить один буфер и работать с смещениями/длинами в стиле ArraySegment.

Update:

Я перечитал вопрос и понял, что это именно о коллекциях как типы значений. Однако основным обоснованием является давление памяти, поэтому этот ответ может быть альтернативным решением для памяти, хотя DirectBuffer - это класс.

Смежные вопросы