Hacker News new | past | comments | ask | show | jobs | submit login

The only other dynamic language with this kind of multithreading capability is, wait for it... Raku (aka Perl 6). And my impression is that Raku doesn’t get very high performance with its multithreading, which is mostly designed to improve I/O throughput (and because it’s a cool feature and Raku has never met a feature it doesn’t like).

Even among static languages, it’s a relatively rare capability: Go has excellent support (of course), C extensions like Cilk and TBB support it, Rust has something similar with tokio, and I’ve heard people claim that Haskell can do something similar with appropriate extensions.

> And my impression is that Raku doesn’t get very high performance with its multithreading

Could you elaborate on how you got that impression? Do you have any benchmarks that the Raku core developers could look at?

I recall seeing various benchmarks of Raku that were on the slow side—slower than Perl 5 / Python speed, which are already what I'd describe as "slow languages". I can't currently find what specifically I read, but https://www.reddit.com/r/perl6/comments/btvkoz/is_perl6_stil... seems to have some discussion (and I think you're on that thread, so I'm sure you're aware). This doesn't specifically address threading performance, but if the runtime is 100-500x slower than C, it's not like threading can make up that kind of performance deficit.

The Raku runtime is still improving, and several object creation benchmarks now outrun Perl. A low bar, some might argue. But still.

Threading can make a difference on non-IO bound tasks if you're interested in wallclock rather than CPU: for instance, `say (1..Inf).grep( { .is-prime } )[9999]` (showing the 10000th prime number) runs 22 seconds on my machine, but the threaded version of that: `say (1..Inf).hyper.grep( *.is-prime )[9999]` runs in 8 seconds. That's just by adding the `.hyper` method to the chain!

Here's a comparable thing in Julia:

    julia> using Primes, Lazy

    julia> @time drop(9999, filter(isprime, Lazy.range(1)))[1]
      0.119811 seconds (1.25 M allocations: 23.502 MiB)
The Lazy package doesn't support using threads yet since 1.3 was just released, so doing the threaded comparison isn't simple at the moment. However, this illustrates what I was getting at: the sequential Julia code is 185x faster than the the sequential Raku code and 67x faster than the threaded Raku code. It's great that Raku threading gets some scaling here (not sure how many cores you have, so it's unclear if 2.75x scaling is good or not, but it's not nothing). But it's considerably easier to scale if there's already a lot of performance on the table. The faster each operation is, the harder it is to make a threading implementation that has low enough overhead to make threads worthwhile. From the performance perspective, any effort spent on threading in Raku would be better spent on sequential speed until that has been maxed out.

I should also note that this is not how one would actually find the 10000th prime efficiently. For that you'd use the `nextprime` function also provided by the Primes package, like so:

    julia> @time nextprime(1, 10000)
      0.010456 seconds (17.00 k allocations: 265.562 KiB)
That's another 10x faster than the lazy sequence approach. Which mostly tells me that the lazy code is impressively efficient—I would have expected a dedicated function to have more of an edge. Lest anyone cry foul about using C or whatever, this function is implemented fairly straightforwardly in Julia:


Thank you for these goals :-)

Just for the record: yes, there are faster ways of finding the 10000th prime, but I use this example often as an example of a CPU-intensive task that can be spread over multiple threads easily.

Also, please note that all features of the example are built-in into Raku: no external module loading needed.

Guidelines | FAQ | Support | API | Security | Lists | Bookmarklet | Legal | Apply to YC | Contact