Rust
allows you to turn off array index bounds checks like this:
let mut k = *some_array.get_unchecked(j);
...........
*some_array.get_unchecked_mut(j) = k - kn;
This ccurs in a code segment marked as unsafe
, but unsafe in Rust really just means the programmer has manual control, and better know what’s s/he’s doing, which I do for this code segment.
I’m doing this because this is part of an inner loop in this algorithm and significantly increases performance compared to the normal bounds-checked array version.
I was wondering is something like this possible in Crystal too?
1 Like
Great! But is this only available for >= 1.1.1?
No? That’s just the the latest version so the API docs default to it.
Is there anything comparable to an array.unsafe_write[]
?
Not technically, but I think it would just be like arr.to_unsafe[idx] = val
.
OK, here’s the deal.
In this code for reading, these didn’t have any performance difference.
x = ary.unsafe_fetch(j)
or
x = ary.to_unsafe[j]
But writing had a substantial effect: ary.to_unsafe[j] = x
Here are results for 2 large inputs, the second input is 2.5x greater than the first.
Before After
121s 117s
318s 308s
A really quick check of the docs didn’t find anything about .to_unsafe
.
I think this needs to be documented at least under performance Tips & Tricks
.
Now to see where else I can use this in my code that will make a difference.
Thanks @Blacksmoke16 .
jzakiya:
In this code for reading, these didn’t have any performance difference.
x = ary.unsafe_fetch(j)
or
x = ary.to_unsafe[j]
That’s expected, because they’re exactly identical.
Here you go: Array(T) - Crystal 1.1.1
Indexable::Mutable
is probably going to introduce a unsafe put method, then you don’t need to write to the buffer pointer directly.
opened 12:17PM - 18 Oct 17 UTC
closed 09:17AM - 09 Sep 21 UTC
status:discussion
topic:stdlib:collection
Just exposing something that was on my mind: Currently `Indexable` requires `siz… e` and `unsafe_at` to implement several reading operations on the container. Those are the classes that use `Indexable` now:
Array(T) BitArray Deque(T) Slice(T) StaticArray(T, N) Tuple(*T)
From those, Array, BitArray and Deque are always writeable, Slice and StaticArray are some times writeable (unsafe), Tuple is always read-only. So, Indexable assumes a read-only container and each one of them is responsible for the write operations they want.
Some operations are implementable on all writable indexable: sort, fill, shuffle, update, swap. It would be nice to either offer those operations directly in Indexable itself (bad for Tuple), or create another module for WritableIndexable (maybe with better name), so that all containers can benefit from these functions. This way Array would have less specific things.
Btw, with this change there would be almost no reason to keep Array at all, Deque could be renamed to "Array" as it is at most as fast as Array, and is sometimes faster.
2 Likes
Thanks again for the info.
I learn something new almost everyday from the forums.