News for hackers. Stuff that matters.
Re:How to speed up the Rust compiler in 2018 by olavk on Monday April 30, 2018 @05:49AM (#16957176)
I find it interesting because of the novel approach to memory management. It is deterministic and zero-overhead like C, C++ and similar, while at the same time safe like garbage collected languages. I think of it like a compile-time garbage collection.

I wouldn't use it as an alternative to garbage collected languages since garbage collection is just simpler overall, but I would consider using it as a safer alternative to C or C++.

Re:How to speed up the Rust compiler in 2018 by danieldk on Monday April 30, 2018 @06:13AM (#16957288)
I wouldn't use it as an alternative to garbage collected languages since garbage collection is just simpler overall,

I do not disagree, but I think one could argue to the contrary as well.

Since most garbage collected languages do not guarantee that objects are actually (timely) garbage collected, you cannot tie the lifetime of other resources (file descriptors, sockets, locks) to object lifetimes. So, the burden is on the programmer to ensure that resources are correctly finalized. Whereas in RAII languages you can properly tie all finalization to object lifetimes.

Note: I am not arguing that GC-ed languages cannot do RAII. AFAIR D has a GC and supports RAII.

Re:How to speed up the Rust compiler in 2018 by olavk on Monday April 30, 2018 @06:26AM (#16957344)
This is true - for example, C# has the `using` block to ensure resources are deterministically released when they go out of scope, not when they at some point later are garbage collected. I would still argue C# is much simpler than Rust since for most object you don't have to worry about this. But I guess there is a certain extra complexity in C# because you actually have to know if a class owns some external resource or not, while this distinction is not necessary in Rust.
Re:How to speed up the Rust compiler in 2018 by moomin on Monday April 30, 2018 @08:15AM (#16957881)
In practice that's rarely an issue, because a) if it has a resource it'll implement IDisposable and b) my IDE screams when I don't dispose an IDisposable.

This is not as good as the Rust model, but it's not awful, either.

Re:How to speed up the Rust compiler in 2018 by olavk on Monday April 30, 2018 @08:30AM (#16957990)
Yes but that is just the compiler offloading some of the static analysis to the IDE. The difference might not matter if you are always in an IDE anyway, but the language would be safer if this was an actual compiler error.
Re:How to speed up the Rust compiler in 2018 by jerf on Monday April 30, 2018 @09:17AM (#16958306)
In most modern languages, there is some way to tie object cleanup to a scope, even for a GC'd value. Note I say "cleanup", as in "I closed the file handle" or something, not "finalization" which is a GC-specific term. It isn't necessarily as rigorous as RAII but it works in principle in much the same way. "with" in Python, for instance, "defer" in Go (less automatic but if used properly fits the 80/20 nature of Go), Haskell has a motley crew of solutions, most other languages you can put something together yourself if nothing is provided.

Where things get complicated is when you don't have a clear scope to tie lifetime to and so you can't use these, but then, that applies to RAII too.

I'm not saying C++ doesn't have a bit of an advantage here, but I think it often gets oversold as "C++ has RAII and other languages have nothing even remotely resembling it", which isn't true.

In practice this isn't a problem that I encounter in GC'd languages anywhere near often enough to justify even a slight preference for a "true RAII" language.

Re:How to speed up the Rust compiler in 2018 by danieldk on Monday April 30, 2018 @10:42AM (#16958894)
It isn't necessarily as rigorous as RAII but it works in principle in much the same way.

I would say that in principle they work very differently ;).

They work superficially in the same way in that if you tie a particular object to the current scope in a RAII language, the cleanup happens at the same point as defer, with, try-with-resource, etc. would. However, there are cases where you really want cleanup to be tied to the object's lifetime.

For example, I have a Tensorflow binding for Go. However, I cannot pass Go-allocated memory (e.g. memory allocated to a slice), because Go does not allocate slice memory on 32-byte boundaries (using Go memory would cause an allocation + memcpy in Tensorflow to align the memory). So, you allocate memory in C-land and have Go structs that wrap your pointers. However, now cleanup becomes interesting. You do not want to rely on finalizers, since they are not guaranteed to run. However, using a Close method is also an annoyance. For tensors that live for the duration of a graph run, it is fine (you can use defer), but other tensors live longer and are reused between runs, shared by models, etc. It becomes unclear pretty quickly who is responsible for closing the model.

I also use a Tensorflow binding for Rust, which is drastically more convenient in this respect. Since ownership is clear, the lifetime of a tensor is bound to the scope or object that owns it. If the owner is dropped, the tensor is also dropped. If you need to share a tensor, you make an Rc/Arc the owner.

Re:How to speed up the Rust compiler in 2018 by jerf on Monday April 30, 2018 @10:54AM (#16959022)
Well, to be honest, my position has consistently been that using Go for scientific programming is not a good idea, and will never be a good idea because the Go team is never going to give you the features you need for it, and that you probably should just use Rust. (Or something else. Rust is not the only choice.) The Go answer is probably that, yes, you need a .Close method, and yes, I agree that in this use case that's really annoying and I would suggest this argues against using Go for this.

People tend to then get annoyed at me for expressing this opinion, but this sort of thing is the reason why. Go is really only merely adequate at interfacing with libraries in other languages [1] which scientific programming does a lot of, and Go has a type system that seems almost precisely tuned to get in your way if you try to program mathematical code in a typed manner but at the same time isn't so weak that you can pull something like a NumPy where at the Python level everything is just untyped so as long as you assemble it correctly up there, the C level can work it all out. Nor can you practically program in that manner, because while you can slather interface{} everywhere, you can't make it convenient to work with like a dynamically-typed language. I think Go is approaching maximally pessimal for scientific-type programming, personally.

I should clarify that when I say Go has "something like" RAII, I do mean pure-Go code only. And by no means is "defer" perfect. (I'm definitely in the camp that it should have been block scoped, not function scoped, and the performance hit can be quite annoying.) It's just that, as I said, it's not like the choice is "either RAII or you're in some manual-management only horrorland"... lots of languages have block-scoped constructs (not just Go) that can be used to 80/20 RAII. That last 20 may be important in some cases, but it's quite often a great deal less important than the 80.

(This post is brought to you by your friendly local "HN poster who has been accused of being unreasonably positive about Go".)

[1] Pretty much every modern language claims to have "great" interfacing with C, despite IMHO wild variances in difficulty. Go is "adequate" because it's not too difficult to simply call a C function, and with not much labor you can get binary-level-compatible structs between the two, which is a nice advantage over Python or Perl or something. But the semantic mismatch is pretty rough around memory management and threading model, and that manifests in slowness in the calls in addition to general semantic mismatch.

Re:How to speed up the Rust compiler in 2018 by mratsim on Thursday May 03, 2018 @04:40AM (#16984293)
Rust is better than Go for sure (cough Generics) but it's already hard enough to fight the mathematics, statistics and machine learning, scientists will not want to fight the Rust syntax as well.

For me, the most promising compiled and statically-typed language for scientific computing is Nim.

Disclaimer: I am the author of a Numpy/Torch/Tensorflow-like library written from scratch in pure Nim, the look and feel is pretty similar to Python Pytorch + Keras for neural networks: https://github.com/mratsim/Arraymancer

Re:How to speed up the Rust compiler in 2018 by danieldk on Monday April 30, 2018 @11:13AM (#16959241)
Well, to be honest, my position has consistently been that using Go for scientific programming is not a good idea, and will never be a good idea because the Go team is never going to give you the features you need for it, and that you probably should just use Rust. (Or something else. Rust is not the only choice.) The Go answer is probably that, yes, you need a .Close method, and yes, I agree that in this use case that's really annoying and I would suggest this argues against using Go for this.

That's a good point. Go was my camping ground while Rust was still breaking every month and I didn't want to go back to C++. Although I don't use Go anymore, I have come to appreciate its simplicity and in a lot of scenarios I would definitely recommend it.

Re:How to speed up the Rust compiler in 2018 by Const-me on Monday April 30, 2018 @02:40PM (#16961099)
> So, you allocate memory in C-land and have Go structs that wrap your pointers. However, now cleanup becomes interesting. You do not want to rely on finalizers, since they are not guaranteed to run.

I did similar thing with C# more than once. Not with TensorFlow, but with my only C++ libraries that also used SIMD and therefore required aligned memory buffers.

It worked just fine. There’s IDisposable for deterministic cleanup, and finalizers as a safety net. Unmanaged interop, i.e. [DllImport], is supported on all platforms, e.g. on Linux it imports from *.so libraries.

Re:How to speed up the Rust compiler in 2018 by kazagistar on Monday April 30, 2018 @10:42AM (#16958899)
> Where things get complicated is when you don't have a clear scope to tie lifetime to and so you can't use these, but then, that applies to RAII too.

Sure, but Rust does help here specifically: resources can safely be moved into child or parent scopes.

Re:How to speed up the Rust compiler in 2018 by Const-me on Monday April 30, 2018 @11:44AM (#16959559)
> I would consider using it as a safer alternative to C or C++

I would, too. But there’re problems for which C or C++ is just faster because of language/compiler extensions like SIMD intrinsic or OpenMP.

Also Rust can’t be used for GPU code; strictly speaking C can’t either, but practically CUDA, C++ AMP, OpenCL are very close to C and/or C++.

Also if you have to deal with lots of pointer-based data structures (trees, graphs, etc)., and it’s not just on the lowest level you can abstract away behind a safe API, I don’t think Rust is safer. To get performance comparable to C++, it’s necessary to use unsafe rust for raw pointers, and IMO modern C++ is safer that unsafe Rust.

Re:How to speed up the Rust compiler in 2018 by pcwalton on Monday April 30, 2018 @05:26PM (#16962551)
How is modern C++ safer than unsafe Rust?

In Rust, the borrow check is still active even in unsafe blocks. In C++, however, the complex rules around when destructors are called, combined with references, are a constant use-after-free footgun that you can never eliminate.

Rust projects that use unsafe code are empirically safer than C++ projects. See, for example, the Servo style system as used in Firefox.

Re:How to speed up the Rust compiler in 2018 by Const-me on Tuesday May 01, 2018 @04:37AM (#16965424)
> the borrow check is still active even in unsafe blocks

When you deal with pointer-based structures (trees, graphs, etc.) you’ll use raw pointers for them. Raw pointers are not borrow checked, and the complete list of pointer-related potential bugs applies to unsafe Rust, you can use after free, double free, mess with pointer arithmetic so you’re out of bounds, etc.

> In C++, however, the complex rules around when destructors are called, combined with references, are a constant use-after-free footgun that you can never eliminate.

C++ ecosystem has lots of stuff that help writing correct code despite unsafe language. Debug builds use special version of heap that fills freed memory with a magic number, this help to catch most UAF bugs very early in the development. There’re runtime tools like valgrind and asan. There’re static analysis tools like PVS studio, clang static analyzer, and coverity.

Unsafe Rust has none of them. Not even a debug heap.

> Rust projects that use unsafe code are empirically safer than C++ projects.

Survival bias: people who need raw pointers and other performance-related features like SIMD and manual RAM layout don’t pick Rust for their projects.

Re:How to speed up the Rust compiler in 2018 by pcwalton on Tuesday May 01, 2018 @11:50AM (#16968095)
> Unsafe Rust has none of them. Not even a debug heap.

Sure it does! I've used most of those features in Rust, except for Address Sanitizer. But even ASan is available now: https://github.com/rust-lang/rust/pull/38699

I remember spending hours using Valgrind on Rust code back in 2011 to track down codegen problems in the compiler :)

Re:How to speed up the Rust compiler in 2018 by burntsushi on Tuesday May 01, 2018 @06:49AM (#16965950)
Respectfully, you're missing one of the most important parts of Rust. Rust isn't just about reducing or eliminating the use of `unsafe`, it's the ability to build an API that might use `unsafe` internally but is safe to use externally. You can't do that with C++.

I also think many of your points over generalize. Finite state machines are graphs for example, but I've never needed to use raw pointers to achieve the performance required. Similarly, I definitely need SIMD, and I use Rust for that.

Re:How to speed up the Rust compiler in 2018 by Const-me on Tuesday May 01, 2018 @08:00AM (#16966288)
> You can't do that with C++

I can, and I do. The trick is to use some other safer language for less performance critical higher level code. C# often works well for me but there’re others, e.g. in data science community Python is quite popular for that role.

> I've never needed to use raw pointers to achieve the performance required.

Very likely, we work on different kinds of projects. One of my ongoing project is a CAD/CAM app for Windows, and I have implemented quite a lot of pointer-based stuff to optimize the performance. Technically they are mostly graphs, logically they’re multi-level hierarchical containers, LRU caches, quad-edge structures, scene trees, external indices, etc.

P.S. Why do you think Mozilla doesn’t use Rust for their DOM tree implementation, and instead relies on the JavaScript runtime and it’s GC? Don’t you think sometimes other people might also want DOM-like structures in their apps, be it for a web page, XML document, objects hierarchy in 3D space, or any other kind of data?

Re:How to speed up the Rust compiler in 2018 by burntsushi on Tuesday May 01, 2018 @10:13AM (#16967156)
You're just moving the goalposts. Pretending an entire language barrier is the same as the barrier between Rust's safe/unsafe is kind of ridiculous. The friction for use is on a completely different scale, not only in terms of convenience but performance as well. For example, a regular expression library might use unsafe internally, but forcing every use of that library to operate in a higher level language to achieve safety is simply a non-starter.

> Very likely, we work on different kinds of projects.

I work heavily with finite automata. Similar libraries written in C or C++ use pointer based stuff quite heavily, but none of it has so far turned out to be necessary in Rust while also achieving comparable performance.

This continues to miss the point that Rust permits building safe abstractions over unsafe internals. Even if you need to use raw pointers in Rust, you're not only no worse off than you are in C++, but you can actually encapsulate that use in a way that is guaranteed by the type system without resorting to using a completely different programming language.

> Why do you think Mozilla doesn’t use Rust for their DOM tree implementation

I'm not involved with that project, so I wouldn't know, and I wouldn't speculate. You shouldn't either.

Re:How to speed up the Rust compiler in 2018 by Const-me on Tuesday May 01, 2018 @06:40PM (#16972407)
> Pretending an entire language barrier is the same as the barrier between Rust's safe/unsafe is kind of ridiculous.

I’m not pretending that. Just two points.

1. If you really need unsafe code, because raw pointers, or other reasons, C++ is safer than unsafe Rust.

2. If your project has two distinct parts, unsafe lower level, and safer higher level, you don’t need to use C++ for both. Real world software use multiple languages in the same project for decades already, e.g. QuakeC was developed in 1996.

> a regular expression library might use unsafe internally

If a library wants to do that, it probably means that safe language is too slow :-) https://github.com/dotnet/corefx/tree/master/src/System.Text...

> I work heavily with finite automata.

I’m not saying Rust is useless. There are projects where it shines, and where I’d probably picked it myself. Like a web browser CSS engine, or your finite automata, or many other things.

I’m saying that there’re large problem areas out there for which, due to various reasons, other languages are still way better than Rust. I do realize Rust evolves fast; eventually these areas might shrink or disappear. But in its current state, my opinion is the applicability is limited to very narrow areas: no bare metal, no SIMD, no GPU APIs, very limited asynchronous IO, limited embedded options, very limited numeric libraries, no GPGPU…

I’ve only listed the areas where I have recently (last couple of years) developed substantial amount of code in any other language.

It just happened that I didn’t work on either finite automata, nor browser CSS engines.

Re:How to speed up the Rust compiler in 2018 by burntsushi on Wednesday May 02, 2018 @07:30AM (#16975909)
> If you really need unsafe code, because raw pointers, or other reasons, C++ is safer than unsafe Rust.

I don't agree. I've told you why. I find speaking with you very frustrating, and it's not clear to me that you've actually understood my point unfortunately. :-/

> If a library wants to do that, it probably means that safe language is too slow

That doesn't make any sense.

Re:How to speed up the Rust compiler in 2018 by Const-me on Wednesday May 02, 2018 @07:17PM (#16981992)
> I find speaking with you very frustrating

Yeah, same here. You’re insinuating things I didn’t said nor meant.

> it's not clear to me that you've actually understood my point

I disagree with your points, and I've told you why.

Re:How to speed up the Rust compiler in 2018 by littlestymaar on Wednesday May 02, 2018 @04:08AM (#16974985)
> P.S. Why do you think Mozilla doesn’t use Rust for their DOM tree implementation, and instead relies on the JavaScript runtime and it’s GC? Don’t you think sometimes other people might also want DOM-like structures in their apps, be it for a web page, XML document, objects hierarchy in 3D space, or any other kind of data?

Nothing prevents you from writing a DOM tree in Rust, but when in comes to the Web DOM you need to interact with JavaScript and with the JS GC no matter what you do. How is DOM managed in other browsers written in C++ ? I would be surprised if it wasn't also handled by the JavaScript runtime.

Re:How to speed up the Rust compiler in 2018 by steveklabnik on Monday April 30, 2018 @12:02PM (#16959720)
SIMD is coming in eight weeks, incidentally.
Re:How to speed up the Rust compiler in 2018 by Const-me on Monday April 30, 2018 @01:36PM (#16960553)
Good to know!

But even if it’ll become available in 2 months, it’ll take some time to develop Rust libraries on top of them.

E.g. in various performance-critical C++ projects I have used https://github.com/Microsoft/DirectXMath and https://eigen.tuxfamily.org

Both are quite large projects with many man-years spent to develop, they saved quite a lot of my development budget.

Re:How to speed up the Rust compiler in 2018 by steveklabnik on Monday April 30, 2018 @02:38PM (#16961089)
Yes and no, a lot of libraries have been built on top of the feature while it was unstable. It’s been in nightly for quite a while at this point.

Of course, more libraries are needed as well, but there’s already some higher level stuff. See https://github.com/AdamNiederer/faster for example. And const generics, coming to nightly near the end of the year, will be another step up. It's true overall that numeric stuff is a weakness, but we'll get there!

Re:How to speed up the Rust compiler in 2018 by SomeHacker44 on Monday April 30, 2018 @12:26PM (#16959937)
> It is deterministic and zero-overhead

I wouldn't say zero-overhead. I would say O(1) overhead in the best case, and equivalent to C-style manual memory management in the typical (which again isn't zero-overhead and isn't even necessarily always O(1) overhead with heavy allocation and deallocation).

But, yes, it isn't GC'd with the attendant challenges GC poses (or benefits it brings).