1 如果有大量的循环,那么尽量减少循环中调用函数,而是把函数结果记录下来,然后在循环中直接使用。
比如下面第一个函数 ShowMemoResult 在循环中多次调用 GetFieldSize 函数
第二个函数 ShowMemoResult1 则声明一个数组,在数组中记录了字段的长度,循环中使用这个数组,而不是调用这个函数
function GetFieldSize(AField: TDataField): Integer;
begin
case AField.DataType of
TFieldType.ftBoolean:
Result := 20;
TFieldType.ftDate, TFieldType.ftDateTime, TFieldType.ftTime:
Result := 20;
TFieldType.ftInteger, TFieldType.ftLargeint, TFieldType.ftSmallint:
Result := 20;
TFieldType.ftFloat:
Result := 20;
else
Result := AField.Size;
end;
if Result<Length(AField.FieldName) then Result := Length(AField.FieldName);
end;
procedure TMainForm.ShowMemoResult(ADataSet: TClientDataSet);
var
i: Integer;
s: String;
sValue: String;
begin
memResult.Lines.BeginUpdate;
try
memResult.Clear;
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
sValue := ADataSet.Fields.FieldName;
sValue := sValue+StrUtils.DupeString(' ', GetFieldSize(ADataSet.Fields)-Length(sValue));
s := s+sValue+' ';
end;
memResult.Lines.Add(s);
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
sValue := StrUtils.DupeString('-', GetFieldSize(ADataSet.Fields));
s := s+sValue+' ';
end;
memResult.Lines.Add(s);
ADataSet.First;
while not ADataSet.Eof do
begin
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
sValue := ADataSet.Fields.AsString;
sValue := sValue+StrUtils.DupeString(' ', GetFieldSize(ADataSet.Fields)-Length(sValue));
s := s+ sValue +' ';
end;
memResult.Lines.Add(s);
ADataSet.Next;
end;
memResult.Lines.Add('--------------------');
memResult.Lines.Add(SysUtils.IntToStr(ADataSet.RecordCount)+' Results');
finally
memResult.Lines.EndUpdate;
end;
end;
procedure TMainForm.ShowMemoResult1(ADataSet: TClientDataSet);
var
i: Integer;
s: String;
sValue: String;
lSize: array of Integer;
begin
memResult.Lines.BeginUpdate;
try
memResult.Clear;
SetLength(lSize, ADataSet.FieldCount);
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
lSize := GetFieldSize(ADataSet.Fields);
sValue := ADataSet.Fields.FieldName;
sValue := sValue+StrUtils.DupeString(' ', lSize-Length(sValue));
s := s+sValue+' ';
end;
memResult.Lines.Add(s);
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
sValue := StrUtils.DupeString('-', lSize);
s := s+sValue+' ';
end;
memResult.Lines.Add(s);
ADataSet.First;
while not ADataSet.Eof do
begin
s := '';
for i:=0 to ADataSet.FieldCount-1 do
begin
sValue := ADataSet.Fields.AsString;
sValue := sValue+StrUtils.DupeString(' ', lSize-Length(sValue));
s := s+ sValue +' ';
end;
memResult.Lines.Add(s);
ADataSet.Next;
end;
memResult.Lines.Add('--------------------');
memResult.Lines.Add(SysUtils.IntToStr(ADataSet.RecordCount)+' Results');
finally
SetLength(lSize, 0);
memResult.Lines.EndUpdate;
end;
end;
procedure TMainForm.actSpeedTestExecute(Sender: TObject);
var
lStart, lEnd: Integer;
begin
Query1.Open;
lStart := Borland.Delphi.Windows.GetTickCount;
ShowMemoResult(TClientDataSet(Query1));
lEnd := Borland.Delphi.Windows.GetTickCount;
Caption := SysUtils.IntToStr(lEnd-lStart);
lStart := Borland.Delphi.Windows.GetTickCount;
ShowMemoResult1(TClientDataSet(Query1));
lEnd := Borland.Delphi.Windows.GetTickCount;
Caption := '1:'+Caption +' 2:'+ SysUtils.IntToStr(lEnd-lStart);
end;
这里要注意不同的数据量下,两个函数的性能不一样的
585条记录时候
第一个函数用时 2000毫秒 第二个函数用时 3400毫秒
2829条记录时候
第一个函数用时 5500毫秒 第二个函数用时 1800毫秒
9717条记录时候
第一个函数出错Heap error 第二个函数用时 121000毫秒
因为结果都输出到Memo中,因此当数据量太大时候会出错,如果不输出Memo也可以出结果,但是肯定比第二个函数性能要差很多 |