← Back to context

Comment by ZoomZoomZoom

18 days ago

One of the coolest tricks is using tcc to compile "on demand." This allows you to use a compiled language like Nim for scripting, with almost no noticeable performance difference compared to interpreted languages.

  #!/usr/bin/env -S nim r --cc:tcc -d:useMalloc --verbosity:0 --hints:off --tlsEmulation:on --passL:-lm
  echo "Hello from Nim via TCC!"

Here's a comparison (bash script at [1]) of a minimal binary compiled this way with different interpreters. First line is the noise. Measured by tim[2] written by @cb321.

  1.151 +- 0.028 ms     (AlreadySubtracted)Overhead
  1.219 +- 0.037 ms     bash -c exit
  2.498 +- 0.040 ms     fish --no-config --private -c exit
  1.682 +- 0.058 ms     perl   -e 'exit 0'
  1.621 +- 0.043 ms     gawk   'BEGIN{exit 0}'
  15.8 +- 2.2 ms     python3 -c 'exit(0)'
  20.0 +- 5.7 ms     node   -e 'process.exit(0)'
  -2.384 +- 0.041 ms tcc -run x.c
  153.2 +- 4.6 ms     nim r --cc:tcc  x.nim
  164.5 +- 1.2 ms     nim r --cc:tcc -d:release x.nim

Measured on a laptop without any care to clean the environment, except turning the performance governor. Even with `-d:release` compiling nim code is comparable.

The fact that tcc compilation cycle measures negative here is a nice punchline.

[1]: https://gist.github.com/ZoomRmc/58743a34d3bb222aa5ec02a5e2b6...

[2]: https://github.com/c-blake/bu/blob/main/doc/tim.md

It's worth pointing out that Nim is going to cache all of the compilation up to the linking step. If you want to include the full compilation time, you'd need to add --forceBuild to the Nim compiler.

(Since a lot of the stuff you'd use this for doesn't change often, I don't think this invalidates the "point", since it makes "nim r" run very quickly, but still)

There's also the Nim interpreter built into the compiler, "NimScript", which can be invoked like:

  #!/usr/bin/env -S nim e --hints:off
  echo "Hello from Nim!"

The cool thing is that, without --forceBuild, Nim + TCC (as a linker) has a faster startup time than NimScript. But if you include compile time, NimScript wins.

  • Yep, always forget about '--forceBuild'. You can see in the script above the nimcache directory was overriden to tmpfs for the measurement, though. Caching will be helpful in real usecases, of course.

    Nimscript is cool but very limited, not being able to use parts of the stdlib taht depend on C. Hope this will change with Nimony/Nim 3.

No, the coolest thing about tcc is that it is developed successfully wiki-style. Everybody can commit to the main branch (called mob). And it only gets better. No cooperation would allow that.