I have noticed that version 4.5 of the ArcGIS Javascript API is noticably slower at fetching tiles from a tile server than version 3.22 of the API. It is particularly apparent when I emulate a slower internet connection using Chrome's developer tools.
It seems that version 3.22 of the API relies on the web browser to limit the number of concurrent tile requests. For HTTP 1.1 in Chrome, this limit is 6 requests per server. Setting multiple servers in ArcGISTiledMapServiceLayer's tileServer property raises this limit to 10 concurrent requests. Other browsers have different limits. See Developer Blog - Max parallel http connections in a browser? for more details.
However version 4.5 of the API limits the number of concurrent tile requests to 6 using a queuing mechanism implemented in init.js (an undocumented part of the API). This means that regardless of the number of servers specified in TileLayer's tileServer property, the limit of concurrent requests stays at 6.
There does not appear to be a way of configuring the API to use a higher number. If you view init.js in Chrome's developer tools, and press the {} button to prettify the code you will see the following code at line 28640:
this._queue = new l({
concurrency: 6,
process: b.process,
peeker: function(b) {
return a._peek(b)
}
})
As you can see the concurrency value is hardcoded.
I have used a hack to raise this value to 12. You can see it at Edit fiddle - JSFiddle. Note this hack uses undocumented classes in the API. When you pan the map in the JSFiddle you can verify in Chrome developer tools there are 10 concurrent tile fetches. If you comment out the hack and retest, there will only be 6.
So I have some questions:
(1) Is there an easier way to do this?
(2) Is it safe to use this hack? Obviously I would need to retest my application if I move to a later version of the API.
(3) Are there any plans to make concurrency a configurable parameter in future versions of the API?
Solved! Go to Solution.
Hi Chris,
This is an area we will improve. We indeed don't yet vary the concurrency based on the service capabilities. This will come.
The hack is ok as a workaround for now as long as you re-apply it in upcoming 4.6.
Cheers
Yann
Nice job figuring this out from the minified code!
I don't see an easier way to do this without bringing in more of the undocumented API, but I do think it's something that could be exposed to the user without too much trouble in the future.
My feeling is that your change isn't going to break anything for now, and as long as you test it with each update, you'll probably be fine. Fair warning though, I'm not particularly knowledgeable about this part of the API, and it's not clear to me why the JS API doesn't just use the browser's request queue.
Yann Cabon might have some better advice
Hi Chris,
This is an area we will improve. We indeed don't yet vary the concurrency based on the service capabilities. This will come.
The hack is ok as a workaround for now as long as you re-apply it in upcoming 4.6.
Cheers
Yann
Thanks for the prompt answers Thomas and Yann.
Thomas said:
> it's not clear to me why the JS API doesn't just use the browser's request queue
My understanding is that HTTP/2 removes the browser's concurrency limits. See google chrome - How many concurrent requests should we multiplex in HTTP/2 - Stack Overflow
So maybe the javascript queue has been added to the API to protect the tile servers.
Chris
The reason is that we want to give some buffer between us and the browser to get a chance cancel requests. The implementation of the queuing is rather simple, we need heuristics and also to make use of tileServers to determine how many requests at a single time.
> I don't see an easier way to do this without bringing in more of the undocumented API, but I do think it's something that could be exposed to the user without too much trouble in the future.
It should just work. Exposing low level configurations like this one is not something we want as it generates more bugs than improves the experience.