#1 2015-05-22 08:31:47

Wim314
Member
Registered: 2014-12-03
Posts: 13

Speed issue on Android

Hi

We've a mORMot service running that can return up-to 5.000 records, sometimes even more, in a variant (TDocVariantData).
At the client side we use the generated cross-platform code.

On a desktop, Win32, OSX or iOS Simulator, this client code performs very well. It can retrieve the items on the server almost instantaneous. However running the same client code on a mid-range Android device is slow, up to a minute to retrieve the same amount of data.

Bandwith is a little less on the mobile device (connected to the same Wifi though), but it is not the bottleneck.
The processing of the result on the client is the part that takes longer, 1.5 minutes compared to a few seconds:

In unit mORMotClient we use this to retrieve the data:

fClient.CallRemoteService(self,'GetPatients',1, // raise EServiceException on error
    [parJSONFilter],res);

In unit SynCrossPlatformREST:
It is this call in aformentionend CallRemotService,

result := CallGetResult(Call,outID); 

that takes way longer.
Any ideas how to speed this up (apart from retrieving less data)?
Is there already something to retrieve a 'paged' result (so in chunks)?

Thnx

Offline

#2 2015-05-22 09:58:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

Hi Wim!

Is it not a problem at the communication layer?
I guess there is something wrong with Indy.
Perhaps some option with Indy to be set?
Are you using the latest version of the framework?

What is the size of the JSON returned?

The chunking should be done at service level, i.e. add a parameter to your method to limit the number of returns items.
You can add a LIMIT clause to the "where" statement of the ORM which retrieve the information from the DB.

Offline

#3 2015-05-22 14:04:02

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

Hi Arnoud, been a while

I was under the impression that in

result := CallGetResult(Call,outID); 

you convert the content in the body of the http return from the server to a variant.
I stepped through it and it's the above call that lasts longest.
To me it looks like it that the actual download of the content form the server is rather fast.

Size is around 580KB.

Offline

#4 2015-05-22 18:01:37

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

580KB should be parsed instantaneously.
I do not understand why it is slow under Android.
Even the JavaScript version (compiled with SmartMobileStudio) is instant for doing this...

Could you do true timing inside the mobile app?
Not from the debugger.

Offline

#5 2015-05-26 15:24:52

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

Did some remote logging

As I expected it is CallGetResult, called from within CallRemoteService (see higher) that's the bottleneck.
This call takes 1 minute 40 seconds on a S3 mini for the aforementioned 580KB (value proven in the remote log).
The actual download is a few seconds.

Did some further detailed testing and (as expected?) it is actually

doc.Init(jsonres); 

within CallGetResult that is  the cause for the delay.

Any ideas?

Offline

#6 2015-05-26 15:48:52

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

I honestly don't know...
580KB should be handled like a breeze! On all platforms, it should be almost instant.

Was you able to reproduce the problem without any HTTP request?
It may be some asynchronous process of HTTP.
Try to uncouple the HTTP request from the process: e.g. load the json in a variable, then run it in a loop.

Offline

#7 2015-05-28 11:55:38

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

As you mentioned I did a test bypassing the Http.
The problem - speed issue - still remains.

It is the parsing of JSON that takes so long. Will try on an iOS device next

Offline

#8 2015-05-28 15:50:50

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

I've no Android device to test how the NextGen compiler works on it...
As you know, I usually use SMS (i.e. JavaScript) to write mobile clients.
And with JavaScript, I never had such performance issues at parsing...

So I'm not able to reproduce the problem here.
May be you ask on StackOverflow website, if someone observed such performance issue on Android.

Offline

#9 2015-05-28 20:05:36

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

Could you send me the json content via email?

Offline

#10 2015-05-29 17:02:03

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

See your mail
Thnx

Offline

#11 2015-05-29 20:16:38

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

The JSON sounds fine.

I'm afraid this is how memory is handled under Android by the Delphi NextGen compiler.
Dead slow.
When all the data is handled and converted to a TJsonVariant, there are a lot of memory allocations, which sounds to be slow under Android - much slower than with JavaScript BTW! Embarcadero did not make a good job here, I'm afraid.

You may try to use the "non expanded" JSON format.
See http://synopse.info/files/html/Synopse% … ml#TITL_87
The resulting JSON should be smaller, and the field names should not be re-allocated in memory.
Set NoAjaxJSON=true - see http://synopse.info/files/html/api-1.18 … NOAJAXJSON

But it would be just a small speed enhancement.
I do not see how TJSONParser could be made faster...
Did you compile the executable with optimizations ON (especially inlining), i.e. in Release mode?

There is an easy workaround.
You should try to to use a RawJSON parameter instead of a variant (TDocVariant) at the interface level, to contain the Patients.
Then use TJSONTableObject.Create(const aJSON: string) to compute the result.
TJSONTableObject.StepObject() will parse the rows one by one, so it should use much less resources, and should be therefore much faster.
Even with this RawJSON, you would still benefit of defining TSQLRestServer.NoAjaxJSON=true, which is handled by TJSONTable/TJSONTableObject.

Update:
I just checked again the code.
In practice, RawJSON won't help, I'm afraid, since the content is always converted into a temporary TJSONVariant.
SO I guess that the only possible solution may be in your case:
- Compute the JSON using TSQLRestServer.NoAjaxJSON=true
- Use a TServiceCustomAnswer kind of result - see http://synopse.info/files/html/Synopse% … #TITLE_422
- Retrieve the JSON on the client side and fill a JSONTableObject.Create(const aJSON: string) to compute the result.

Offline

#12 2015-06-01 06:55:13

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

Thnx Arnoud!!
Will try your suggestions.

Offline

#13 2015-06-01 08:24:58

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

When you use TServiceCustomAnswer kind of result with the cross-platform clients, it returns a single variant item containing the response HTTP body, encoded via HttpBodyToVariant(Call.OutBody).
It is not a normal "string" variant, it is variant of type string as mean of proprietary raw binary storage.

To retrieve the JSON from this variant, you should write:

HttpBodyToText(VariantToHttpBody(TheReturnedVariant),DestinationJson);

Offline

#14 2015-06-01 16:55:12

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

Thnx again Arnoud
The suggested way of working is much fast, thnx.

Offline

#15 2015-06-01 17:14:01

ab
Administrator
From: France
Registered: 2010-06-21
Posts: 13,183
Website

Re: Speed issue on Android

Good news.

But I am disappointed about the performance of the Delphi RTL under Android...

Is it the same with iOS?

Offline

#16 2015-06-02 09:16:17

Wim314
Member
Registered: 2014-12-03
Posts: 13

Re: Speed issue on Android

Yes, it's the same (a little faster but that may be due to differences in hardware, os, .. I guess)
With the suggested way of working (above) it's also way faster.

Offline

Board footer

Powered by FluxBB