Подтвердить что ты не робот

Списки обобщений и массивов

Система, над которой я работаю, была написана до .net 2.0 и не имела преимуществ от генериков. Он был в конечном итоге обновлен до 2.0, но ни один из кода не был реорганизован из-за ограничений по времени. Существует множество мест, где код использует ArraysLists и т.д., Которые хранят объекты как объекты.

С точки зрения производительности, насколько важно изменить код на использование дженериков? Я знаю с точки зрения производительности, бокса и распаковки и т.д., Он неэффективен, но сколько из прироста производительности действительно будет от его изменения? Получают ли дженерики что-то, что нужно использовать в будущем, или это достаточно для изменения производительности, которое необходимо предпринять для обновления старого кода?

4b9b3361

Ответ 1

Технически производительность дженериков, как вы говорите, лучше. Однако, если производительность не очень важна, и вы уже оптимизированы в других областях, вы, вероятно, получите МНОГО БОЛЬШЕ улучшений, потратив свое время в другом месте.

Я бы предложил:

  • использовать генерические файлы в будущем.
  • если у вас есть надежные модульные тесты, а затем рефакторинг для дженериков при касании кода
  • тратить другое время на рефакторинг/измерение, которое значительно улучшит производительность (вызовы базы данных, изменение структуры данных и т.д.), а не несколько миллисекунд здесь и там.

Конечно, есть причины, отличные от производительности, для изменения дженериков:

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

Ответ 2

Здесь результаты, полученные из простого анализа строки из 100 КБ файла 100 000 раз. Общий список (char) занял 612,293 секунды, чтобы пройти 100 000 раз через файл. ArrayList потратил 2 880,415 секунд, чтобы пройти 100 000 раз через файл. Это означает, что в этом случае (поскольку ваш пробег будет отличаться) общий список (char) будет в 4,7 раза быстрее.

Вот код, который я пропустил через 100 000 раз:

Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run
    Dim genList As New ArrayList

    For Each ch As Char In strToProcess.ToCharArray
        genList.Add(ch)
    Next

    Dim dummy As New System.Text.StringBuilder()
    For i As Integer = 0 To genList.Count - 1
        dummy.Append(genList(i))
    Next

End Sub

 Public Sub Run(ByVal strToProcess As String) Implements IPerfStub.Run
     Dim genList As New List(Of Char)

     For Each ch As Char In strToProcess.ToCharArray
         genList.Add(ch)
     Next

     Dim dummy As New System.Text.StringBuilder()
     For i As Integer = 0 To genList.Count - 1
         dummy.Append(genList(i))
     Next
 End Sub

Ответ 3

Единственный способ узнать наверняка - профилировать свой код с помощью инструмента, такого как dotTrace.

http://www.jetbrains.com/profiler/

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

Ответ 4

Обобщение, будь то Java или .NET, должно использоваться для проектирования и безопасности типов, а не для производительности. Автобоксинг отличается от дженериков (по сути, неявным объектом для примитивных преобразований), и, как вы упомянули, вы НЕ должны использовать их вместо примитива, если есть много арифметических или других операций, которые могут привести к поражению производительности от повторного неявное создание/уничтожение объекта.

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

Ответ 5

Это зависит, лучший ответ - прокомментировать ваш код и посмотреть. Мне нравится AQTime, но для этого существует несколько пакетов.

В общем случае, если ArrayList используется LOT, возможно, стоит переключить его на общую версию. На самом деле, скорее всего, вы даже не сможете измерить разницу в производительности. Бокс и распаковка - это дополнительные шаги, но современные компьютеры настолько быстры, что практически не отличаются. Поскольку ArrayList на самом деле является просто обычным массивом с красивой оболочкой, вы, вероятно, увидите гораздо большую производительность, полученную в результате лучшего выбора структуры данных (ArrayList.Remove - O (n)!), Чем при преобразовании в generics.

Изменить: у программиста Outlaw есть хороший момент, вы все равно будете боксировать и распаковывать с помощью дженериков, это просто происходит неявно. Весь код, связанный с проверкой исключений и нулей от кастингов и ключевых слов "is/as", поможет немного.

Ответ 6

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

Ответ 7

Что подразумевает использование автобоксинга/распаковки? Это вопрос безопасности. При использовании не общего набора вам необходимо явно вернуть обратно фактический тип объекта. С помощью дженериков вы можете пропустить этот шаг. Я не думаю, что есть разница в производительности так или иначе.

Ответ 8

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

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

Ответ 9

Зависит от того, сколько там в вашем коде. Если вы привязываете или показываете большие списки в пользовательском интерфейсе, вы, вероятно, увидите большой прирост производительности.

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

Если вы используете много ArrayLists во всем своем коде, и было бы очень сложно их заменить (что может повлиять на ваши графики), тогда вы можете принять подход if-you-touch-it-change-it.

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

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

Ответ 10

Если объекты в массивах ArrayLists являются типами объектов, вы получите немного от того, чтобы не отнести их к правильному типу. Если они представляют собой типы значений (структуры или примитивы, такие как Int32), то процесс бокса/распаковки добавляет много накладных расходов, а общие коллекции должны быть намного быстрее.

Здесь статья MSDN по этому вопросу

Ответ 11

Generics имеет гораздо лучшую производительность, особенно если вы будете использовать value-type (int, bool, struct и т.д.), где вы получите заметное увеличение производительности.

  • Использование Arraylist со значениями типов вызывает бокс /unboxing, который, если сделано несколько сотен раз, значительно медленнее, чем использование общего списка.

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

Я писал о здесь.

Ответ 12

Использование generics также должно означать, что ваш код будет более простым и простым в использовании, если вы хотите использовать такие вещи, как linq в более поздних версиях С#.