Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

> Look at how many basic data structures (in the standard library or outside it) require unsafe features in Java vs Rust.

This is a fundamental misunderstanding of how "unsafe" code relates to a platform's trusted computing base. Rust could move all of those unsafe data structures out of the standard library and into the compiler itself, thereby reducing the amount of occurrences of the string "unsafe" in the source, code, but this would do nothing to reduce the size of the trusted computing base that Rust presents. In fact, it would decrease our confidence in that code, because Rust libraries have a robust ecosystem of tools for validating their correctness, unlike whatever bespoke IR the Rust compiler itself is emitting. Java's own data structures are implemented with the support of an extensive runtime written in C++, which forms their own trusted computing base that every user of Java relies upon, and demands just as much careful auditing as any data structure in the Rust standard library.



> This is a fundamental misunderstanding of how "unsafe" code relates to a platform's trusted computing base. Rust could move all of those unsafe data structures out of the standard library and into the compiler itself, thereby reducing the amount of occurrences of the string "unsafe" in the source, code, but this would do nothing to reduce the size of the trusted computing base that Rust presents.

No, you're missing the point, which is that you cannot write some common data structures in safe Rust (whether they're implemented in the standard library or in the compiler), but you can in Java (inside or outside the standard library). In other words, the point is that safe Rust is quite restricted.

> Java's own data structures are implemented with the support of an extensive runtime written in C++, which forms their own trusted computing base that every user of Java relies upon, and demands just as much careful auditing as any data structure in the Rust standard library.

No, because these data structures are not part of the trusted computing base, which is fixed and closed. In Rust, that base has to be extended to any third-party code that uses unsafe, which is needed in many more situations. In fact, the need for unsafe code in Java has been so reduced that we're currently in the process of removing Unsafe altogether, making it inaccessible to third party code, which would still be able to write the data structures that would be unsafe in Rust in safe Java (the only unsafe thing remaining would be the FFM API, used for FFI, and the legacy JNI, used for that same purpose).

It isn't controversial that the amount of stuff you can do in safe Java is significantly higher than the amount of stuff you can do in safe Rust. That's just obvious.


> No, you're missing the point, which is that you cannot write some common data structures in safe Rust (whether they're implemented in the standard library or in the compiler), but you can in Java (inside or outside the standard library). In other words, the point is that safe Rust is quite restricted.

This is incorrect. You can write those data structures in safe Rust just as easily as you can in Java. You'd write them using the safe primitives that the Rust stdlib provides to you, just like how Java does it. Such collections could often be made to have superior performance by using unsafe Rust, which is why the collections in the stdlib use unsafe code internally, but it's an optimization, not a requirement. You highly underestimate what safe Rust can do; it's not "quite restricted", this is a low-information take.

> In Rust, that base has to be extended to any third-party code that uses unsafe, which is needed in many more situations.

That Rust allows you to define your own safe interfaces to unsafe constructs is a strength of Rust, and necessary for any language that wants to challenge C and C++ on the basis of runtime performance.

> It isn't controversial that the amount of stuff you can do in safe Java is significantly higher than the amount of stuff you can do in safe Rust. That's just obvious.

Turns out, things that people take as obvious can also be wrong.


> This is incorrect. You can write those data structures in safe Rust just as easily as you can in Java. You'd write them using the safe primitives that the Rust stdlib provides to you, just like how Java does it. Such collections could often be made to have superior performance by using unsafe Rust, which is why the collections in the stdlib use unsafe code internally, but it's an optimization, not a requirement.

Of course you can, but the reason you don't is that their performance would be quite bad. I guess you could call that "an optimisation", but good performance for these data structures is a requirement. I am well aware that you can do a lot in safe Rust, but the result is such that you wouldn't want to use Rust at all.

> That Rust allows you to define your own safe interfaces to unsafe constructs is a strength of Rust, and necessary for any language that wants to challenge C and C++ on the basis of runtime performance.

Every language with unsafe constructs allows you to do that! The problem is that with Rust you need to do it quite a bit (of course, if you want acceptable performance, that is). That's not an upside of Rust compared to other safe languages, it's a downside.

> Turns out, things that people take as obvious can also be wrong.

They can, but this one isn't. Safe Rust is Turing complete and in the functional sense you could do anything with it. But the same is true for Python. So does that mean safe Rust and Python are interchangeable because by your measure they can do the same things? Of course not.


> Of course you can, but the reason you don't is that their performance would be quite bad

Not very different from Java or C#. Worse than zig/c/c++ but that’s because those are the equivalent of using use in rust.


> Not very different from Java or C#

It will be significantly worse than Java, at least in some important situations (don't know about C#). I've been programming in C++ for many, many years, and I find it increasingly hard to even match Java's performance, even when writing unsafe code, especially when programs get larger and/or more concurrent (very broadly speaking, Java's performance is about that of C++ - in some situations it's worse and in others is better, but the same general vicinity; after all, the JVM was designed to address some of the performance issues that certain classes of C++ programs suffer from).

Performance is not the reason to use a low-level language in many domains, and in those domains, if you want super-high performance and safety, there are better and more popular alternatives already. You use a low-level language when you need the things low-level languages do best, but you also expect performance that is more-or-less the same as the high-performance safe alternatives.


The point is not that those specific implementations use unsafe Rust but to illustrate that to write even basic data structures you need unsafe Rust.


That's just false. You can use `Arc` or even one of the safe GC crates available, and get semantics like Java with no `unsafe`.


You can't get the same semantics (e.g. no leaks) and you certainly can't get the same performance.


Yeah but that doesn't work for any kind of performant code which is the reason people who write those data structures use unsafe. This is one very annoying thing about Rust community. The language sucks for coding self-referencing data structures with unpredictable free patterns. This is a fact and the reason number of people on this very forum posted long articles about moving away from Rust for those purposes.

Your "actually you can" post is just misleading and will result in more people who will get burnt but the design of the language.


No, you really can. You can use GC crates and the performance will be like Java, or you can use Rc and the performance will be like Swift. The only reason Rust people use unsafe for data structures (and they do not always do) is that for them, Java/Swift-level performance is just not enough.


> No, you really can. You can use GC crates and the performance will be like Java

It won't be anywhere near Java's. Those GCs are mark-and-sweep collectors. Java uses moving collectors. Moving collectors are used to avoid the high overheads of malloc/free in the C runtime (or of any free-list-based mechanism). They're a performance optimisation. Heap allocations in Java behave more like arenas than like heap allocations in languages with non-moving memory management, whether it's C, Rust, Python, or Go. Other runtimes that use moving collectors are Google's V8 and Microsoft's .NET, except that Java's ZGC has no GC pauses.


I'm well aware. I don't know a moving GC crate for Rust, but I do know that building a safe moving GC crate for Rust is possible, using the same principles as existing GC crates. It will not be exactly as performant as Java, because you don't have compiler support for updating pointers, but it will almost be - pointers inside the data structures can be updated via derive, the only pointer that cannot is the pointer to the data structure itself, so you will need to heap-allocate the data structure (the GC root). Given that in Java everything is under indirection anyway, this will have the same efficiency or even better.


> I don't know a moving GC crate for Rust, but I do know that building a safe moving GC crate for Rust is possible, using the same principles as existing GC crates.

But those pointers would not interoperate easily with code that does not expect them. Of course you could effectively "host" a moving GC world inside Rust (or C++, or C), just as you could host the entire JVM in a Rust program (or vice-versa, host a Rust program in a Java program), but the effectiveness and attractiveness of that depends on interoperability with existing libraries.

Java's FFM also lets you bring your own memory management strategies, but the interop with existing types is not transparent (i.e. while you can put a manually-managed object that implements a Map or a List interface in the manually-managed portion, you cannot let that Map or List store arbitrary Java objects).

So there can be interfaces that connect a world of moving pointers and a world of non-moving ones (that's what FFM is), but then the interop between them is pretty much the same as FFM, i.e. the interface between Java and C. That's not really "in the same language".

> Given that in Java everything is under indirection anyway,

I don't know what that means. References in Java are implemented as pointers (some GCs use free bits for some stuff). Maybe you mean that Java doesn't yet have types that are flattened into their container, but it will soon: https://openjdk.org/jeps/401 (this is only the first step). Indeed, that was the last gap that could still allow me to match or beat Java's performance even in some large programs (provided they matched a domain where this was important, and there are certainly some). With that gap closing, the number of large programs where I, an experienced C++ programmer, could even match Java's performance without extraordinary effort is getting very, very, very small.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: