Can you please provide code with wrapping operators that works with 0.34.0 (and sooner w/o -Ddisable_overflow
)? There’s no point in compiling code against 0.34.0 that doesn’t work in the correct way.
The above code examples 1) and 2) compile with 0.34 without -Ddisable_overflow
as I stated, as well as 2) with 0.33.
@jzakiya I think what everyone is trying to say here is that the overflow checks are expected to be slower than not doing overflow checks. If you were compiling your code in 0.33.0 with -Ddisable_overflow
and you want the same behavior for 0.34.0 then your only option is to stop using +
, -
, etc. everywhere and use &+
, &-
, etc.
Doing testing on a more “quiet” system (limited background threads use) the time differences between 0.33 and 0.34 disappear, and are sameish. So that won’t make any difference, since overflow was occurring at only one place.
Plus if that really matters, then the default behavior should be to internally use the &
wrappers for all the arithmetic symbols. If it’s always more accurate and faster to use &+
versus +
why make users populate their code with the longer versions, in order to get more accurate/faster results?
But, the stripped binaries for 0.34 are always at least 20KB greater.
To test this, I compiled puts "Hello World!''
, and the stripped binaries were: 0.33 - 393528 bytes and 0.34 - 397640, 4KB greater.
So, 0.34 inherently comes with more baggage vs 0.33, thus overall, offers no tangible benefits for running this specific code.
Not a criticism, just an observation for this one specific use case.
As you add more overall features/capabilities I would expect this to occur in a pre 1.0 development release. As long as there’s no significant performance or accuracy impediments I’m good with it. Rust binaries were “hugemongous” initially, until lately, so it’s par for the course.
It doesn’t matter where the overflow was happening. Whenever you use +
or -
, the runtime will check for overflow under the hood. So in your code, overflow checking is done everywhere except where you now use &-
.
It’s not always more accurate. If you have a counter and it overflows, that’s usually an error. Say you are counting number of beds in a hospital with Int32. You really don’t want to end up with -2147483648 beds. That’s why +
will raise by default, to prevent you from getting to that state.
In fact, it’s very unusual to want to have wrapping operators by default. Only in very specific bitwise or math situations you want that. Which might be your use case, but I’m not sure.
We never case about binary size because disk space is not a limited resource, much less 20KB (I know, I know, embedded systems, but that’s not our target).
Oh thit, I thought it was the other way around. Now what you said makes sense. That wasn’t clear from reading the docs/blog on this. Let me go back and change things to see the effect it will have.
I understand for desktops/laptops binary sizes aren’t a big issue, however they are if you’d like Crystal to be used in embedded systems where memory is a premium. That’s why Matz (with funding from the Japanese government) created MRuby, specifically for those environments.
Can’t reproduce this building on Ubuntu using Crystal’s default dockerfiles. What OS are you on and which test setup did you use?
$ echo 'puts "Hello World"' > test.cr
$ docker run --rm -it -v $(pwd):/app -w /app crystallang/crystal:0.34.0 crystal build test.cr -o test.34 --release --no-debug
$ docker run --rm -it -v $(pwd):/app -w /app crystallang/crystal:0.33.0 crystal build test.cr -o test.33 --release --no-debug
$ ls -l test.3*
-rwxr-xr-x 1 root root 473696 Apr 9 00:25 test.33
-rwxr-xr-x 1 root root 474016 Apr 9 00:25 test.34
$ strip test.33
$ strip test.34
$ ls -l test.3*
-rwxr-xr-x 1 root root 392592 Apr 9 00:26 test.33
-rwxr-xr-x 1 root root 392584 Apr 9 00:26 test.34
Here’s the system and environment that produced the posted results.
➜ ~ inxi -MSC
System: Host: localhost.localdomain Kernel: 5.5.10-pclos1 x86_64 bits: 64 Desktop: KDE Plasma 5.18.4 Distro: PCLinuxOS 2020
Machine: Type: Laptop System: System76 product: Gazelle v: gaze10 serial: <superuser/root required>
Mobo: System76 model: Gazelle v: gaze10 serial: <superuser/root required> UEFI [Legacy]: American Megatrends
v: 1.05.08 date: 03/31/2016
CPU: Topology: Quad Core model: Intel Core i7-6700HQ bits: 64 type: MT MCP L2 cache: 6144 KiB
Speed: 3100 MHz min/max: 800/3500 MHz Core speeds (MHz): 1: 3100 2: 3100 3: 3100 4: 3100 5: 3100 6: 3100 7: 3100
8: 3100
hello_world.cr => puts "Hello World!"
For both 0.33 and 0.34
$ crystal build hello_world.cr --release
$ strip hello_world
20KB for an executable that can’t accidentally overflow its arithmetic might be considered worth it…Do you want your math to accidentally be able to wrap, by default? This isn’t like in Ruby, where if it overflows it gets auto promoted…though come to think of it that would be an interesting class to have “AutoPromotableInt” or something, that moves to BigInt if it overflows. Or maybe BigInt is already efficient enough under the covers for that type of use and we could just use that :)
Here’s my size results in Ubuntu 19.04
hello_world 0.33 755040
hello_world 0.34 773248
hello_world 0.33 stripped 392544
hello_world 0.34 stripped 400736
It increased by a few percentage.
On OS X
hello_world 0.33 417656
hello_world 0.34 418328
hello_world 0.33 stripped 332264
hello_world 0.34 stripped 332264
hello_world.dwarf 0.33 418129
hello_world.dwarf 0.34 423462
So small percent increase again.
Doesn’t seem too extraordinary… :| Though overall still seems a bit large, would be a fun endeavor to try and figure out how to get it smaller, but I’m not too worried about it ATM. :)
Why the push toward 1.0?
This is from 2016, about the quest for the smallest Rust binary (Rust is inherently smaller now).
https://lifthrasiir.github.io/rustlog/why-is-a-rust-executable-large.html
Also FYI: mruby - about
The huge portions of those binaries are really just stdlib baggage you don’t actually need for such a tiny program printing hello world. You can easily shrink it by not including stdlib but rolling your own.
Seems this was never posted on the forum, and perhaps very few people have seen it at all.
Well, according to the comments at least 11 people outside the core team. And it was also posted on reddit with 80+ upvotes, so word should have made it around.
From ysbaddaden:
I’m not fond of where this is all going. The nice & fun of Crystal is slowly eroding away
Well, that hurt to read.
What’s this issue with Exhaustive pattern matching for case stuff? Context.
If the developer doesn’t have the right type to match, that’s their problem. That’s not a issue of the language. Especially considering Crystal is statically typed… wait a minute… unions: hold my beer!
This is one of the downsides of open source. People want features that other developers don’t think are necessary. This cycle repeats itself too and is never-ending. There is nothing wrong with a language having core values that are set in stone, and having developers adapt.
What’s that supposed to mean? Unions are completely statically typed.
Also, it is quite normal for any project, whether it’s open source or not, that there are different opinions on the way to go forward. If we all shared the same opinion, it would be a sign there’s something very wrong!
Where can I find that remark from ysbabadden?
Unions are not statically typed.
The type of a variable or expression can consist of multiple types.
You just brought up another negative of open source. Assuming change is good…
@ganymedes here: https://github.com/crystal-lang/crystal/pull/8424#issuecomment-610808655
What does this mean?