* * * * * More stupid benchmarks about compiling a million lines of code I'm looking at the code GCC (Gnu's Not Unix Compiler Collection) [1] produced for the 32-bit system (I cut down the number of lines of code [2]): -----[ data ]----- 804836b: 68 ac 8e 04 08 push 0x8048eac 8048370: e8 2b ff ff ff call 80482a0 8048375: 68 ac 8e 04 08 push 0x8048eac 804837a: e8 21 ff ff ff call 80482a0 804837f: 68 ac 8e 04 08 push 0x8048eac 8048384: e8 17 ff ff ff call 80482a0 8048389: 68 ac 8e 04 08 push 0x8048eac 804838e: e8 0d ff ff ff call 80482a0 8048393: 68 ac 8e 04 08 push 0x8048eac 8048398: e8 03 ff ff ff call 80482a0 804839d: 68 ac 8e 04 08 push 0x8048eac 80483a2: e8 f9 fe ff ff call 80482a0 80483a7: 68 ac 8e 04 08 push 0x8048eac 80483ac: e8 ef fe ff ff call 80482a0 80483b1: 68 ac 8e 04 08 push 0x8048eac 80483b6: e8 e5 fe ff ff call 80482a0 80483bb: 83 c4 20 add esp,0x20 -----[ END OF LINE ]----- My initial thought was Why doesn't GCC (Gnu's Not Unix Compiler Collection) just push the address once? but then I remembered that in C, function parameters can be modified. But that lead me down a slight rabbit hole in seeing if printf() (with my particular version of GCC) even changes the parameters. It turns out that no, they don't change (your mileage may vary though). So with that in mind, I wrote the following assembly code: -----[ Assembly ]----- bits 32 global main extern printf section .rodata msg: db 'Hello, world!',10,0 section .text main: push msg call printf ;; 1,999,998 more calls to printf call printf pop eax xor eax,eax ret -----[ END OF LINE ]----- Yes, I cheated a bit by not repeatedly pushing and popping the stack. But I was also interested in seeing how well nasm [3] fares compiling 1.2 million lines of code. Not too badly, compared to GCC: -----[ shell ]----- [spc]lucy:/tmp>time nasm -f elf32 -o pg.o pg.a real 0m38.018s user 0m37.821s sys 0m0.199s [spc]lucy:/tmp> -----[ END OF LINE ]----- I don't even need to generate a 17M (Megabyte) assembly file though, nasm can do the repetition for me: -----[ Assembly ]----- bits 32 global main extern printf section .rodata msg: db 'Hello, world!',10,0 section .text main: push msg %rep 1200000 call printf %endrep pop eax xor eax,eax ret -----[ END OF LINE ]----- It can skip reading 16,799,971 bytes and assemble the entire thing in 25 seconds: -----[ shell ]----- [spc]lucy:/tmp>time nasm -f elf32 -o pf.o pf.a real 0m24.830s user 0m24.677s sys 0m0.144s [spc]lucy:/tmp> -----[ END OF LINE ]----- Nice. But then I was curious about Lua. So I generated 1.2 million lines of Lua: -----[ Lua ]----- print("Hello, world!") -- 1,999,998 more calls to print() print("hello, world!") -----[ END OF LINE ]----- And timed out long it took Lua to load (but not run) the 1.2 million lines of code: -----[ shell ]----- [spc]lucy:/tmp>time lua zz.lua function: 0x9c36838 real 0m1.666s user 0m1.614s sys 0m0.053s [spc]lucy:/tmp> -----[ END OF LINE ]----- Sweet! [1] https://gcc.gnu.org/ [2] gopher://gopher.conman.org/0Phlog:2019/10/04.2 [3] https://nasm.us/ Email author at sean@conman.org .