Skip to content

Performance issue and optimization ideas - TMVCJsonDataObjectsSerializer.JsonObjectToDataSet #553

@MPannier

Description

@MPannier

Hello,

I have a JSON array with 7500 elements which I load into a TFDMemTable with 38 fields by using this function FDMemTable1.LoadFromJSONArrayString.
In my case, this takes about 14 sec. I did some research to speed up the data load. I found some optimizations for FDMemTable (BeginBatch/EndBatch and AutoCalcFields := False;).
Now the "load" takes about 12 sec. It is faster but not fast enough.

I have done a test with a classic for i := 1 to 8000 loop to insert some hard coded fake data into my FDMemTable. I would like to know which part is the bottleneck. This takes less than 200 ms!
That means my FDMemTable and also the 8000 records are not the problem.

After that, I have tested the JSON parsing. I've done something like this:

lJsonArray := TJDOJsonArray.Parse(Res.BodyAsString) as TJDOJsonArray;
try
for var J := 0 to Pred(lJsonArray.Count) do
begin
var lJsonObj : TJsonObject := lJsonArray.Items[J].ObjectValue;
DataSet.Append;
DataSetField1.AsInteger := lJsonObj.I['Field1'];
DataSetField2.AsWideString := lJsonObj.S['Field2'];
...
DataSet.Post;
end;

This takes only 200 ms (with all 38 fields). Compared to 12 sec, it is really fast.
Why is LoadFromJSONArrayString slower?

I found the reason in TMVCJsonDataObjectsSerializer.JsonObjectToDataSet. For a new test, I have uncommented the following line:

//lName := GetNameAs(ADataSet.Owner, Field.Name, Field.FieldName);

//if (IsIgnoredAttribute(AIgnoredFields, lName)) or (IsIgnoredComponent(ADataSet.Owner, Field.Name)) then
//continue;

//lName := TMVCSerializerHelper.ApplyNameCase(GetNameCase(ADataSet, ANameCase), lName { Field.FieldName } );

lName := Field.FieldName; //uncomment the previous lines and use only this one

Now the data load takes only 200 ms.
The problem-functions are GetNameAs, IsIgnoredComponent and GetNameCase. All of these functions use RTTI to get some information from TField.
I know we can't remove this functions, but can we speed up these functions?
I have some ideas, but I'm not sure what the best one is.
First a question: Can TField have the attributes MVCNameAsAttribute, MVCDoNotSerializeAttribute and MVCNameCaseAttribute? Maybe we can remove one of these functions?
Is it possible to check for all attributes at the same time? Then the RTTI stuff is done only one time, not three times.
Is caching an option? (field name and a list of attributes)
Is an additional parameter an option? Something like "IgnoreNameCase" or "FieldNameAsIs"?
I have no experience with RTTI. Maybe the RTTI code can be optimized?

What do You think? Any other suggestions?

Metadata

Metadata

Labels

acceptedIssue has been accepted and inserted in a future milestoneenhancement

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions