#1 2016-04-20 19:07:12

chapa
Member
Registered: 2012-04-30
Posts: 117

Record Load/Save JSON Thread Safe?

Hi,

Are RecordLoad/SaveJSON() thread safe?

I have really high multithread load using them. Always had random AVs, but recently they became more and more often.
Did secure them inside a lock, and everything seems fine now.

I had random AVs at TTextWriter.AddRecordJSON, TJSONRecordAbstract.CustomWriter, TJSONCustomParserRTTI.WriteOneLevel, WriteOneValue.
Also at FinalizeRecord and LStrClr when local variable of the record is about to be released ending a procedure call.

Also wanted to ask, are this methods fastest approach when it comes to object<->json conversion?

Thanks.

Regards,
chapa

Offline

#2 2016-04-20 19:19:25

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Record Load/Save JSON Thread Safe?

Record persistence as JSON is perfectly thread-safe.
It is used on production, on highly multi-threaded servers, since years.
There is no global variable involved.

Offline

#3 2016-04-20 19:40:58

chapa
Member
Registered: 2012-04-30
Posts: 117

Re: Record Load/Save JSON Thread Safe?

Thanks ab,

Than, going to investigate further the AVs at SynCommons unit and let you know results.

About the performance, are Record Load/Save JSON functions fastest approach when it comes to object<->json conversion?
How slower in your opinion using _Json and TDocVariants are compared to them?

Thanks.

Offline

#4 2016-04-20 20:10:31

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 14,182
Website

Re: Record Load/Save JSON Thread Safe?

It depends on which kind of data is stored.

Records use less memory, since the field names are not stored.
So they are faster in practice.
See http://blog.synopse.info/post/json-benc … on-dbxjson

Offline

#5 2016-04-21 14:32:25

chapa
Member
Registered: 2012-04-30
Posts: 117

Re: Record Load/Save JSON Thread Safe?

Thanks ab,

Along with not obvious AVs, I got this madExcept log:

exception message  : Access violation at address 0000000000411D75 in module 'test.exe'. Write of address 0000000000FACCF0.

thread $1184:
00411d75 +015 test.exe System                        @LStrClr
0080fff6 +0a6 test.exe SynCommons         34391   +5 TJSONCustomParserRTTI.FinalizeNestedRecord
008100e4 +044 test.exe SynCommons         34421   +7 TJSONCustomParserRTTI.FinalizeNestedArray
00810126 +016 test.exe SynCommons         34429   +1 TJSONCustomParserRTTI.AllocateNestedArray
008105a3 +303 test.exe SynCommons         34493  +29 ProcessValue
00811320 +510 test.exe SynCommons         34668  +64 TJSONCustomParserRTTI.ReadOneLevel
00811e47 +037 test.exe SynCommons         34818   +2 TJSONRecordAbstract.CustomReader
0080dee3 +2b3 test.exe SynCommons         33861  +19 RecordLoadJSON

Please, note, that I do not have any string properties defined in the record!

I think RecordLoadJSON in some odd cases brokes input buffer and/or its own props buffer.
Even in other records containing RawUTF8 I got broken reference to them causing system finalizearray to AV on record cleanup upon procedure end.

Record definition is as follow:

  TTestDTO = packed record
    Id: Integer;
    Seen: Integer;
  end;

  TTestArrDTO = packed record
    arr: array of TTestDTO;
  end;

  __TTestDTOJSON =
    'Id Integer ' +
    'Seen Integer';

  __TTestArrDTOJSON =
    'arr [ ' + __TParserOddSeenDTOJSON + ' ]';

  TTextWriter.RegisterCustomJSONSerializerFromText(TypeInfo(TTestArrDTO), __TTestArrDTOJSON).Options := [soReadIgnoreUnknownFields];

Using Delphi XE7, Debug 64bit

When I thread protect the call to RecordLoadJSON() everything goes just fine.

Any input where and how I should proceed will be appreciated.

Last edited by chapa (2016-04-21 14:34:19)

Offline

Board footer

Powered by FluxBB