For Crystal is i = i.succ faster than i += 1

In this article on speeding up Ruby 3.3 - 3.4 it states the YJIT it can optimize this:

i = i.succ

better than this.

i += 1

Is this the case in Crystal, or it doesn’t make a difference?

1 Like

#succ is implemented as self + 1 so I don’t really see how that would be any faster than i = i + 1. So i’d vote it doesn’t really make a difference.

2 Likes

That article is quite interesting.

The situation in Crystal is completely different though because there is no interpreter to worry about. All code is compiled into very efficient machine code.
And the compiler understands that i += 1 and i = i.succ are semantically equivalent. So they both result in the same machine code.

2 Likes

Thanks. That’s what I thought when I looked at the sources code for succ.

In my updated Ruby primes-utils code it made a significant difference though.

I updated the code base to change all instances of x += 1 to x = x.succ and ran the before|after code on Ruby 3.3.6, Ruby 3.4-preview1 (with YJIT) and TruffleRuby 24.1.1. For each, the after code was clearly empirically faster.

In fact, for one test case, the time for 3.3.6 went from 29.8 secs to 24.5, for 3.4-preview1: 14.17 secs to 9.16 secs, and for 24.1.1: 35.1 secs to 24.1 secs.

So Ruby 3.4 is closing in on being not so far behind compiled code performance, at least for my heavy numerical computation based use case.

Correction:
TruffleRuby went 14.17s to 9.16 and Ruby-3.4-preview1 was 35.1 to 24.1 secs.

1 Like