I discussed this a bit on #dom on matrix, but this is actually being caused by a footgun. The
Blob constructor takes an array of blob segments as a first argument, whereas this example passes in a
Uint8Array. WebIDL converts each element of the array individually into a string to be added to the stream, so the behaviour actually ends up being:
["0", "0", "0", ...500k times, "0"]
The overhead in this situation, then, becomes due to the overhead of processing all 500k stream segments independently. WebKit appears to eagerly concatenate sequences of strings together into the same blob part at construction time, meaning that they end up storing a sequence of 500k "0"s, whereas we convert each single-byte string into a stream independently. The largely-inflated overhead is then coming just from every stream being relatively expensive compared to a single byte string.
It might be worth considering producing a warning of some kind if a
Uint8Array is directly passed to
new Blob as the first argument, depending on how difficult that is to do, and we could consider concatenating adjacent string/ArrayBuffer segments together like WebKit is in order to reduce overhead for very large blob segment sequences.