-
-
Notifications
You must be signed in to change notification settings - Fork 14.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
Speed up application startup by using ld.so.cache
#207061
base: staging
Are you sure you want to change the base?
Conversation
ld.so.cache
After looking around some more, I stumbled across @fzakaria'a nix-harden-needed, which may be a better choice over Guix's solution (per the README, they want to integrate it into Nixpkgs). (Farid: hi, figured I'd loop you in here, considering you have interest in this problem :) |
Hi Winter! Thank you for pinging me. My hot-take: Edit: This is a great PR btw -- very concise if it works. Only unfortunate thing is patching but maybe you can upstream something to make it configurable based on an ELF file section. It has the added benefit of supporting LD_LIBRARY_PATH which the other options don't (maybe though that's a feature?) |
Here is a document of some other much more "visionary" ideas I have for Nix + NixOS. |
So I hope you don't mind me asking this here (if you'd rather discuss over e.g. IRC, Matrix, or email to avoid cluttering up this PR, let me know), but what does Shrinkwrap provide that this cache approach doesn't? They seemingly both eliminate the intensive RPATH traversal. I know there's one advantage you list in the README:
but I admit I'm confused as to what a practical example of this would look like/what the problem is in general 😅. Do you mind explaining? |
It does work; I've tested it with I think an advantage to this solution is definitely that it's minimally invasive and concise, as you mention.
(Why doesn't Shrinkwrap support it, since it just lifts dependencies up to the parent ELF?) |
Reached out on Matrix. |
Some questions:
|
@@ -71,7 +71,8 @@ let | |||
../../build-support/setup-hooks/reproducible-builds.sh | |||
../../build-support/setup-hooks/set-source-date-epoch-to-latest.sh | |||
../../build-support/setup-hooks/strip.sh | |||
] ++ lib.optionals hasCC [ cc ]; | |||
] ++ lib.optionals hostPlatform.isLinux [ ../../build-support/setup-hooks/generate-ld-cache.sh ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hostPlatform.isLinux is no specific enough, for example pkgsMusl doesn't have a ldconfig. Maybe hostPlatform.isLinux && hostPlatform.isGnu
?
generating LD cache for ELF executables in /nix/store/bgm2nivmwfa94pw6xlial071z9
0vv5pg-nano-7.1
found lib: /nix/store/62hdd7jfmj90wrwl6dp94hj6xzl9cgvq-ncurses-6.3-p20220507/lib
/libncursesw.so.6
found lib: /nix/store/mpgmlwjdd9g61w92q5d9g8y7r66fp8j6-musl-1.2.3/lib/ld-musl-x8
6_64.so.1
found lib dirs: /nix/store/62hdd7jfmj90wrwl6dp94hj6xzl9cgvq-ncurses-6.3-p2022050
7/lib /nix/store/mpgmlwjdd9g61w92q5d9g8y7r66fp8j6-musl-1.2.3/lib
/nix/store/6j095nxqj7qylwbbp4m00kb640gca06x-generate-ld-cache.sh: line 41: ldcon
fig: command not found
failed to generate LD cache
(nix-build -A pkgsMusl.nano)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point this only works for Glibc
building stdenv comes up with some errors (that are probably not fatal only because shell is terrible):
might be better to add this hook to the final linux stdenv stage only. cross-building an armv7 test system from scratch fails at python:
buildEnv (and presumably symlinkJoin and friends) don't seem to like the approach :( edit
|
Adding Not sure what to do about |
|
||
fixupOutputHooks+=('if [ -z "${dontGenerateLDCache-}" ]; then generateLDCache "$prefix"; fi') | ||
|
||
generateLDCache() { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not just use patchelf to list the dependencies rather than this bash ?
(does patchelf list the needed transitive? if not, you can write a tiny C binary using https://github.com/lief-project/LIEF)
Might be more maintainable.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we've done some investigating and it looks like a purpose-built tool that crawls a dep tree and generates a cache file will be the best thing to do. ld
and ldconfig
apparently can't be made to work in cross-builds (ldd
certainly not, for ldconfig
we've found nothing doing it with glibc. only one instance with uclibc, which doesn't want to build for armv7 right now (and that doesn't bode well for using its ldconfig))
would very much like to make this rust though, C ought to disappear and rustc is in our closures anyways
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
There was a similar patch and discussion from NixOS/patchelf#357 (comment) that started to fold this into the patchelf phase. I'm a fan of the ld.so.cache approach due to the possibility of providing a different cache en-masse, or to mutable locations for testing/debugging!) (but the shrinkwrap also has merits. Looks like the ldd searching for transitive deps is the main difference. I fear this makes the approach more fragile. What are the pros/cons here?
This would make it easier to then patch or redirect to a new place later. I can imagine a
|
+ static const char store[] = @STORE_DIRECTORY@; | ||
+ const char *origin = _dl_get_origin (); | ||
+ | ||
+ /* Check whether ORIGIN is something like "/gnu/store/…-foo/bin". */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ /* Check whether ORIGIN is something like "/gnu/store/…-foo/bin". */ | |
+ /* Check whether ORIGIN is something like "/nix/store/…-foo/bin". */ |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: https://discourse.nixos.org/t/2022-01-03-nixpkgs-architecture-team-meeting-23/24404/1 |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
What the status on this currently? |
This pull request has been mentioned on NixOS Discourse. There might be relevant details there: |
I don't understand, why aren't fzakaria's solutions plain better, compared to a cache? |
I have some interesting work in similar vein for relocation processing that is a clear win for Nixpkgs as well; I plan to speak + write about it. |
Description of changes
This PR does two things:
$ORIGIN/../etc/ld.so.cache
instead of/etc/ld.so.cache
, and to prefer the cache overRPATH
entriesgenerate-ld-cache
, to facilitate the generation of these cachesThis was originally implemented by Guix's Ludovic Courtès in August of 2021 (after Ricardo came up with the idea) -- see their blog post and their discussion on the change for more information + some benchmarks. The glibc patch is copied verbatim from the Guix codebase.
As noted in the linked Guix issue, there are a few things to consider here:
$ORIGIN/../etc/ld.so.cache
path means that it can only be used with first-level sub-directories likebin
andsbin
ld.so.cache
ldd
to get the required dependencies, as opposed to just using the data from the ELF.When discussing this with pennae, they brought up the idea of embedding an absolute path to the cache in an ELF section, and adjusting the patch to do that. We may want to do this instead; I'd appreciate thoughts on the matter.
I'd like to thank the Guix folks mentioned above for originally coming up with and implementing this idea, as well as pennae for nerd sniping me into looking at perf stuff, and their thoughts on the matter.
Things done
sandbox = true
set innix.conf
? (See Nix manual)nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"
. Note: all changes have to be committed, also see nixpkgs-review usage./result/bin/
)nixos/doc/manual/md-to-db.sh
to update generated release notes