Having an issue where the first service call is very slow, then after the others are faster.
my URL is HTTPS so I was wondering if it had something to do with that.
my Code:
OkHttpClient okClient = new OkHttpClient();
okClient.setReadTimeout(1, TimeUnit.MINUTES);
okClient.setConnectTimeout(1, TimeUnit.MINUTES);
Retrofit client = new Retrofit.Builder().baseUrl(baseURL).addConverterFactory(SimpleXmlConverterFactory.create()).addCallAdapterFactory(RxJavaCallAdapterFactory.create()).client(okClient).build();
dmvAPIInterface = client.create(DmvAPIInterface.class);
public interface DmvAPIInterface
{
@Headers({
"Content-Type: application/x-www-form-urlencoded"
})
@GET("GetDataByLP")
Call<DMVResponse> getResponse(@Query("LP") String LP,@Query("LPState") String LPState, @Query("jamaica") String Jamaica, @Query("demo") String Demo, @Query("deviceID") String DeviceID, @Query("OS") String OS);
I had to put the timeouts to 1 minute because if I didn't, nothing happens and it just keeps loading for ever till I have to stop it. Usually the first call takes 15 - 20 seconds then after that the others are much faster (1-3 seconds)
The first call will always be a few tens or hundreds of milliseconds slower because parsing the annotations on the endpoint is done on first use. It will not be tens of _seconds_ slower, however.
long startNanos = System.nanoTime();
Call<String> call1 = example.getString();
long tookMillis1 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
startNanos = System.nanoTime();
Call<String> call2 = example.getString();
long tookMillis2 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
System.out.println("First time creation: " + tookMillis1 + "ms");
System.out.println("Second time creation: " + tookMillis2 + "ms");
startNanos = System.nanoTime();
Response<String> response1 = call1.execute();
long tookMillis3 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
startNanos = System.nanoTime();
Response<String> response2 = call2.execute();
long tookMillis4 = TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - startNanos);
System.out.println("First execution: " + tookMillis3 + "ms");
System.out.println("Second execution: " + tookMillis4 + "ms");
yields:
First time creation: 15ms
Second time creation: 0ms
First execution: 40ms
Second execution: 1ms
Are you hitting a Google App Engine endpoint? A cold call to App Engine takes on the order of 15s to startup. Try adding the logging-interceptor from OkHttp to see how long the actual HTTP call takes.
I'm also seeing a similar issue only on certain wifi networks. I've been able to reproduce this in two separate apps with separate codebases both using retrofit. The first network call is taking roughly 20 seconds and then every request after that with the existing retrofit instance takes 200ms or less. Same apps running on most networks or in the emulators work just fine. Had a few users complain about it working slowly for them only on certain wifi networks as well.
@JakeWharton
Same happens to me, but in different scenario.
When the internet connection goes down but the Wi-Fi status is connected, the first network call takes all the seconds specified in read/connect timeout. However, when a second call is made right after the first one, the call is immediate. Why does it take so long in the first time and not se subsequent ones?
I noticed the same problem. On certain data networks the first call through retrofit takes about ~11 seconds. I narrowed it down to DNS lookup taking too long to resolve the host name.
I was able to resolve this issue by changing my device's Dns server. I'm developing android app so I used "Dns Changer" app to switch to Google Dns server. But I cannot expect the users to do so too.
So at startup I make a dummy call from all the webservices that I'm using in the app. That way all the services do the lookup at startup and they are ready to go from that point. It's not the perfect solution but it works and I'm still exploring the alternatives
@JakeWharton I am also facing this issue. And I am facing it in the same way like @luccasmaso is facing. The first response is comming late after eating up all the timeperiod mentioned in connect timeout. And then after all the webservice call runs taking no time. And to add more, it runs without any issue on the http server but on https server it gives the issue.
Can anyone put the enlightment on the issue and any solution to resolve it.
set dns in okhttp to resolve this issue
val httpClient = OkHttpClient.Builder()
httpClient.dns(CustomDns())
https://garage.easytaxi.com/tag/dns-android-okhttp/
I am also facing the same issue. Currently I have set the timeout to 2sec. But this solution can not be hold for long time since I am downloading data/files which could be bigger in size. Please help me on this. Is there similar issue on Okhttp?
I found solution for HttpClient – it's because of proxy resolving. Just wrap your HttpClient like this:
var client = new HttpClient(new HttpClientHandler { UseProxy = false });
I am also facing a similar issue. Did any find solution for this? In firebase performance for the first call from the app, I can see high p95
I'm getting random reports of this issue from users as well. Did some debugging and it seems to come down to a DNS lookup issue.
First API taking approx the same time as specified in readTimeout. e.g. if it is 60 seconds then the first API will take 60 seconds. NOTE: this is not API issue, I changed the API, and still reproducing.
@ajitjangra @PravinsinghWaghela @garokiam @samyakjain
I'm facing exactly the same issue, where the first httpOk request takes a long time. How did you resolve it please?
If you check the mention link above, you will see I even utilised a custom DNS and turned off proxy, but it remains problematic.
If you could share your experience and solution for the community, it would be much appreciated.
Thank you
Am also facing similar issues where the first call is taking a long time. All the calls after that happens just in seconds.
OH COME ON : ITS BEEN 5 YEARS AND THIS BUG IS STILL HERE SOMEWHERE.......
In a nutshell, Retrofit/Android tries to connect first via IPv6. If there is a firewall issue as it was in my case, it keeps retrying until 60 seconds timeout have been reached. Only then it switches to IPv4.
See more here: https://github.com/square/okhttp/issues/6486
I recommend removing the AAAA dns entry to your server, until you have fixed the IPv6 issues. Good luck.