HttpRequest slow and unreliable on Android

We are noticing slow and unreliable HttpRequests on Android.

To show the problem I created a testcase:

file

The screen is flashing every time a request is successful, so it is possible to compare performance between devices directly. A Profiler logs the average time in advance.

Test results: iOS (iPhone 5s): Profiler AvarageTime: 0.048084 CallCount: 2788 Android (Note2): Profiler AvarageTime: 0.168169 CallCount: 2433 Android (Nvidia Shield): Profiler AvarageTime: 0.15938 CallCount: 2458

  • HttpRequest might not be responding. (And new requests are not executed)

  • The test is revealing a memory leak in HttpRequest:

E/dalvikvm-heap(23383): Out of memory on a 16400-byte allocation.
I/dalvikvm(23383): "AsyncTask #4" prio=5 tid=15 RUNNABLE
I/dalvikvm(23383):   | group="main" sCount=0 dsCount=0 obj=0x425163e0 self=0x619db980
I/dalvikvm(23383):   | sysTid=23413 nice=10 sched=0/0 cgrp=apps/bg_non_interactive handle=1638175168
I/dalvikvm(23383):   | state=R schedstat=( 12669599687 2890955684 27783 ) utm=961 stm=305 core=0
I/dalvikvm(23383):   at com.fuse.ExperimentalHttp.DownloadTask.doInBackground(DownloadTask.java:~40)
I/dalvikvm(23383):   at com.fuse.ExperimentalHttp.DownloadTask.doInBackground(DownloadTask.java:26)
I/dalvikvm(23383):   at android.os.AsyncTask$2.call(AsyncTask.java:288)
I/dalvikvm(23383):   at java.util.concurrent.FutureTask.run(FutureTask.java:237)
I/dalvikvm(23383):   at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
I/dalvikvm(23383):   at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
I/dalvikvm(23383):   at java.lang.Thread.run(Thread.java:841)
W/dalvikvm(23383): threadid=15: thread exiting with uncaught exception (group=0x41bffc08)
E/AndroidRuntime(23383): FATAL EXCEPTION: AsyncTask #4
E/AndroidRuntime(23383): Process: com.HttpPerformanceTest, PID: 23383
E/AndroidRuntime(23383): java.lang.RuntimeException: An error occured while executing doInBackground()
E/AndroidRuntime(23383):     at android.os.AsyncTask$3.done(AsyncTask.java:300)
E/AndroidRuntime(23383):     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355)
E/AndroidRuntime(23383):     at java.util.concurrent.FutureTask.setException(FutureTask.java:222)
E/AndroidRuntime(23383):     at java.util.concurrent.FutureTask.run(FutureTask.java:242)
E/AndroidRuntime(23383):     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
E/AndroidRuntime(23383):     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
E/AndroidRuntime(23383):     at java.lang.Thread.run(Thread.java:841)
E/AndroidRuntime(23383): Caused by: java.lang.OutOfMemoryError
E/AndroidRuntime(23383):     at com.fuse.ExperimentalHttp.DownloadTask.doInBackground(DownloadTask.java:40)
E/AndroidRuntime(23383):     at com.fuse.ExperimentalHttp.DownloadTask.doInBackground(DownloadTask.java:26)
E/AndroidRuntime(23383):     at android.os.AsyncTask$2.call(AsyncTask.java:288)
E/AndroidRuntime(23383):     at java.util.concurrent.FutureTask.run(FutureTask.java:237)
E/AndroidRuntime(23383):     ... 3 more

Thanks for reporting this. We’ll look into it!

I reviewed and tested the HttpRequest.java class in Fuse:

The biggest delay occures in UploadTask.java

Line 72:
System.setProperty("http.keepAlive", "true");

Line 246:
urlConnection.setUseCaches(true); 
//value should be forwarded from HttpMessageHandlerRequest.EnableCache(bool)

Line 250:
urlConnection.setRequestProperty("connection", "close");

This enables reuse of underlaying Socket connections. But could cause problems in old Android versions:

Some Requests take multiple seconds

Some Requests are not responding for up to 10 seconds leading to a high avarage time: (Nvidia Shield) Profiler - AvarageTime: 0.112517 CallCount: 7703 LastTime: 0.394511

OutOfMemoryException

There is still an OutOfMemoryException occuring after some time.

Thanks for the update. I’ll be digging into this and hopefully will have some news very soon.

[for those following this, we have been working with Eike to track this down]

We have a fix for these issues now. There is a slight overhead compared to ios in how the callbacks are traversing the threads, but this too will be looked at.

It is at least 4 times faster than it used to be for small requests.

These fixes will be rolling out in monday’s update