2017-02-17 27 views
0

Я читал о том, как коллекции, такие как встроенные массивы и списки, отличаются друг от друга и замечают, что встроенные массивы намного быстрее, чем списки (в определенных ситуациях в 7 раз быстрее).Самая быстрая коллекция для оптимизации в Unity3D?

Итак, мой вопрос: Если я использую встроенные массивы, которые я не заполняю полностью, но вместо этого имею максимальное значение и использую счетчик int для отслеживания размера, будет ли он значительно быстрее, чем использование списков?

Причина в том, что у меня есть многопользовательская игра, в которой я создал сервер для себя в Node.js с нуля, и использую websockets-sharp как библиотеку для клиента, и вижу некоторые задержки из-за для коллекций, которые я должен модифицировать и проверять мои функции обновления (используя списки, стеки, словарь и очереди), и интересно, что массив byte [] увеличит производительность.

P.S. Вот где я получил информацию от примерно построен в производительности массива против System.Collections:

http://answers.unity3d.com/questions/38479/is-listt-as-fast-to-access-as-a-standard-array.html

Performance differences... so dramatic?

http://wiki.unity3d.com/index.php/Choosing_the_right_collection_type

+0

Полностью зависит от того, как приложение добавляет и извлекает данные. Напишите один раз? Только для чтения? Случайный доступ? Добавить только? Случайная вставка? – MickyD

+0

Я бы использовал встроенный массив таким же образом, что использовал бы списки, которые в настоящее время включают в себя цикл, изменяя его содержимое с добавлением и удалением элементов. –

+0

Я хочу ответить на это, но вам нужно больше деталей. На ваш вопрос о словаре Vs List, как вы планируете использовать их? В другом случае использование имеет значение для сравнения двух. – Programmer

ответ

3

Если я использую встроенный в массивах, которые не заполняют полностью, но вместо того, чтобы иметь максимальное значение, и использовать счетчик Int для отслеживания размера, это будет значительно быстрее, чем при использовании списков?

Да.

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

Я как-то сделал приложение, которое передает изображение HQ через сеть. Это было легко сделать с List, но после того, как я перешел на Array, количество кадров, полученных мной в секунду, увеличилось.Он также получил возможность распределения памяти.

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

Юнить blog также имеет пост, который показывает производительность различной между использованием Array и List для улучшения функции Update(). Это действительно большое увеличение производительности, а массив составляет около 5x быстрее, чем List в этом эксперименте.

Эти правила, которые я поставил перед собой при работе Unity и еще remians, чтобы быть правдой, даже сегодня:

Если вам нужно хранить большие предметы (200к и выше), что требует вам проходное их каждый кадр, использовать массив и простое значение int, которое вы можете использовать для определения длины массива.

.Если это только детали о размере и работает только один раз в то время, а затем использовать List.

Я изменил код this для запуска в Unity и ниже - результат.

Array/для: 6726ms (-1295415896)

Список/для: 15803ms (-1295415896)

Array/Еогеасп: 8511ms (-1295415896)

Список/Еогеасп: 42689ms (-1295415896)

Разница очень важна в Unity, в отличие от обычного приложения C#.

void Start() 
{ 
    List<int> list = new List<int>(6000000); 
    for (int i = 0; i < 6000000; i++) 
    { 
     list.Add(UnityEngine.Random.Range(1, 10)); 
    } 
    int[] arr = list.ToArray(); 

    int chk = 0; 
    Stopwatch watch = Stopwatch.StartNew(); 
    for (int rpt = 0; rpt < 100; rpt++) 
    { 
     int len = list.Count; 
     for (int i = 0; i < len; i++) 
     { 
      chk += list[i]; 
     } 
    } 
    watch.Stop(); 
    UnityEngine.Debug.Log(String.Format("List/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk)); 

    chk = 0; 
    watch = Stopwatch.StartNew(); 
    for (int rpt = 0; rpt < 100; rpt++) 
    { 
     int len = arr.Length; 
     for (int i = 0; i < len; i++) 
     { 
      chk += arr[i]; 
     } 
    } 
    watch.Stop(); 
    UnityEngine.Debug.Log(String.Format("Array/for: {0}ms ({1})", watch.ElapsedMilliseconds, chk)); 

    chk = 0; 
    watch = Stopwatch.StartNew(); 
    for (int rpt = 0; rpt < 100; rpt++) 
    { 
     foreach (int i in list) 
     { 
      chk += i; 
     } 
    } 
    watch.Stop(); 
    UnityEngine.Debug.Log(String.Format("List/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk)); 

    chk = 0; 
    watch = Stopwatch.StartNew(); 
    for (int rpt = 0; rpt < 100; rpt++) 
    { 
     foreach (int i in arr) 
     { 
      chk += i; 
     } 
    } 
    watch.Stop(); 
    UnityEngine.Debug.Log(String.Format("Array/foreach: {0}ms ({1})", watch.ElapsedMilliseconds, chk)); 
} 
+1

Боковое примечание: «Он также избавился от распределения памяти», вероятно, фактическая причина того, что ваш реальный код будет намного быстрее (поскольку даже разница в стоимости доступа, вероятно, утопится в стоимости обработки каждого элемента) ... И есть нет причин, по которым вы не могли получить аналогичные преимущества, просто повторно используя предварительно выделенный список с помощью «List.Clear» ... –

+0

@AlexeiLevenkov Да, я повторно использовал «Список», а также использовал «List.Clear()» тоже , Иногда добавление в список иногда выделяет память. Доступ к его ценности невозможен. Он выделяет, пока размер списка больше, чем размер изображения, которое я отправлял. Проблема в том, что размер моего изображения всегда меняется. – Programmer

+0

Иногда размер изображения увеличивается, иногда он падает, и это приводит к тому, что «List» выделяет некоторое время. В какой-то момент это останавливается, но разница в производительности всегда присутствует даже после того, как она прекращает выделение памяти. Я знаю, что я могу указать размер «List» при создании, чтобы остановить выделенную часть, но если вам нужно указать размер вовремя, то почему бы не использовать 'Array'? Кроме того, пожалуйста, взгляните на блог Unity, который я связал в ответе, который показывает разницу в производительности «Array' vs« List ». – Programmer

2

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

Это говорит о том, что теперь вам нужно сделать больше, если вы собираетесь делать что-то из списка, а массивы - нет. Если вы делаете это не так эффективно, как код в списке, вы просто будете делать что-то медленнее. Даже если все сделано отлично, вы можете, например, не сможет иметь код, который позволяет дрожанию пропускать проверку границ (потому что вы оставляете некоторое пространство в конце массива, например), что означает, что реальная производительность не будет такой хорошей, как контрольная точка, в которой может произойти дрожание что).

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

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