The ever-present, over-achieving Hallvard Vassbotn has just posted an excellent analysis of how the Delphi compiler generates code for the "for-in" statement. He also presented many suggestions on how to make this as efficient as possible. I will be taking his suggestions back to the team to get folded into the next release. You should also be sure to read Primoz Gabrijelcic's blog posts on writing enumerators.
I noticed that I haven't gotten any "bites" on my challenge to spot the deadlock... Since returning to the office after my trip to Kona, HI, I've been working on several things not related to multi-core, thread-pooling, paralleling, etc... Mostly surrounding the next Delphi/C++Builder release. I'll come back to threading soon.
That's great, Allen! ;)
ReplyDeleteUpdate: I have now taken the time to report these issues and suggestions in Quality Central. Note: I think my the QC report ended up as a Beta report and may thus not be publically viewable.
QC#53623 - Function calls inside while expressions are not inlined
QC#53737 - For-in codegen: Enumerator MoveNext calls are not inlined
QC#53738 - Change all RTL and VCL enumerators from class to record
QC#53739 - Inline GetCurrent and MoveNext in all RTL and VCL enumerators
Yes, Hallvard is nice as always. But what stumbles me, is that no one presented a comparative benchmark with the for..to structure. For ex. (how to preserve indentation in this blog engine?):
ReplyDeleteprocedure TForm4.Button1Click(Sender: TObject);
const
MAX_COUNT = 1000000;
var
i: Integer;
t: cardinal;
lTemp: TStringList;
cCrt, cResult: string;
begin
lTemp:=TStringList.Create;
t:=GetTickCount;
for i := 0 to MAX_COUNT do
lTemp.Add('CodeGear Delphi Benchmark');
t:=GetTickCount-t;
ShowMessage('Filling the list done in '+IntToStr(t)+' msecs');
//------------------- Test #1. for..to loop
t:=GetTickCount;
for i := 0 to MAX_COUNT do
cResult:=AnsiUpperCase(lTemp[i]);
t:=GetTickCount-t;
ShowMessage('Test done in '+IntToStr(t)+' msecs. Result: '+cResult);
//------------------- Test #2. for..in loop
t:=GetTickCount;
for cCrt in lTemp do
cResult:=AnsiUpperCase(cCrt);
t:=GetTickCount-t;
ShowMessage('Test done in '+IntToStr(t)+' msecs. Result: '+cResult);
lTemp.Free;
end;
...which shows that for..to is faster. But it would a nice comparison with all the optimizations which Hallward proposed. While I acknowledge that for..in has its virtues, did you consider to implement the QC #33772? (the for..to..step - imho, it should be simple - if you'll look at the asm code is just an inc ebx (now) and this should be replaced AFAIS with an add ebx, if 'step1'), also speaking about 'for' cycles and QC perhaps when you're 'on it', consider also the QC#49588 - imho, it will help (sometimes a lot) in quality of source code.
(Sorry for the 'deadlock challenge' - no time, no ability, no... ;-) )
Btw, what do you mean 'Mostly surrounding the next Delphi/C++Builder release.'? Any details? :-)
...me again. It seems that WordPress ate my < and >.
ReplyDeleteIt should read close to the end: "with an add ebx < constant >, if 'step < > 1'