Fragen? Antworten! Siehe auch: Alternativlos
Der Standard-Linker unter Linux ist GNU ld von den binutils. Das ist ein uraltes Fossil von einer Codebasis, weil die eben nicht das konkrete Problem gelöst haben, sondern ein allgemeineres Problem lösen. Der Linker ist parametrisierbar und kann zur Compilezeit mitgeteilt kriegen, ob man ELF, COFF oder gar Windows EXE Files damit linken will. Kann glaube ich auch MACH-O von Apple, bin mir aber nicht sicher gerade.
Jedenfalls ist das Teil schnarchlangsam. Spielt in den meisten Fällen keine Rolle. Ich hab damit jahrzehntelang prima arbeiten können, ohne dass mir jemals aufgefallen wäre, wie langsam das Teil ist. Meine Programme sind aber auch alle relativ überschaubar.
Wenn man mal, sagen wir, Firefox linkt, dann ist die Link-Pause merkbar. Spielt im Vergleich zur Compilezeit keine Rolle, aber ist nicht gar nicht da.
Also haben sich über die Jahre Projekte gegründet, um mal einen schnelleren Linker zu bauen. Der erste, den ich gesehen habe, ist GNU gold, der ist auch Teil von den binutils. Ist in C++ geschrieben und direkt ... doppelt so groß wie ld. War zwar ein bisschen schneller aber linkte bei mir mal Firefox nicht und konnte auch kein link-time optimization und war daher direkt draußen.
Das nächste Projekt, das antrat, war LLVM lld. Der hat erstmals ein bisschen Multithreading am Start, aber nur für einige Teile. mold will jetzt alle Teile auf alle Cores verteilen.
Ich habe mal testweise das Erstellen von libavcodec.so gemessen:
GNU ld: 1.21s user 0.26s system 99% cpu 1.463 totalDas war jeweils noch mit Debug-Symbolen. Gut, unterhalb einer Sekunde ist das jetzt alles nicht sonderlich aussagekräftig, und die %CPU-Spalte bei mold ist offenbar damit überfordert, wie flott das Ding fertig war :-)
GNU gold: 0.83s user 0.10s system 99% cpu 0.928 total
LLVM lld: 0.69s user 0.17s system 258% cpu 0.333 total
mold: 0.03s user 0.00s system 13% cpu 0.247 total
Aber ich finde das ein interessantes Ergebnis und wollte direkt mal dietlibc damit linken, um zu gucken, ob das geht. Ging nicht, weil ich eine obskure Spezialoption von GNU ld benutze, -z noseparate-code. ld hat vor ein paar Jahren angefangen, nach SPECTRE bei den Segmenten Padding auf Page-Größe zu machen. Hintergrund ist, dass die Hardware Speicherschutz mit Page-Granularität macht. Wenn also in einem Binary Code und Datensegment nebeneinander im Binary liegen, dann war früher auf der letzten Page des Datensegmentes (das read-write gemappt ist!) auch die ersten Bytes des Codesegments, und man hätte da also reinschreiben können in einem Exploit oder so. Jetzt bläst der Linker das mit Null-Bytes auf. Ist an sich eine gute Idee, aber bei dietlibc will ich halt winzige Binaries haben. Da ist das Binary für rm sowas wie 9k groß. Wenn der Linker da Padding einfügt, dann ist das mal eben 50% größer. Daher möchte ich das bei der dietlibc gerne selektiv ausschalten können, und obiges wäre die Option dafür gewesen.
Die konnte mold nicht. Also hab ich vor zwei Tagen einen Bug aufgemacht. Heute war die Mail in der Inbox, dass er das eingebaut hat.
Ich muss sagen: Hut ab. So stellt man sich das in seinen Fieberträumen vor, dass Software-Entwicklung so abläuft. Erstens natürlich dass der Typ überhaupt reagiert, dann dass er mir nicht erklärt, meine Anforderung sei Scheiße, dann dass er das implementiert, und dann dass er das quasi über Nacht implementiert. Sehr beeindruckend.
Ich wünsche euch allen, dass ihr eure Codebasen auch so in Schuss habt, dass ihr auf so eine Anforderung mal eben so flott reagieren könntet. :-)
mold hat bei mir jetzt auf jeden Fall mehrere Schritte auf der Treppe genommen.
Update: Äh, jetzt habe ich den Link vergessen. Ist auf Github. Hat m.W. keine separate Homepage.