[lld] [lld][MachO]Multi-threaded i/o. Twice as fast linking a large project. (PR #147134)
John Holdsworth via llvm-commits
llvm-commits at lists.llvm.org
Tue Jul 8 23:01:36 PDT 2025
================
@@ -282,11 +283,103 @@ static void saveThinArchiveToRepro(ArchiveFile const *file) {
": Archive::children failed: " + toString(std::move(e)));
}
-static InputFile *addFile(StringRef path, LoadType loadType,
- bool isLazy = false, bool isExplicit = true,
- bool isBundleLoader = false,
- bool isForceHidden = false) {
- std::optional<MemoryBufferRef> buffer = readFile(path);
+typedef struct {
+ StringRef path;
+ bool isLazy;
+ std::optional<MemoryBufferRef> buffer;
+ const char *start;
+ size_t size;
+} DeferredFile;
+typedef std::vector<DeferredFile> DeferredFiles;
+
+#ifndef _WIN32
+typedef struct {
+ DeferredFiles deferred;
+ size_t counter, total, pageSize;
+ pthread_mutex_t mutex;
+} PageInState;
+
+// Most input files have been mapped but not yet paged in.
+// This code forces the page-ins on multiple threads so
+// the process is not stalled waiting on disk buffer i/o.
+static void multiThreadedPageInBackground(PageInState *state) {
+#define MaxReadThreads 200
+ static size_t totalBytes;
+
+ pthread_t running[MaxReadThreads];
+ if (config->readThreads > MaxReadThreads)
+ config->readThreads = MaxReadThreads;
+ pthread_mutex_init(&state->mutex, nullptr);
+
+ for (int t = 0; t < config->readThreads; t++)
+ pthread_create(
+ &running[t], nullptr,
+ [](void *ptr) -> void * {
+ PageInState &state = *(PageInState *)ptr;
+ while (true) {
+ pthread_mutex_lock(&state.mutex);
+ if (state.counter >= state.deferred.size()) {
+ pthread_mutex_unlock(&state.mutex);
+ return nullptr;
+ }
+ DeferredFile &file = state.deferred[state.counter];
+ state.counter += 1;
+ pthread_mutex_unlock(&state.mutex);
+
+ const char *page = file.start, *end = page + file.size;
+ totalBytes += end - page;
+
+ int t = 0; // Reference each page to load it into memory.
+ for (; page < end; page += state.pageSize)
+ t += *page;
+ state.total += t; // Avoids the loop being optimised out.
+ }
+ },
+ state);
+
+ for (int t = 0; t < config->readThreads; t++)
+ pthread_join(running[t], nullptr);
+
+ pthread_mutex_destroy(&state->mutex);
+ if (getenv("LLD_MULTI_THREAD_PAGE"))
+ printf("multiThreadedPageIn %ld/%ld\n", totalBytes, state->deferred.size());
+}
+#endif
+
+static void multiThreadedPageIn(DeferredFiles deferred) {
+#ifndef _WIN32
+ static pthread_t running;
+ static pthread_mutex_t busy;
+
+ if (running)
+ pthread_join(running, nullptr);
+ else
+ pthread_mutex_init(&busy, nullptr);
+
+ PageInState *state =
+ new PageInState{deferred, 0, 0, llvm::sys::Process::getPageSizeEstimate(),
+ pthread_mutex_t()};
+
+ pthread_mutex_lock(&busy);
+ pthread_create(
+ &running, nullptr,
+ [](void *ptr) -> void * {
+ PageInState *state = (PageInState *)ptr;
+ multiThreadedPageInBackground(state);
+ pthread_mutex_unlock(&busy);
+ delete state;
+ return nullptr;
+ },
+ state);
----------------
johnno1962 wrote:
And windows now builds 👍
https://github.com/llvm/llvm-project/pull/147134
More information about the llvm-commits
mailing list