-
Notifications
You must be signed in to change notification settings - Fork 12.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using include_bytes!
on large binary blobs compiles more slowly than expected
#65818
Comments
Similar to #56900 (which kind of went under the radar) |
Most ideally this would result in rustc telling linker to link that file into whatever symbol. Possible but super non-trivial to achieve. (At least as far as runtime behaviour of this item is concerned) |
I'm sure you're aware but just to spell it out for completeness: this would not work in general since const eval may need the file contents, it would be a fast path for the special where the bytes are only needed at runtime. Depending on the details, I am also a bit concerned about robustness. For example, just storing the file path in the rlib could break if the included file is moved or deleted between the rlib being created and it being linked into a binary or other final artifact. It also wouldn't extend to staticlibs, I believe, which are probably a common crate type for projects where this optimization would help. OTOH, using |
After seeing the const-ness of needing this I tried out a few different formulations as well: pub static FOO: &[u8] = include_bytes!("..."); or... pub fn foo() -> &'static [u8] {
include_bytes!("...")
} unfortunately though while they were slightly faster they were still quite slow (on the order of hundreds of milliseconds for a 10MB file or so) |
I believe the only reason we pretty print constants is for rustdoc -- though I could be wrong -- I imagine maybe the solution then is to impose some sort of limit? And/or if we can somehow store that the constant came from include_bytes, I wonder if displaying |
In my tests, a 256 MiB file ( |
I just came across this with the windows crate where I embed the default metadata describing the Windows API amounting to around 20MB. Are there any plans to fix this or should I write my own implementation? |
I tried to experiment with this last year, there are very real benefits from not escaping bytes from The main issues:
IIRC, one viable implementation candidate was supporting interning non-UTF-8 byte arrays in string interner and representing them as |
Hi All, I was wondering if there was any progress in the recent months with this issue? |
…etrochenkov Delay `include_bytes` to AST lowering Hopefully addresses rust-lang#65818. This PR introduces a new `ExprKind::IncludedBytes` which stores the path and bytes of a file included with `include_bytes!()`. We can then create a literal from the bytes during AST lowering, which means we don't need to escape the bytes into valid UTF8 which is the cause of most of the overhead of embedding large binary blobs.
…etrochenkov Delay `include_bytes` to AST lowering Hopefully addresses rust-lang#65818. This PR introduces a new `ExprKind::IncludedBytes` which stores the path and bytes of a file included with `include_bytes!()`. We can then create a literal from the bytes during AST lowering, which means we don't need to escape the bytes into valid UTF8 which is the cause of most of the overhead of embedding large binary blobs.
#103812 improved this considerably (small benchmark). There's still some slowness on the LLVM side however |
I've been playing around recently with compiling a crate that simply contains:
and I've been surprised that the compile time of this crate is pretty nontrivial!
For example this crate:
takes 0.060 seconds to compile on nightly for me. If a multi-megabyte binary (such as
cargo
itself) is included:this crate takes 0.729 seconds to compile!
There appear to be at least two major sources of slowdown:
include_bytes!
theexpr_lit
function callsfrom_lit_kind
which callsto_lit_token
that runs an operation per-byte, which is pretty expensive for multi-megabyte files.There may be a few other sources of slowdown, but ideally usage of
include_bytes!
and large byte blobs in general should never iterate over the bytes and perform expensive operations, but rather the bytes should just be transferred as a whole in various contexts if absolutely necessary.The text was updated successfully, but these errors were encountered: