У меня есть два предложения:
Во-первых, как насчет использования Reflector или ILSpy для просмотра Generic List<T>
?Я предполагаю, что реализация не в CF или вы могли бы использовать его.Generic List<T>
поддерживает массив и использует алгоритм удвоения, начиная с массива длиной 4, каждый вызов .Add over Capacity заставляет его удваиваться и выполнять Array.Copy в новый массив.Размер не изменится, если вы явно не установите Capacity на ноль, так что будьте осторожны с точки зрения памяти.Добавление - это одно, но каждое удаление приведет к тому, что массив будет скопирован и смещен влево после удаления индекса.
Второе предложение заключается в следующем: как насчет создания пользовательского класса, который для этого обрабатывает целочисленный массив, который использует аналогичный двойной алгоритм (или четырехкратное увеличение) для Generic List<T>
(для обработки изменения размера), но начинается сскажем, размер 256. Вы можете добавить целочисленные идентификаторы объекта к этому из последовательности так быстро, как вам нравится, и это не будет удваиваться слишком часто.Вы также можете смоделировать удаление, указав (int) -1 или uint.MaxValue как «нулевой индекс», означающий отсутствие Array.Copy при удалении.Затем примените некую быструю сортировку для каждого кадра, чтобы отсортировать массив индекса объекта перед рисованием.Если вы сортируете по возрастанию, все ваши -1 появятся в начале (или uint.MaxValues в конце) и могут быть проигнорированы.Вы можете периодически «собирать» индексный массив, изменяя размеры и удаляя предыдущие -1
в отдельном потоке (будьте осторожны - используйте блокировку;)
Что вы думаете?Просто подумав, что вы будете компенсировать некоторые вычисления один раз за кадр для быстрой сортировки (не дорого на xbox, по сравнению с выделением / сбором памяти при каждом удалении и некоторых добавлениях (дорого).
UPDATE - BlockArray - Listгде T - массив фиксированного размера
Еще один комментарий по этому поводу.Недавно я экспериментировал с наиболее эффективной структурой данных для динамически изменяемых списков и экспериментально обнаружил, что блоки массивов - это класс, который поддерживается списком T [], где каждый T [] был массивом блока фиксированного размера, например512, 4096, 8192 как несколько преимуществ над простым списком .
Я обнаружил, что реализация Add () (где размер неизвестен) в спискезначительно превосходил Add () для List , особенно когда общий размер стал больше.Это связано с алгоритмом удвоения List , который запрашивает новый массив в 2 раза больше старого, а memcpy - старым массивом при превышении размера.
Скорость итерации аналогична.Предварительное выделение (предварительно определенная емкость) было намного медленнее, чем List для небольших блоков (512), но лишь немного медленнее для больших блоков (8192).Удаление проблематично, так как требует копирования / сдвига влево многих блоков.
Что интересно в списке(список блоков), вы можете кэшировать / объединять блоки.Если достаточно малы, блоки T [] помещаются в кучу небольших объектов (в пользу сжатия, более быстрого выделения), могут помещаться в кэш L2, и несколько блоков могут быть предварительно выделены и объединены в пул