Very slow build speeds for hello world

Crystal builds and runs programs much slower than expected on my system.


The program tested can be replicated by running crystal init hello and putting puts "hello world" into src/hello.cr and trying to run it.

I have seen others build programs much more complex much faster using crystal on their systems and other languages like rust and go compile programs much faster on my system.

Here are the benchmarks from hyperfine using command
hyperfine --warmup 3 "crystal ./src/hello.cr" --export-markdown ./Benchmarks.md

Command Mean [s] Min [s] Max [s] Relative
crystal ./src/hello.cr 5.001 ± 0.329 4.604 5.501 1.00

( s stands for seconds )
I am not sure what causes this and i am very new to crystal, any help would be nice.

This is somewhat of a known “issue”. See Incremental compilation exploration for some related discussion on why its a bit of a problematic thing to solve.

But it’s also relative to your hardware, as its pretty darn quick for me. I know the compiler really likes having fast single core perf, which can have a big impact like you’re seeing. So really comes down to what your system is :confused:.

Command Mean [ms] Min [ms] Max [ms] Relative
crystal test.cr 540.5 ± 21.8 511.7 577.7 1.00

Related: CPU Compile Speed Benchmarks

After using Crystal for a while, you will get used to it, considering the programming efficiency brought by Crystal, it is worth it.

Even, for Crystal only, you should purpose a new beast PC, that is how i did it, although only a AMD 7840hs, but the current development experience is acceptable.

1 Like

It’s pretty much impossible to draw any conclusions from your benchmark results, without any information about the system you’re running this on. Comparison with performance of other compilers (or any kind of benchmark really) could also provide some context whether the performance is expected or not.

Here is my full system information.
i posted the benchmark here because i felt it was an accurate measurement but my main concern is that compiling programs takes 5 seconds on my hardware.

Operating System: NixOS 24.05
KDE Plasma Version: 6.0.5
KDE Frameworks Version: 6.2.0
Qt Version: 6.7.1
Kernel Version: 6.6.31 (64-bit)
Graphics Platform: Wayland
Processors: 8 × Intel® Core™ i5-8250U CPU @ 1.60GHz
Memory: 7.6 GiB of RAM
Graphics Processor: Mesa Intel® UHD Graphics 620

here is another benchmark running clang++

hyperfine --warmup 3 "clang++ ./hello.cpp -o helloworld"
Benchmark 1: clang++ ./hello.cpp -o helloworld
  Time (mean ± σ):      2.004 s ±  0.039 s    [User: 1.699 s, System: 0.254 s]
  Range (min … max):    1.959 s …  2.079 s    10 runs

Crystal taking 2.5 times longer than clang seems quite reasonable.
The ratio is similar on my system. But the absolute times are significantly faster: 278ms and 908ms.

So it doesn’t seem there’s anything wrong with the Crystal compiler in particular. Your system performance seems to be very poor for some reason. The i5-8250U is a bit dated of course, but I would expect it to have more punch than what youre measurements show.

i5-8250U is a really bad(slow) CPU compare to Intel 12??? or 13??? or AMD zen3, zen4, my bet you really should update your’s hardware for to use Crystal.

I am not in the position to update my hardware right now (most things are working well enough), so i probably will not be able to learn/use crystal. I don’t think the laptop is too old, (4 years) but oh well.

It seems most people have a good experience but my specific hardware seems to just not work well with it.

You have similar “single core performance” as my Ryzen and my crystal hello.cr takes about 2 seconds (or less) . It looks like it’s a laptop:

  • try to find out if a thermal throtling isn’t the problem of worse than expected performance - if so, there may be a thick cohesive brick of dust in the fan from all the years :) :)

  • also make sure the CPU is not in some power saving mode (try tracking the current core frequencies during the benchmark - is it getting to maximums near 3.4 GHz)?

1 Like

Don’t give up on Crystal. I only use older hardware and love Crystal. Just try to minimize the times you compile the program.

5 Likes

Another aspect is how did you install Crystal. If you compiled it by hand, it might not be optimized (release mode).

Could also try doing like GC_DONT_GC=1 crystal build src/hello.cr. Based on Add `--no-gc` to `crystal build` · Issue #14223 · crystal-lang/crystal · GitHub, that gave 30% faster compilation times, at the cost of a bit more memory.

3 Likes

Core member here with a slow older CPU (Intel Haswell from almost 10 years ago). I feel the pain:

$ time crystal run hello.cr
Hello world!

real    0m2,260s
user    0m4,932s
sys     0m0,541s

But on recompile it ain’t that bad:

$ time crystal run hello.cr

real    0m1,676s
user    0m1,608s
sys     0m0,331s

BTW, for the PC selection, check

may be you can add your’s PC benchmark here, lets us check if there is any performance issue.

1 Like

Just wanna pop in to say an i5-8 is absolutely not a slow cpu and we should not be relying on new absurdly fast hardware to forget crystal’s compile time speeds - that alienates all those who can’t buy expensive hardware.

(5 seconds is also normal for me on windows, though it tends to be much faster in wsl)

4 Likes

True… But as one whose experience goes back to the 68000 (at a blazing 7.14Mhz), I’ll say there’s also a matter of mindset. What is “fast compilation” anyway? Sure, the Go compiler is much faster, but if I take half the time in Crystal coding an equivalent program, there’s room for waiting for the compiler.

(Not that I would mind a speedup of the compiler…)

So, yeah, I know it’s a bit rough in the beginning, but I think it pays off in the long run.

2 Likes

Note: on UNIX (and thus WSL) we can use fork to do the LLVM codegen in multiple processes, which we obviously can’t on Windows. This can explain some (maybe most?) of the “slower to compile on windows” behavior (check with crystal build --stats).

I tried to use threads instead of fork but I hit LLVM thread safety issues :sob:

An alternative would be add a crystal codegen command instead of forking, and to stream the LLVM IR from the main process to the codegen processes (similar to how its done in MT). That would be Windows compatible.

1 Like

This is a really important and frequently overlooked point.

3 Likes

Just curious, Is Crystal being used in Shopify’s internal projects?

I doubt it! Shopify created Sorbet and I’m pretty sure they are using that with their Ruby code, and very happy with it.

1 Like