В начале статьи Александра Алексеева "Что плохого в глобальных переменных?" меня зацепила фраза "быстрее в работе". Я хочу поспорить с ней и поддержать Александра в аргументах против глобальных переменных.
Я давно заметил, одну маленькую неприятность с глобальными переменными. Проведем небольшой тест на создание, заполнение и чтение 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
ОтветитьУдалить