Commit message:
[loader] Size the file:// response pipe to the file, capped at 2 MiB
FileURLLoader asks for the "larger" 2 MiB data pipe for every file://
response since https://crrev.com/c/3428154, which fixed slow loads of
very large local files. The pipe's shared memory is created, fallocated
and mapped up front by the browser and mapped again by the consumer, so
for the common case of small local resources (an app shell's scripts,
stylesheets and images, and every chrome-extension:// resource, which
extensions::ExtensionProtocols loads through
CreateFileURLLoaderBypassingSecurityChecks) most of the cost of the load
is setting up and tearing down 2 MiB of shared memory to move a few KiB.
The file size is known before the pipe is created, so clamp the capacity
to [net::kMaxBytesToSniff, 2 MiB] using it. Files of 2 MiB and more get
exactly the pipe they get today; smaller files get a pipe that still
holds the whole file, so the number of producer/consumer round trips
does not change, and the MIME sniffing buffer always fits.
Measurements (Linux x64 official build; content_shell loading a page
from file:// that XHRs local files of each size, per-request latency,
30 interleaved fresh-process runs per side, medians; two sessions,
headless and X11):
1 KiB 1.37 -> 0.94 ms / 1.30 -> 0.97 ms
16 KiB 1.31 -> 0.91 ms / 1.29 -> 0.91 ms
64 KiB 1.43 -> 1.00 ms / 1.37 -> 1.00 ms
256 KiB 1.66 -> 1.20 ms / 1.56 -> 1.22 ms
1 MiB 2.60 -> 2.40 ms / 2.70 -> 2.58 ms
4 MiB 5.95 -> 5.95 ms / 6.00 -> 6.05 ms (pipe unchanged)
All rows up to 1 MiB p < 1e-9 (Welch and Mann-Whitney).
Tested: content_unittests (FileURLLoaderFactoryTest.*),
content_browsertests --gtest_filter=*FileURL*:NavigationBrowserTest.*:
*Loader*:*Download*File*:*Fetch*, unit_tests ExtensionProtocolsTest.*,
content_unittests loader tests under ASan; no behavior change for range
requests, directory listings or files >= 2 MiB.