4 ms·
This indictment makes little sense to me considering that, outside the Rust compiler itself, the largest early and still ongoing use case for Rust was/is Servo.
by im_down_w_otp 7y ago
This indictment makes little sense to me considering that, outside the Rust compiler itself, the largest early and still ongoing use case for Rust was/is Servo. A web browser engine, which is predominantly a thing that's dealing with multitudes of graph-shaped problems.
:confused:
- wahern 7y agoHave you looked at the issue tracker for Servo? The bugs and pain points are enlightening. Plus, Servo isn't even used in production! The strategy has been to move parts of it. AFAIU, the most complex piece so far has been the CSS engine. That's nothing to sneeze at, but still. I recently wrote a full PKIX X.509 DER decoder in LPeg in a couple nights of hacking; have fun doing that (or writing anything equivalent to LPeg[1], for that matter) in a language without GC. It's absolutely possible, just like it's possible to implement it in ATS or Coq, but that's not the point of debate. That said, it's one thing to admit the costs of Rust's model. It's another to argue about the implications of that cost--i.e. the degree to which it makes Rust non-viable long-term. On that point I have no opinion, except to say that for complex application development I've been very happy using Lua as a glue language, and many others have been happy using GC'd languages for complex logic. But that's more of a neutral factoid as it both diminishes Rust's relative costs and benefits. Whether it augurs in favor of Rust or not depends on your starting point. Plus, language success is less dependent on merit than we'd like to believe. [1] Note that LPeg is far more than a PEG engine (like Rust pest), as strict PEG engines are incapable of parsing DER, which is context-sensitive. In addition to its extensions (e.g. runtime matches), what makes LPeg so simple is that you don't even need intermediate graph representations. You can transform subtrees in the grammar inline, mixing function transforms and intermediate captures to your hearts content. This is difficult to explain and more difficult to appreciate until you see and use it in action.
- vlovich123 7y agoThe challenge with gc is that it itself isn’t a complete solution and actually creates new problems that are even harder to solve. Everyone worries about memory because it’s the most common resource but all resources have this problem (eg files, network handles, dB connections, audio handles, etc). So then you end right back to having GC languages add back scope-based ownership for that (python with, java closeable, etc). With RAII-style management like C++ or Rust all resources are treated uniformly. Furthermore the challenge with concurrent GC is that max memory utilization is difficult to contain and difficult to make performance deterministic. So yes it has advantages. It also has severe disadvantages for the types of low-level efficient things Rust is meant for. Remember. Rust is meant to replace the existing problems that people reach for C/C++. That’s the space it’s competing in - embedded programming, operating systems, browsers, etc. There are problems that other languages are better suited for. Python, Ruby, Java are easier to work with not only because of GC. Java in particular pays an even larger cost due to not supporting value types and is still struggling afaik to integrate them properly into the GC which inhibits programmer-aided optimization of memory usage/layout. Also, I’ll note that Swift and Objective-C are pretty easy to work with for memory management (on the level of Java) despite not having GC and get quite close to the performance of C/C++/Swift. The challenges with GC that you handwave away has been what’s been said about GC ever since the beginning. Perhaps it’s time to admit that GC isn’t the silver bullet you think it is?
- sdegutis 7y ago> Swift and Objective-C are pretty easy to work with > and get quite close to the performance of C/C++/Swift. In some cases, identical performance. ;)
- millstone 7y agoIt’s a real issue. Consider (as you say) the Rust compiler. It has an IR phase called MIR, which is a tree, and elements in the tree need to know how to find themselves in the parent. For example, a function has a set of basic blocks, and each BB needs to know about its function. This is a very typical IR; LLVM is the same. Backreferences are hard in Rust, so a BB instead maintains its index into a Vec<BB>, owned by the function. But this index is just a number: ownership is not modeled, it is not statically checked, and it may fall out of sync. It is effectively a slow, weird (though sandboxed) raw pointer. You can write this stuff in Rust, but it is awkward and Rust cannot bring its strengths to bear. Rust assumes a tree-like ownership model and if you fall off that path, it can’t help much. Graphs aren’t trees so Rust is less helpful here.
- Sean1708 7y ago> It is effectively a slow ... raw pointer. In my experience (unless I've misunderstood what you're trying to say) this is the fastest way to write graphs because of how much more cache-friendly it is than having to chase a load of pointers.
- zelly 7y agoTrue, but you can do the same thing more efficiently with pointers. Suppose the parent maintains an array of children Node* Then each child has a Node** member which points to itself in that array. That's one dereference to get up to the parent context. In the Rust example, to do the same would take an extra few steps and probably miss the cache. I think speculative execution would favor the pointer method.
- vlovich123 7y agoDo you have benchmarks? An array offset isn’t speculative and I suspect you’ll have a very hard time showing that vec[i] is slower than *ptr. One challenge is if vec[i] involves a bounds check which it might in native rust.
- 7y ago