Optimization?..

Issue #55 resolved
Алексей © created an issue

Hi!

I was searching a script engine for a little program. At a time I was found DWS2 (2.3). Looked in some source and got... confused. Is all dws so well optimized as thing below?..

DWS: 1732 EZ: 94

18 times slower in so easy function!

program dws_speed;

{$APPTYPE CONSOLE}

uses
  Windows;

// code from TSetLengthFunc.DoEvalProc from unit dwsStringFunctions
procedure DWSSetLength(var s: string; n: Integer);
var
  i: integer;
begin
   i:=Length(s)+1;
   SetLength(s, n);
   while i<=n do begin
      s[i]:=' ';
      Inc(i);
   end;
end;

// analog from scratch
procedure EZSetLength(var s: string; n: Integer);
var
  i: integer;
begin
   i:=Length(s);
   SetLength(s, n);
   if n > i then
     FillChar(s[i], (n-i) * SizeOf(Char), #0);
end;

var
  Tick: Cardinal;
  Idx: Integer;
  s: string;
begin
  repeat
    Tick := GetTickCount;
    for Idx := 0 to 500000 do begin
      DWSSetLength(s, 1000);
      DWSSetLength(s, 300);
      DWSSetLength(s, 500);
      DWSSetLength(s, 0);
    end;
    WriteLn('DWS: ', GetTickCount - Tick);
    Tick := GetTickCount;
    for Idx := 0 to 500000 do begin
      EZSetLength(s, 1000);
      EZSetLength(s, 300);
      EZSetLength(s, 500);
      EZSetLength(s, 0);
    end;
    WriteLn('EZ:  ', GetTickCount - Tick);
  until False;
end.

Comments (5)

  1. Eric Grange repo owner

    Your EZSetLength code just crashes here (try with range checking)

    Also you are setting the empty characters to #0, not to space, and you cannot use FillChar to achieve that with utf-16.

    DWScript deviates from Delphi in that it mandates for all variables and states to be well defined at all times, in the case of String SetLength the convention is to fill the extra characters with whitespace. Leaving existing bytes untouched would be a security risk (it leaks whatever data was previously placed at that memory), so it was not an option. And #0 confused users, and also confuses OLE/COM and other C-based applications that take #0 as a string terminator, so white space was chosen.

    This is one case were predictability and security took over raw performance.

  2. Алексей © reporter

    Even

    procedure EZSetLength(var s: string; n: Integer);
    var
      i: integer;
    begin
       i:=Length(s);
       if n > i then
        s := s + StringOfChar(#32, n-i)
       else SetLength(s, n);
    end;
    

    still 6 times faster (XE, 32 bit) and not less secure.

    P.S: The joke is in the source of "StringOfChar" procedure.

  3. Eric Grange repo owner

    Ok, that was the implicit UniqueString

    However this is quite peripheral, that SetLength method is pretty much an edge case, as working on strings character by character is currently not very efficient in scripts, and it is mostly there for legacy & compatibility.

  4. Log in to comment