Deserialization Optimization - uROTypes.FindROClass

RemObjects SDK for Delphi
Version: 8.3.93.1183

uROTypes.FindROClass implements a linear search over all registered TROComplexType classes. It is invoked by TROStreamSerializer at deserialization for every TROComplexType descendant.

For small messages and few registered TROComplexType classes this may be adequate.

In our project there are more than 600 registered TROComplexTypes, and we have messages with arrays containing thousands of TROComplexType descendants.

In this case, the linear search in FindROClass is inadequate. We patched it and replaced it with a hashtable based implementation.

Result of a test (640 registered TROComplexType classes, deserialization of ~7000 TROComplexType descendants):

  • Without optimization: 100% serialization execution time
  • With optimization: 65% serialization execution time

We would be glad to see a similar improvement in the original RemObjects SDK code base.

1 Like

Thanks, logged as bugs://76477

can you upload your testcase that shows that uROTypes.FindROClass isn’t optimized, pls?
as I see, we use standard TStringList.IndexOf that uses quicksort

From RemObject SDK 8.3.93.1183, uROTypes.pas:

var
  _ComplexTypes : TList{$IFDEF NEXTGEN}<TROComplexTypeClass>{$ENDIF};
//...
function FindROClass(const aClassName: string): TROComplexTypeClass;
var
  i: Integer;
begin
  Result := nil;
  for i := 0 to (_ComplexTypes.Count-1) do begin
    if (CompareText(TClass(_ComplexTypes.Items[i]).ClassName, aClassName)=0) then begin
      Result := TROComplexTypeClass(_ComplexTypes.Items[I]);
      Break;
    end;
  end;
end;

From RemObjects 9.0.97.1245, uROTypes.pas:

    var
      _ComplexTypes : TList{$IFDEF NEXTGEN}<TROComplexTypeClass>{$ENDIF};
    //...
    function FindROClass(const aClassName: string): TROComplexTypeClass;
    var
      i: Integer;
    begin
      for i := 0 to (_ComplexTypes.Count-1) do begin
        if (CompareText(TClass(_ComplexTypes.Items[i]).ClassName, aClassName)=0) then begin
          Result := TROComplexTypeClass(_ComplexTypes.Items[I]);
          Exit;
        end;
      end;
      {$IFDEF RO_RTTI_Support}
      Result := RORTTI_FindROClass(aClassName)
      {$ELSE}
      Result := nil;
      {$ENDIF}
    end;

this method was updated after 9.0.97.1245:

    for i := 0 to _ComplexTypes_new.Count-1 do begin
      if list1.IndexOf(_ComplexTypes_new[i]) <> -1 then Continue; // already processed
      //_TMyComplexList = {$IFDEF NEXTGEN}TDictionary<String,TROComplexTypeClass>{$ELSE}TStringList{$ENDIF};
      List := _TMyComplexList(_ComplexTypes_new.Objects[i]);
      {$IFDEF NEXTGEN}
      if List.ContainsKey(aClassName) then begin
        Result := List.Items[aClassName];
        Exit;
      end;
      {$ELSE}
      j := List.IndexOf(aClassName);
      if j <> -1 then begin
        Result := TROComplexTypeClass(List.Objects[j]);
        Exit;
      end;
      {$ENDIF}
    end;

bugs://76477 got closed with status nochangereq.

Logged as bugs://i64365.

bugs://i64365 was closed as fixed.