News for hackers. Stuff that matters.
Re:Four Years of Rust by pornel on Wednesday May 15, 2019 @01:41PM (#19921849)
There are already several decent GC languages. If Rust was just another GC language, I don't think it would have attracted such a strong community required to develop all of these things and break out of obscurity. It'd be another Go with generics, or Elixir-native, or Swift with uglier syntax.

In the no-GC no-runtime niche for a very long time there was nothing viable besides C and C++. For programmers who want C-like level of control, performance and low-level compatibility there are very few alternatives, and if you want non-crash-prone parallelism on top of that, there's nothing but Rust.

Re:Four Years of Rust by dpc_pw on Wednesday May 15, 2019 @03:56PM (#19923108)
I don't really understand why people would want a GC over deterministic destruction like in Rust. GC is [neither necessary nor sufficient](https://ruudvanasseldonk.com/2015/10/06/neither-necessary-no...). Ownership model in practice is much more convenient precisely because objects can act like resources and implement their cleanup logic, and the business logic can rely on it. It's a great improvement in any imperative PL.

I have (re-)implemented couple of real-life projects, and each time Rust was much better higher-level language than eg. Java, Python or JS. Borrow checker fights are non-issue in practice: just avoid references, pass messages as copies and when you have to share data use `Arc` and copy on write (or just add `Mutex`).

There's a reason why Rust is most loved PL for 4 years in a row. Once you try it, and get past initial adjustments (mosty: what owns what relationship) everything clicks, and I guarantee that you won't miss GC at all.

Re:Four Years of Rust by pjmlp on Wednesday May 15, 2019 @04:24PM (#19923373)
Because having a GC doesn't mean throwing away deterministic destruction.

Many GC enabled system languages do offer both mechanisms.

It is a matter of enjoying productivity it offers, while having the tools to fine tune performance when it actually matters.

Re:Four Years of Rust by dpc_pw on Wednesday May 15, 2019 @05:47PM (#19924104)
> Many GC enabled system languages do offer both mechanisms.

?

Can you give me an example? Java's `finalize` is not deterministic destruction. D's scope guards (or Go's `defer`) are also not like destructors, because a calling code has to take care of them.

> It is a matter of enjoying productivity it offers,

There's hardly any productivity gain, and it is being offset by productivity gained by a reliable and hassle-free resource management.

Re:Four Years of Rust by manwe150 on Wednesday May 15, 2019 @11:00PM (#19925781)
Not exactly a systems language, but Python has deterministic destruction (due to the use of reference counting) of non-cyclic data structures.

Edit: Oh, and if you don’t think that’s enough, note that Rust doesn’t guarantee destruction to ever occur in that case (“considered safe”): https://doc.rust-lang.org/book/ch15-06-reference-cycles.html

Re:Four Years of Rust by kevinmgranger on Wednesday May 22, 2019 @11:57AM (#19982550)
> Python has deterministic destruction

Not quite.

https://docs.python.org/3/reference/datamodel.html#object.__...

> It is not guaranteed that __del__() methods are called for objects that still exist when the interpreter exits.

Re:Four Years of Rust by dpc_pw on Thursday May 16, 2019 @12:41AM (#19926175)
Oh, interesting. But from what I read it's only an implementation detail of CPython?

With `with`I can't eg. pass an open file to another function to eg. be closed there etc.

Example:

https://play.rust-lang.org/?version=stable&mode=debug&editio...

closing `File` will happen at the end of `foo` or `foo2`.

Re:Four Years of Rust by manwe150 on Thursday May 16, 2019 @12:21PM (#19930360)
That's probably a tricky question, since CPython is also essentially the spec. PyPy talks a bit about this: http://doc.pypy.org/en/latest/cpython_differences.html#diffe...

That's true, since Python has reflection it can't easily optimize that case, whereas that's a powerful benefit of having a linear type system for tracking ownership like Swift or Rust. But early freeing (which Rust has and Python does not) is slightly different from deterministic freeing (which both have) is slightly different from guaranteed freeing (which CPython has and Rust does not).

Re:Four Years of Rust by pjmlp on Thursday May 16, 2019 @12:31AM (#19926132)
D structs have destructors, for example.

Dealing with borrow checker on cases that are still being worked on (NLL 2, GUI callbacks), using unsafe for graphs or dealing with use-after-free array indexes for the alternative workaround, unsafe Drop implementations, doesn't look hassle free to me.

Re:Four Years of Rust by dpc_pw on Thursday May 16, 2019 @12:58AM (#19926255)
D's destructors are not deterministic, IIRC.

> using unsafe for graphs or dealing with use-after-free array indexes for the alternative workaround, unsafe Drop implementations, doesn't look hassle free to me.

Valid points, but these are rare problems in idiomatic Rust.

Specifically avoiding graphs by structuring code into a tree of ownership, has greatly improved architecture of my programs, to the point that I just do it like this in all programming languages I use.

Rust made me realize how many problems objects carelessly cross-referencing each other (especially in OOP) - "because there's a GC, so why not" create.

Similar with array of indexes - great improvement both in usability and reliability. At least all use after-free in that case is checked and fails deterministicly. It makes my data with graph-like, or relationship properties resemble relational database.

For problems with lifetimes in destruction all I needed so far is https://crates.io/crates/dangerous_option . I actually wish it was part of language (a nullable types, panicking at runtime).

Re:Four Years of Rust by pjmlp on Thursday May 16, 2019 @02:40AM (#19926710)
> D's destructors are not deterministic, IIRC.

Yes they are, they get called at the end of scope.

> Valid points, but these are rare problems in idiomatic Rust.

Being rare doesn't mean they aren't there, and anyone trying to write UI related code will deal with them on regular basis.

Re:Four Years of Rust by dpc_pw on Friday May 17, 2019 @05:47PM (#19943870)
https://forum.dlang.org/thread/[email protected]...

Can you clarify, what am I misunderstanding here? In couple of places online I've found that you can't depend on dtor being called.

Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @05:03PM (#19923747)
As pjmlp said below, GC doesn't preclude deterministic destruction, so it isn't about resources in general; it is largely about memory. Also typical programs in any language have quite a bit of stack-allocatable data and C/C++/D/Go/Rust do support stack-allocatation, so the memory heap isn't involved everywhere.

Wherever the memory heap is involved, if the system isn't memory-starved, it can be argued that deterministic free-ing is a step too far; maybe you don't want time to be spent putting that long-ish list of heap-allocated values on the free list when exiting a function on the critical path. There is something to be said for lazy operations in such contexts, which the GC can provide (off the critical path - using GC.disable() in D) - a lot easier than a "region-based" memory management solution in C/C++/Rust. I don't know of a synthetic benchmark result to tilt the argument either way.

At a system level, it is slightly dismaying that the "back-pressure" required to trigger lazy operations is only present for memory, and only within a Unix process; when it comes to limits on open file handles or sockets or overall OS memory usage, there is no back-pressure to reclaim them - indeed no mechanism to lazily schedule files/sockets for closure.

Re:Four Years of Rust by dpc_pw on Wednesday May 15, 2019 @05:57PM (#19924192)
> indeed no mechanism to lazily schedule files/sockets for closure.

It's not only about file sockets. It's about your core abstractions. Thread-pools, channels, flushing streams, events and other stuff, unlocking Mutexes, auto-validating guards etc...

I have production or semi-production experience with code written in C, D, C++, Python, Go, Java, Node, Scala, Rust and others (please excuse argument from authority, but that's all I have right now) so I can tell the difference and I think ...

... people that haven't worked with Rust long enough greatly under-appreciate number of stuff that benefit from deterministic resource-like management - not only on system resource usage / performance side, but simply the day to day reliability and writing simple bug-free code with ease.

Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @06:59PM (#19924621)
I wasn't talking about necessarily temporal operations like mutex ops; of course, they should be deterministically done - it is a beautiful implementation detail that it falls out of the principles of Rust, without explicit compiler support and/or "checked-delete" as is required in most other languages.

I meant lazy operations for avoiding unnecessarily making things like memory deallocation temporal. Unless you have a strict memory budget (and you might additionally need to have mitigation for memory fragmentation), freeing whenever GC deems it fit, or streams flushing whenever the OS/library deems it fit, can't be worse - but could potentially be better - for performance than being done only at points decided arbitrarily by the language and the program structure. It is simply easier to disable GC on critical paths.

But as you say, you are not (only) talking about performance. You are talking about determinism for predictability. I hope you are not implying predictability across various threads/processes that make up the system, only within 1 thread/process where that predictability leads to reliability.

Reliability across threads/processes needs strategy because failures are inevitable (yes, I have drunk the Erlang kool-aid too, among other ones). While I have no doubt that Rust's design principles would support developing such strategies, I do wonder as to what scale this would work up to ...

... as you say, I don't know the size of projects Rust has scaled to, I just know enough about Rust itself to balk at its complexity (and I am a C++ person!). Maybe we are just talking from different viewpoints. You, having done a variety of non-trivial production code in a plethora of languages, plump for Rust. But I honestly wonder about the size & longevity of your C/C++ semi-production code - semi, because it is C/C++ ;-) - I have worked on large C++ codebases for long-lived products, and I somehow can't see another complex language solving more problems net-net.

Re:Four Years of Rust by dpc_pw on Wednesday May 15, 2019 @08:25PM (#19925074)
> I meant lazy operations for avoiding unnecessarily making things like memory deallocation temporal.

Yes, I wasn't talking about real-time/performance consideration. The root post was along the lines of "Rust is nice, but I like productivity of a GC". I'm saying deterministic destruction is more productive for the developer and Rust makes a great high-level language.

Regarding stuff like non-blocking deallocation etc. You can still do it in Rust if so you desire. In the a destructor, enforced by the type, you can use nice abstractions, etc. and eg. defer deallocations, or draw memory from an arean. I think eventually Rust will just have more or less standardized type for GCs and graphs with explicit roots etc.

But sure, it is all still very new here, so if one is writing a real-time trading or OS, maybe they should stick to C/C++.

> But I honestly wonder about the size & longevity of your C/C++ semi-production code - semi, because it is C/C++

In C I worked on code powering embedded chips (mostly radio communication, kernel modeules) and eg. real-time hypervisor powering some high-end cars. In C++ eg. some high-perf data management stuff (data dedupilcation, encryption, etc.) in a SV unicorn. I actually would describe myself as C (as opposed to C++ person), but I know my around modern C++ quite well - i just really don't like working with it.

> I somehow can't see another complex language solving more problems net-net.

I don't think Rust is actually that complex. It is definitely bigger than C, but I think it's much smaller than C++. And it is sane. Thinks play well together in it, I think I could get a new dev productive with Rust in a week or up to a monthy, and as long as you avoid `unsafe` in Rust they will produce a decent code with ease. In C++ you're either an "expert" or you're debugging segfaults. ;)

Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @08:53PM (#19925206)
I truly was curious about your C/C++ code - good for you that it was less C++ and more C! I don't know any masochists, so I don't know anybody who likes to work in C++ (even with just composition and generics), or even any reluctant "expert". I get away from segfaults because I am on server & can get away by more static copying of data (it pales in comparision to what alternatives offer).

I can see why you think Rust is tractable; you have worked on fairly complex stuff like automobile base software (AutoSAR, was it?). I am probably not as good at it as you are, so the cognitive load of designing at that scale with borrow-checking seems prohibitive. I hope there is a way to slice the problem which makes for less cognitive load.

Re:Four Years of Rust by dpc_pw on Wednesday May 15, 2019 @10:51PM (#19925746)
> AutoSAR, was it?

Just a real-time hypervisor for Tegra underlying Nvidia Automotive platform. MISRA C, ISO 26262. Bleh. :D

> so the cognitive load of designing at that scale with borrow-checking seems prohibitive

I have multiple 1k - 10k line Rust projects on github, and I hardly ever deal or think about lifetimes. I just randomly opened a project of mine on github, opening some major files and there's literally 0 explicit lifetime annotations anywhere.

People hang up on lifetimes because they are unfamiliar, but for someone that gets some understanding and accepts "ways of Rust" (mostly avoiding cyclical graphs, using IDs instead of pointers, etc.), there are not an issue. Only when designing some weird zero-cost abstractions in performance-critical APIs, trying to avoid any copying, one has to annotate some lifetimes in non-trivial ways. Usually you can just ask someone on IRC and they will give you an answer. :D

The mental overhead is actually way lower than in C (or most languages for that matter). After a while you get used to relying on compiler to check the mundane stuff and focus only on the higher level problems. It's quite relieving actually.

Re:Four Years of Rust by wyatwerp on Friday May 24, 2019 @03:10PM (#20004442)
MISRA C? Cool!

About the design model for programming in Rust, I guess only making the time to try writing something in Rust can answer the question. It is interesting how the steepness of the Rust learning curve could actually be a hook to get people to try it, which is all any well-designed language would need to gain adherents.

Back to critical systems programming, does MISRA C have a "certified" compiler like CompCert C or something? If so, Rust usage in such a niche must be a long way away - even if one could "certify" the Rust compiler code, how would one "certify" the million+ lines of C++ in LLVM!

Re:Four Years of Rust by njepa on Wednesday May 15, 2019 @04:17PM (#19923302)
I think mainly because mastering new concepts increases the barrier to entry, overhead and scope. Which in turn affects creativity. There are many brilliant programming languages, used by brilliant programmers, yet, most really useful software tends to be produced by whatever. It would be awesome if Rust could overcome that, but I don't really see how currently.
Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @04:34PM (#19923475)
In the no-GC no-runtime niche, you probably need brilliant programmers anyway. Most of them are banging their heads against the C++ wall right now; they would love to get back some of their lost creativity via mastering of new concepts (Rust borrow checker, or Pony's deny capabilities - https://pony-lang.io ).
Re:Four Years of Rust by njepa on Wednesday May 15, 2019 @05:45PM (#19924090)
In my experience C++ programmers aren't necessarily great programmers as such. Because low levels things usually requires domain knowledge and experience more so than programming brilliance.
Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @06:04PM (#19924245)
The topic was the no-GC no-runtime niche, which necessarily requires brilliant programmers, and they are stuck with C++. They would welcome tools to represent their resource control well, borrow checking or deny capabilities.

As a current C++ programmer who remembers what GCC 2.95's error messages looked like for even simple templates, I second you - it is less about the intellect, and more about experience and enough domain knowledge. But quite a few like me work on large C++ software that is not in the no-GC no-runtime niche; modules, good abstractions and native compilation would be enough to match or likely beat whatever we are putting together in C++, which doesn't even have modules yet - and the GC-based conveniences would be a big icing on the cake, so D, Nim, Pony all look interesting. (side note ... https://ponylang.io and not https://pony-lang.io as stated earlier)

Re:Four Years of Rust by njepa on Wednesday May 15, 2019 @08:11PM (#19925017)
I definitely think it is needed. I just don't think Rust has solved the paradox that the more you need something specialized the less you can afford the overhead.

Finding hundreds of web developers with some spare time who don't mind learning Rust, can port some of their tooling and use it in some part of their stack isn't going to be much of a problem. The same isn't true if you, say, need an embedded programmer who has worked with zigbee and needs to be in your lab for testing and verification.

Pretty much all major programming languages are where they are as a result of being some kind of "lowest common denominator" for their application. Something like Bash is pretty horrible as a programming language, but extremely accessible for sysadmins. Only now is it changing slightly were things like Python and Go is becoming more popular, but mostly because they are easier than the alternatives.

Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @02:12PM (#19922128)
Taking nothing away from the Rust community that has managed such a complex language so well so long, I have to say that there never was anything viable in the no-GC no-runtime niche (that is why it is a niche - otherwise why would anybody be using GC'd languages). We were/are just gritting and bearing C++.

If it is a typical program, i.e. not a device driver or OS kernel running on low-memory hardware, having a GC + runtime doesn't preclude performance, for a long-running program. Of course, for short-running programs, just malloc, don't free, is the fastest.

Re:Four Years of Rust by jandrewrogers on Wednesday May 15, 2019 @04:12PM (#19923243)
The use case for non-GC languages go significantly beyond low-level OS kernel type code. Most of our backend infrastructure software and servers (e.g. database engines) are also poor fits for a GC languages, and this is what Rust is targeting. For this type of software, a GC has a large negative performance impact, so it isn't really an option. Operational cost efficiency is often a key factor in platform selection -- being able to reduce hardware requirements by an integer factor is compelling.

To me, Rust is a cleaner and stricter but also more narrow systems programming language than C++, and can be used as a sensible replacement for many C++ code bases, particularly as Rust adds features. Rust still has some challenges. For example, the DMA-driven, schedule-based memory safety models that have become fashionable in high-performance database kernels are not compatible with Rust's memory model. You'd have to make most of the code "unsafe" (in a Rust sense, it is actually an alternative memory safety model designed around a different set of assumptions).

Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @05:48PM (#19924121)
Off-hand, Mirage OS comes to mind - it completely upends how you would "build" and "run" back-end services, and it is written solely in a GC'ed language - OCaml. And all GC'ed languages are not equal; see https://roscidus.com/blog about a Linux package manager ported from Python to OCaml for performance reasons (followed by an OCaml reimplementation of a component in a virtualized OS).

Some infrastructure, e.g. database engines, is ubiquitous, but all instances are of the same few software products written in C/C++/Java. Those ubiquitous instances have banged most bugs out of those codebases, so it is an uphill battle there to convince incumbents and upstarts alike, of the value of a new implementation. But Rust & Pony are marvelously positioned to march up that hill, especially if you throw in multi-threading.

My impression is that only a minority of widely-programmed back-end infrastructure that suits Rust is written in C/C++ (say, map-reduce kernels). The code-base size & the data flow complexity inside those components is pretty limited, and Rust should be tractable at that scale.

Most widely-programmed infrastructure software - in the back-end and on cell phone OS'es - have been merrily using Java/Python/Ruby/Erlang. OCaml is quoted as being used in the management component of VMware. These are much larger applications; is there any evidence or hint that Rust isn't onerous to develop larger systems in? Without that evidence, I feel (not think) that a disciplined GC'ed language (D? Pony?) has a better chance there.

Re:Four Years of Rust by pimeys on Wednesday May 15, 2019 @02:55PM (#19922544)
Having a GC also kind of makes it nasty to write libraries to other GC'd languages. In Rust all of this is very easy, and you can get the speed bump to your Ruby/Python/JavaScript libraries using a modern and safe language.
Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @03:31PM (#19922891)
Is the speed bump for other-language libraries or for other-language applications?

For speeding up other-language libraries, D has a -betterC mode, which prevents you from using the subset of the language and the libraries (standard & user-defined) that relies on GC. The remaining language is a very clean C that simply works on the other language's GC'd memory (using the other language's C interface), and can use stack allocation or any heap allocation strategy of your choice for its working set (reference counting ala C++ shared_ptr could be the obvious choice, but it is your party).

For other language applications, it is a valid option to speed up the entire application by writing it in D, as it has "all" the features of those other languages + all the convenience that is afforded by a GC + threads if you don't want a multi-process design. I quote "all" because I mean useful things like blocks/closures, generic data structures, etc. - of course, neither Rust nor D give you runtime devices like monkey-patching/meta-class hackery/prototype changes.

Re:Four Years of Rust by pimeys on Wednesday May 15, 2019 @04:09PM (#19923217)
We've been rewriting a big Scala code base to Rust now since January and the team is advancing in a nice pace.

Our plan was:

- Take one part of the system to rewrite over JNA

- Run a massive amount of Scala tests against the new code

- When green, take another part

- Meanwhile the other part of the team writes the user-facing code base, connecting it to the new Rust crates

- The test suit works also over an integration layer, so the other team can test their code and the backend with the same test suite

We're quite far already. Originally I was the only person with Rust experience. Now there's five of us.

Re:Four Years of Rust by hopscotch on Thursday May 16, 2019 @10:20AM (#19929285)
Why are you migrating from Scala?
Re:Four Years of Rust by pimeys on Thursday May 16, 2019 @05:03PM (#19933192)
The company wants much lower resource usage per node and easy integration with other languages.
Re:Four Years of Rust by buckminster on Wednesday May 15, 2019 @05:27PM (#19923944)
> Of course, for short-running programs, just malloc, don't free, is the fastest.

A custom malloc that knew free would never be called would be faster still. I wonder if any short-running utilities do this?

Re:Four Years of Rust by pornel on Wednesday May 15, 2019 @06:48PM (#19924550)
AFAIK the D compiler is basically this.
Re:Four Years of Rust by wyatwerp on Wednesday May 15, 2019 @07:05PM (#19924656)
And it is a short-running utility :-)
Re:Four Years of Rust by rudedogg on Wednesday May 15, 2019 @03:44PM (#19923003)
> It'd be another Go with generics, or Elixir-native, or Swift with uglier syntax.

I just want to point out that the Swift package management situation is currently bad. SPM (https://github.com/apple/swift-package-manager) can't be used within Xcode, and is basically not used for anything outside of server-side swift / Linux.

It also doesn't look like SPM will be integrated with Xcode this WWDC, so you're stuck with CocoaPods or Carthage.

I'm really jealous of cargo. And RLS (Swift LSP doesn't really work well because it doesn't know about your dependencies - back to the package manager issue).