В начале статьи Александра Алексеева "Что плохого в глобальных переменных?" меня зацепила фраза "быстрее в работе". Я хочу поспорить с ней и поддержать Александра в аргументах против глобальных переменных.
Я давно заметил, одну маленькую неприятность с глобальными переменными. Проведем небольшой тест на создание, заполнение и чтение TStringList. Для начала выполним программу, в которой есть процедура с локальными переменными:
Переменные цикла i и j перенесем в процедуру, что бы сделать их локальными переменными:
Я давно заметил, одну маленькую неприятность с глобальными переменными. Проведем небольшой тест на создание, заполнение и чтение TStringList. Для начала выполним программу, в которой есть процедура с локальными переменными:
Результат:program lv; {$APPTYPE CONSOLE} uses System.Classes, System.SysUtils, System.Diagnostics; const ciMaxIndex = 99999999; procedure TestProc; var sl: TStringList; st: String; t : TStopwatch; i, j: Integer; begin t := TStopwatch.StartNew; for j := 1 to 10 do begin sl := TStringList.Create; try for i := 0 to ciMaxIndex do sl.Add(IntToStr(i)); finally sl.Free; end; end; t.Stop; WriteLn('create: ', FormatFloat('0.0', t.ElapsedMilliseconds / 10)); sl := TStringList.Create; try for i := 0 to ciMaxIndex do sl.Add(IntToStr(i)); t := TStopwatch.StartNew; for j := 1 to 10 do for i := 0 to ciMaxIndex do st := sl[i]; t.Stop; WriteLn('get: ', FormatFloat('0.0', t.ElapsedMilliseconds / 10)); finally sl.Free; end; end; begin TestProc; end.
create: 8972,9Теперь та же программа, но процедура в ней работает с использованием только глобальных переменных:
get: 1442,0
Результат:... var sl: TStringList; st: String; t : TStopwatch; i, j: Integer; procedure TestProc; begin ... end;
create: 8979,0Видно, что создание и заполнение TStringList прошло примерно с одинаковой скоростью. А вот чтение при использовании глобальных переменных почти в два раза медленнее!
get: 2710,2
Переменные цикла i и j перенесем в процедуру, что бы сделать их локальными переменными:
Результаты чтение лучше, но не на много:... var sl: TStringList; st: String; t : TStopwatch; procedure TestProc; var i, j: Integer; begin ... end;
create: 8978,9Вывод: глобальные переменные - это палки в колеса производительности программы.
get: 2585,4
Попробуйте оставить Stringlist глобальным, а st сделать локальным и не увидите падения скорости.
ОтветитьУдалитьВаш второй пример тормозит не на извлечении а на записи в глобальную переменную.
Может быть потому, что так вы заставляете не просто перекидывать указатель строки st на одну из строк StringList-а, а заставляете действительно копировать содержимое строки в другую область памяти.
Ваш второй код просто делает другую работу, которая занимает другое время.
Сделать переменную st локальной? Тогда о чем было бы писать? Вы сделаете переменную st локальной, я сделаю переменной st локальной. А Вася Пупкин сделает ее глобальной, как и все остальные переменные, потом весь код запихнет в один "begin-end." и расскажет всем, что его программа тормозит, т.к. ее нужно переписать на более "правильном языке", чем Delphi
ОтветитьУдалить