W wątku:
Błąd 'Type mismatch' przy ustalaniu długości tablicy
Mieliśmy z @furious programming odmienne zdanie co do łączenie napisów.
Nie znalazłem swoich starych testów więc napisałem nowe:
SpeedComparatorMain.lfm:
object ASpeedComparator: TASpeedComparator
Left = 382
Height = 112
Top = 208
Width = 281
Caption = 'Speed comparator ...'
ClientHeight = 112
ClientWidth = 281
OnCloseQuery = FormCloseQuery
LCLVersion = '1.4.4.0'
object TopPanel: TPanel
Left = 0
Height = 56
Top = 0
Width = 281
Align = alTop
BevelInner = bvSpace
BevelOuter = bvNone
BevelWidth = 4
ClientHeight = 56
ClientWidth = 281
TabOrder = 0
object GConcat: TGroupBox
Left = 4
Height = 48
Top = 4
Width = 119
Align = alLeft
Caption = 'Concat'
ClientHeight = 30
ClientWidth = 115
TabOrder = 0
object CConcat: TLabel
Left = 0
Height = 30
Top = 0
Width = 115
Align = alClient
Alignment = taRightJustify
Caption = '0'
Font.Color = clNavy
Font.Height = -19
Layout = tlCenter
ParentColor = False
ParentFont = False
end
end
object GOperator: TGroupBox
Left = 158
Height = 48
Top = 4
Width = 119
Align = alRight
Caption = 'Operator'
ClientHeight = 30
ClientWidth = 115
TabOrder = 1
object COperator: TLabel
Left = 0
Height = 30
Top = 0
Width = 115
Align = alClient
Alignment = taRightJustify
Caption = '0'
Font.Color = clNavy
Font.Height = -19
Layout = tlCenter
ParentColor = False
ParentFont = False
end
end
end
object BtnStart: TButton
Left = 105
Height = 25
Top = 80
Width = 75
Caption = 'Start'
OnClick = BtnStartClick
TabOrder = 1
end
end
SpeedComparatorMain.pas:
unit SpeedComparatorMain;
{$mode objfpc}{$H+}
interface uses
Classes,
SysUtils,
FileUtil,
Forms,
Controls,
Graphics,
Dialogs,
StdCtrls,
ExtCtrls,
SyncObjs;
type
PThreadRecord=^TThreadRecord;
TThreadRecord=record
Th:TThread;
Count:Cardinal;
Info:TLabel;
Func:TNotifyEvent;
Cs:TCriticalSection;
Work:Boolean;
end;
TCompareThread=class(TThread)
private
Data:PThreadRecord;
protected
procedure Execute;override;
public
constructor Create(AData:PThreadRecord);
end;
{ TASpeedComparator }
TASpeedComparator = class(TForm)
BtnStart: TButton;
CConcat: TLabel;
COperator: TLabel;
GConcat: TGroupBox;
GOperator: TGroupBox;
TopPanel: TPanel;
procedure BtnStartClick(Sender:TObject);
procedure FormCloseQuery(Sender:TObject;var CanClose:Boolean);
private
ThList:array[0..1]of TThreadRecord;
Cs:TCriticalSection;
procedure NeedString(const S:String);
procedure OnConcat(Sender:TObject);
procedure OnOperator(Sender:TObject);
public
constructor Create(AOwner:TComponent);override;
destructor Destroy;override;
end;
var ASpeedComparator:TASpeedComparator;
const MakeSize:Integer=1000;
const TestCount:Integer=1000;
implementation
{$R *.lfm}
{ TCompareThread }
constructor TCompareThread.Create(AData:PThreadRecord);
begin
Data:=AData;
inherited Create(true);
FreeOnTerminate:=true;
end;
procedure TCompareThread.Execute;
begin
Data^.Work:=true;
while not Terminated do
begin
Data^.Func(Self);
Inc(Data^.Count);
Data^.Cs.Enter;
try
Data^.Info.Caption:=IntToStr(Data^.Count);
finally
Data^.Cs.Leave;
end;
end;
Data^.Work:=false;
end;
{ TASpeedComparator }
constructor TASpeedComparator.Create(AOwner:TComponent);
begin
inherited Create(AOwner);
Cs:=TCriticalSection.Create;
ThList[0].Cs:=Cs;
ThList[0].Info:=CConcat;
ThList[0].Func:=@OnConcat;
ThList[0].Th:=TCompareThread.Create(@ThList[0]);
ThList[1].Cs:=Cs;
ThList[1].Info:=COperator;
ThList[1].Func:=@OnOperator;
ThList[1].Th:=TCompareThread.Create(@ThList[1]);
end;
destructor TASpeedComparator.Destroy;
begin
Cs.Free;
inherited Destroy;
end;
procedure TASpeedComparator.NeedString(const S:String);
begin
if Length(S)<0 then Application.Terminate;
end;
procedure TASpeedComparator.OnConcat(Sender:TObject);
var T,I:Integer;
var S:String;
begin
for T:=1 to TestCount do
begin
SetLength(S,0);
for I:=1 to MakeSize do S:=Concat(S,' ',IntToStr(I),#13#10);
//for I:=1 to MakeSize do S:=Concat(S,IntToStr(I),#13#10);
NeedString(S); // Aby optymalizator nie wyciął w pień tą zmienną S
end;
end;
procedure TASpeedComparator.OnOperator(Sender:TObject);
var T,I:Integer;
var S:String;
begin
for T:=1 to TestCount do
begin
SetLength(S,0);
//for I:=1 to MakeSize do S:=S+' '+IntToStr(I)+#13#10;
for I:=1 to MakeSize do S:=S+IntToStr(I)+#13#10;
NeedString(S); // Aby optymalizator nie wyciął w pień tą zmienną S
end;
end;
procedure TASpeedComparator.BtnStartClick(Sender: TObject);
var I:Integer;
begin
for I:=Low(ThList) to High(ThList) do ThList[I].Th.Start();
end;
procedure TASpeedComparator.FormCloseQuery(Sender:TObject;var CanClose:Boolean);
var I:Integer;
begin
CanClose:=true;
for I:=Low(ThList) to High(ThList) do ThList[I].Th.Terminate;
for I:=Low(ThList) to High(ThList) do while ThList[I].Work do Application.ProcessMessages;
end;
end.
W załączniku razem z projektem.
Na podstawie kodu z satysfakcją stwierdziłem że miałem racje ponieważ program pokazuje że nawet: S:=Concat(S,' ',IntToStr(I),#13#10);
jest szybsze od: S:=S+IntToStr(I)+#13#10;
Z tym że na wszelki wypadek postanowiłem sprawdzić inną sytuacje ... jestem zaskoczony faktem że: S:=S+' '+IntToStr(I)+#13#10;
jest szybsze od: S:=Concat(S,IntToStr(I),#13#10);
Czyli dowalamy składnik i mamy szybszy program?
WTF?
Sprawdzałem pod: