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

Какие простые изменения внесли самые большие улучшения в ваши программы Delphi

У меня есть программа Delphi 2009, которая обрабатывает множество данных и должна быть как можно быстрее и не использовать слишком много памяти.

Какие небольшие простые изменения вы внесли в свой код Delphi, который оказал наибольшее влияние на производительность вашей программы, заметно сократив время выполнения или использование памяти?


Спасибо всем за ваши ответы. Много полезных советов.

Для полноты я опубликую несколько важных статей по оптимизации Delphi, которые я нашел.

Перед тем, как начать оптимизацию кода Delphi на странице About.com

Скорость и размер: 10 лучших трюков также на сайте

Основы оптимизации кода и Руководства по оптимизации Delphi в Delphi высокой производительности, относящийся к Delphi 7, но все же очень улокальный.

4b9b3361

Ответ 1

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

Хотя AsyncCalls может сделать намного больше, я нашел его полезным для этой очень простой цели. Скажем, у вас есть подпрограмма, заблокированная следующим образом: Disable Button, Do Work, Enable Button. Вы перемещаете часть "Do Work" в локальную функцию (называете ее AsyncDoWork) и добавляете четыре строки кода:

var  a: IAsyncCall;    
a := LocalAsyncCall(@AsyncDoWork);  
while (NOT a.Finished) do 
  application.ProcessMessages;  
a.Sync;

Для этого вы запускаете AsyncDoWork в отдельном потоке, в то время как ваш основной поток остается доступным для ответа на пользовательский интерфейс (например, перетаскивание окна или нажатие кнопки "Отмена" ). Когда AsyncDoWork завершен, код продолжается. Поскольку я переместил его на локальную функцию, все локальные вары доступны, код не нужно изменять.

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

Я не использую это для написания новых программ. Это просто быстрый и простой способ сделать старые программы более отзывчивыми.

Ответ 2

.BeginUpdate;

.EndUpdate;

;)

Ответ 3

Используйте инструмент профилирования Delphi (некоторые здесь или здесь) и найдите свои собственные шеи бутылки. Оптимизация неправильных узких мест - пустая трата времени. Другими словами, если вы применяете все эти предложения здесь, но игнорируете тот факт, что кто-то положил sleep (1000) (или аналогичный) в какой-то очень важный код, это пустая трата времени. Сначала исправьте свои "узкие места".

Ответ 4

Прекратить использование TStringList для всего.

TStringList - это не универсальная структура данных для эффективного хранения и обработки всего, от простого до сложного. Ищите альтернативы. Я использую Delphi Container and Algorithm Library (DeCAL, ранее известный как SDL). Julians EZDSL также должна быть хорошей альтернативой.

Ответ 5

Предварительное распределение списков и массивов, а не их увеличение с каждой итерацией.

Это, вероятно, оказало наибольшее влияние на меня с точки зрения скорости.

Ответ 6

Если вам нужно использовать Application.processmesssages(или подобное) в цикле, попробуйте называть его только каждую N-ю итерацию.

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

Ответ 7

  • FastMM
  • FastCode (lib)
  • Используйте высокопроизводительные структуры данных, такие как хэш-таблица (и т.д.). Во многих местах быстрее создать один цикл, который делает хэш-таблицу поиска для ваших данных. Использует довольно много памяти, но, безусловно, быстро. (это, возможно, самое важное, но 2 первых мертвы просто и требуют очень мало усилий)

Ответ 8

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

Ответ 9

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

Вы можете посмотреть OmniThread Library by Gabr, но в Delphi есть ряд библиотек потоков. Вы можете легко реализовать свою собственную параллель для использования анонимных типов.

Ответ 10

Прежде чем что-либо сделать, определите медленные части. Не прикасайтесь к рабочему коду, который выполняется достаточно быстро.

Ответ 11

Сделайте интеллектуальное использование SetLength() для строк и массивов. Оптимизируйте инициализацию с помощью FillChar или ZeroMemory.

Локальные переменные, созданные в стеке (например, типы записей), быстрее, чем выделенные кучи (объекты и новые()) переменные.

Повторно используйте объекты, а не Destroy, затем создайте. Но убедитесь, что код управления для этого быстрее, чем диспетчер памяти!

Ответ 12

  • Создание модульных тестов
  • Проверять все тесты
  • Профиль вашего приложения
  • Рефактор ищет узкие места и память
  • Повторите шаг 2 (по сравнению с предыдущим проходом)

Ответ 13

При работе с tstringlist (или аналогичным) установите "sorted: = false" до тех пор, пока не понадобится (если вообще). Кажется, это не проблема...

Ответ 14

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

Ответ 15

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

Это не требует классов, освобождение и доступ к нему происходит очень быстро. Даже если он должен расти, вы можете это сделать - см. Ниже. Используйте только TList или TStringList, если вам нужна гибкость в изменении размера.

type
  TMyRec = record
    SomeString : string;
    SomeValue : double;
  end;

var
  Data : array of TMyRec;
  I : integer;

..begin
  SetLength( Data, 100 ); // defines the length and CLEARS ALL DATA
  Data[32].SomeString := 'Hello';
  ShowMessage( Data[32] );

  // Grow the list by 1 item.
  I := Length( Data );
  SetLength( Data, I+1 );

..end;

Ответ 16

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

Ответ 17

  • Отключить отладку

  • Включить оптимизацию ВКЛ

  • Удалите все ссылки на блоки, которые   вы фактически не используете

  • Ищите утечки памяти

Ответ 18

Используйте множество утверждений для отладки, затем отключите их в транспортном коде.

Ответ 19

Отключите проверку диапазона и переполнения после того, как вы протестировали экстенсивно.

Ответ 20

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

Ответ 21

Для старой разработки BDE, когда я впервые начал Delphi, я использовал множество компонентов TQuery. Кто-то сказал мне использовать TTable master-detail после того, как я объяснил ему, что я делаю, и это заставило программу работать намного быстрее.

Вызов DisableControls может опустить ненужные обновления пользовательского интерфейса.

Ответ 22

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

Ответ 23

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

Ответ 24

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

Ответ 25

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

Ответ 26

Рассмотрим, действительно ли база данных СУБД является идеальным выбором. Если вы только читаете данные и никогда не меняете их, то фиксированный фиксированный файл записи может работать быстрее, особенно если путь к данным можно легко сопоставить (т.е. Один индекс). Тривиальный двоичный поиск по фиксированному файлу записи по-прежнему чрезвычайно быстрый.

Ответ 27

  • BeginUpdate... EndUpdate
  • ShortString vs. String
  • Используйте массивы вместо TStrings и TList

Но грустный ответ заключается в том, что настройка и оптимизация позволят вам улучшить 10% (и это опасно); перепроектирование может дать вам 90%. Когда вы действительно понимаете цель, вы часто можете переформулировать проблему (и, следовательно, решение) в гораздо более выгодных условиях.

Приветствия

Ответ 28

Изучите все петли и найдите способы короткого замыкания. Если вы ищете что-то конкретное и находите его в цикле, используйте команду BREAK для немедленного освобождения под залог... нет смысла зацикливаться на остальных. Если вы знаете, что у вас нет соответствия, используйте как можно скорее CONTINUE.

Ответ 29

Воспользуйтесь некоторыми кодом проекта FastCode. Части его были включены в VCL/RTL (например, FastMM был), но там больше вы можете использовать!

Обратите внимание, что у них есть новый сайт, они тоже перемещаются, но, похоже, он немного неактивен.

Ответ 30

Возможно, воспользуйтесь VCL FixPack Andreas Hausladen

VCL Fix Pack - это модуль Delphi, который исправляет ошибки VCL и RTL во время выполнения исправление исходных функций. Если вы хотите, чтобы все исправления пакета IDE Fix Pack ваше приложение - это то, что вы необходимость. Добавление устройства в проект (Delphi и С++ Builder) автоматически устанавливает патчи, которые доступны для версии Delphi/С++ Builder.