Set XHR response type to "text"
when the request's Accept header is text/plain
or application/json
#1452
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
What
When the Accept header of the outgoing request is either
"text/plain"
or"application/json"
, set the response type of the underlying XHR request to"text"
.Why
This polyfill sets the responseType of the underlying
XMLHttpRequest
to "blob" if the global context supports it: https://github.com/JakeChampion/fetch/blob/main/fetch.js#L595In turn, the call to
fetchResponse.json();
does the following:That is, it takes the response body (which is already in JSON format), it then constructs a
FileReader
, does a regex match to find the encoding and then parses the blob to finally return the string.That’s a tonne of overhead that could be avoided by just setting the
responseType
of theXMLHttpRequest
to"text"
when we expect text to be returned in the response.Performance improvement
Background
This polyfil is used to provide the
fetch
API for React Native, here.At Relive, our app is built using React Native. We came across this when looking at using the
resourceEventMapper
provided by Datadog, where the resulting network request is returned as the underlyingXMLHttpRequest
object, but it had the response type set to"blob"
.Experiment
We ran an experiment to compare the impact of this overhead.
Definitions
end - start
):Results
With about 29k users in each
control
andtest
cohort, with both cohorts doing about 3.1M requests each, we see the following:NB: p95 and above, we start seeing a lot of noise due to network errors, so the most interesting bits are p90 and downward.
That is, on average, a 4% performance improvement, and a 5% improvement for p95.
Locally
Since the change proposed in the PR really should have the biggest affect on the
.json()
call, I was also able to confirm a performance improvement by creating some performance tests based on the existing test suite here.Again, time in ms.
NB: "small" is a JSON object w/ 10 fields, "medium" has 100 fields and "large" has 10000 fields.
Open questions
[ ] Since we're only using this polyfill in React Native, we could test it there. But where else is this polyfill being widely used, and is this proposed change safe for those?
[ ] Is there a more elegant way to set the response type other than looking at the Accept header?
[ ]
XMLHttpRequest
also supportsjson
as a response type. Perhaps it's worth considering setting the response type tojson
and delegate the JSON parsing toXMLHttpRequest
. Could this lead to even further performance improvements?[ ] What happens as the response object gets even bigger than the "large" version above?
Tests
All passing ✅