Wednesday, October 17, 2007

Enumerators, Inlining, methods on records, for-in and deadlocks

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.

3 comments:

  1. That's great, Allen! ;)

    Update: 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

    ReplyDelete
  2. 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?):


    procedure 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? :-)

    ReplyDelete
  3. ...me again. It seems that WordPress ate my < and >.

    It should read close to the end: "with an add ebx < constant >, if 'step < > 1'

    ReplyDelete

Please keep your comments related to the post on which you are commenting. No spam, personal attacks, or general nastiness. I will be watching and will delete comments I find irrelevant, offensive and unnecessary.