lld-link foo.lib /wholearchive:foo.lib should work the same way as
lld-link /wholearchive:foo.lib foo.lib. Previously, /wholearchive in
the former case was ignored.
Details
Diff Detail
- Build Status
Buildable 19247 Build 19247: arc lint + arc unit
Event Timeline
lld/COFF/Driver.cpp | ||
---|---|---|
1250 | I think we need to canonicalize the path a little to ensure that this works on case insensitive file systems: We shouldn't enqueue the same file twice, right? Also, maybe we should just enqueue all whole archive inputs in this loop, up front, and then only process inputs later if the input wasn't already added as a whole archive input. | |
1250 | I guess to make it easy to write a cross-platform test for path canonicalization, the test could use: | |
1270 | I don't think Args.hasArg(OPT_wholearchive_flag) is the right check here, that asks if a whole archive flag appears anywhere on the command line, not if this particular flag is whole archive. |
lld/COFF/Driver.cpp | ||
---|---|---|
134 | I think O(n**2) stats on input object files is going to be too much. Once we have the FD, you can do fs::getUniqueId(FD) to get the inode number, and then build a set of those. I guess if it's not a file MemoryBuffer, don't do the inode check. It probably comes from a whole archive. | |
1255–1256 | sys::fs::equivalent internally opens and closes a file handle for the purpose of doing a stat and comparing inodes. This will end up doing O(inputs * wholearchiveinputs) equivalency tests, and linkers have many input object files. Is there a way to avoid that? | |
1270 | I see, I didn't understand how OPT_wholearchive_flag vs. file worked. |
lld/COFF/Driver.cpp | ||
---|---|---|
1255–1256 | That's right, but I don't think there's a way to avoid that unless we implement some OS-dependent logic on our side. How operating system normalize pathname components depends on the operating system and the file system, and I believe the only reliable way to do that is to ask about it to the system. Maybe we could cache stat's results along with filenames to reduce the number of system calls, but I'm not sure if we need it. If it turns out to be too slow, we could optimize, but probably we should do that later when it becomes a real problem. In reality, what is the largest number of files you can think of you want to pass to the linker? For hundreds of files, this is probably fine. If you pass thousands of files, this is probably slow. |
lld/COFF/Driver.cpp | ||
---|---|---|
1255–1256 | We have a library that's built from ~5,000 object files, so we care about the performance here :) I can try to get some numbers later today. |
I don't need the exact number as long as it is more than 5,000. :) I'll try to optimize this patch for a large number of input files.
lld/COFF/Driver.cpp | ||
---|---|---|
1255–1256 | Right, O(n) stats should be fine, just use llvm::sys::fs::getUniqueId or whatever it's called, and it will be fine. That gets the inode (or its local equivalent). |
lld/COFF/Driver.cpp | ||
---|---|---|
134 | Since this is a MemoryBuffer and not a MemoryBufferRef, I think anything that comes to this function is a file and not a slice of a file. |
lld/COFF/Driver.cpp | ||
---|---|---|
796 | Typo: wrapper |
This diff results in a 30% link time regression for us (5.3 seconds to 6.8 seconds) when linking ~5,000 input files together. This is when cross-compiling on Linux; the results would probably be even worse on Windows, where I believe stat/the filesystem in general is slower.
Is there any way to make this less expensive? I notice we still have the O(n^2) loop comparing every input file to every other input file (using a cached stat result, but still). @rnk had previously suggested building up a set out of inode numbers, which should be O(n) instead; are there problems with that approach?
This new version is much better; there doesn't actually appear to be any performance difference for my test case at all now (barring noise). Thank you!
lld/trunk/COFF/Driver.cpp | ||
---|---|---|
1249–1250 ↗ | (On Diff #151041) | We forgot to call findFile here. I'll go ahead and fix that. This caused https://crbug.com/852679 |
I think O(n**2) stats on input object files is going to be too much. Once we have the FD, you can do fs::getUniqueId(FD) to get the inode number, and then build a set of those. I guess if it's not a file MemoryBuffer, don't do the inode check. It probably comes from a whole archive.