News for hackers. Stuff that matters.
Re:Speed of Rust vs. C by Animats on Saturday March 13, 2021 @12:39AM (#26444290)
"But the biggest potential is in ability to fearlessly parallelize majority of Rust code, even when the equivalent C code would be too risky to parallelize. In this aspect Rust is a much more mature language than C."

Yes. Today, I integrated two parts of a 3D graphics program. One refreshes the screen and lets you move the viewpoint around. The other loads new objects into the scene. Until today, all the objects were loaded, then the graphics window went live. Today, I made those operations run in parallel, so the window comes up with just the sky and ground, and over the next few seconds, the scene loads, visibly, without reducing the frame rate.

This took about 10 lines of code changes in Rust. It worked the first time it compiled.

Re:Speed of Rust vs. C by phkahler on Saturday March 13, 2021 @07:25AM (#26446109)
>> One refreshes the screen and lets you move the viewpoint around. The other loads new objects into the scene.

How did you do that in Rust? Doesnt one of those have to own the scene at a time? Or is there a way to make that exclusive ownership more granular?

Re:Speed of Rust vs. C by Animats on Saturday March 13, 2021 @02:37PM (#26449284)
Since this got so many upvotes, I'll say a bit more. I'm writing a viewer for a virtual world. Think of this as a general-purpose MMO game client. It has no built-in game assets. Those are downloaded as needed. It's a big world, so as you move through the world, more assets are constantly being downloaded and faraway objects are being removed. The existing viewers are mostly single thread, in C++, and they run out of CPU time.

I'm using Rend3, which is a 3D graphics library for Rust that uses Vulkan underneath. Rend3 takes care of memory allocation in the GPU, which Vulkan leaves to the caller, and it handles all the GPU communication. The Rend3 user has to create all the vertex buffers, normal buffers, texture maps, etc., and send them to Rend3 to be sent to the GPU. It's a light, safe abstraction over Vulkan.

This is where Rust's move semantics ownership transfer helps. The thread that's creating object to be displayed makes up the big vertex buffers, etc., and then asks Rend3 to turn them into a "mesh object", "texture object", or "material object". That involves some locking in Rend3, mostly around GPU memory allocation. Then, the loader puts them together into an "object", and tells Rend3 to add it to the display list. This puts it on a work queue. At the beginning of the next frame, the render loop reads the work queue, adds and deletes items from the display list, and resumes drawing the scene.

Locking is brief, just the microseconds needed for adding things to lists. The big objects are handed off across threads, not recopied. Adding objects does not slow down the frame rate. That's the trouble with the existing system. Redraw and new object processing were done in the same thread, and incoming updates stole time from the redraw cycle.

If this was in C++, I'd be spending half my time in the debugger. In Rust, I haven't needed a debugger. My own code is 100% safe Rust.

Re:Speed of Rust vs. C by gridspy on Saturday March 13, 2021 @03:01PM (#26449480)
Wonderful! Thanks for sharing. This sounds like the exact sort of work that Rust is perfect for.

I'm making a game in Rust and Godot (engine) and since it's a factory game the simulation performance is important. Rust means I worry far less about stability and performance.

I bet if you wrote a good blog entry with screenshots and explanation of how your code loads and renders I imagine it would do well on HN.

Re:Speed of Rust vs. C by Animats on Saturday March 13, 2021 @03:28PM (#26449694)
Too soon. Someday perhaps a Game Developers Conference paper/talk. I was considering one, but live GDC has been cancelled for 2021. My real interest in this is how do we build a big, seamless metaverse that goes fast. I'm far enough along to see that it's possible, but not far enough along that people can use the client.

Rust is good for this sort of thing. It's overkill for most web back end stuff. That's where Go is more useful. Go has all those well-used libraries for web back end tasks. Parallelism in web back ends tends to be about waiting for network events, not juggling heavy compute loads of coordinated disparate tasks. Hence all the interest in "async" for web servers. As I've said before, use the right tool for the job.

Re:Speed of Rust vs. C by gridspy on Saturday March 13, 2021 @03:30PM (#26449704)
One idea I liked was ...

You have an authoritive world simulation server, as usual.

You then have several servers whose chief job is to keep clients in sync with the authoritive server.

Most network games combine these two roles, but there is a lot of processing and network traffic required to keep clients in sync. For massive multiplayer there is a benefit to scale the "client-interaction" servers.

Re:Speed of Rust vs. C by fhunt on Saturday March 13, 2021 @09:26PM (#26452219)
My question is probably off because I lack the knowledge but how do the commercial games/game engines do this then if this is such a rocket science? Something like Fortnite or an aged GTA do what you've described (downloading assets on demand without any fps-drop) for quite some time now.
Re:Speed of Rust vs. C by kbenson on Sunday March 14, 2021 @12:18AM (#26452998)
The claim isn't that it's impossible, or "rocket science", it's that it's hard to do right and was made much easier. You're bringing up for comparison a game engine that has been in constant development by experts for over two decades (Unreal Engine) and a game engine in constant development for over a decade ago (RAGE). Just because someone makes a professional product using tens or hundreds of millions of dollars doesn't mean it was easy.

There's a reason why Epic is able to charge a percentage of sales for their engine, and companies still opt for it. That's because it's hard to do reliably and with good performance and visuals.

Re:Speed of Rust vs. C by fhunt on Sunday March 14, 2021 @10:11AM (#26455600)
Yeah, but just picking one of many requirements in game dev and advocating why lang x can do this better than y ignores all the other checkboxes. Yeah, C++ is nerve-wrecking but Rust can be even more. IIRC there was a thread about Zig vs Rust and why Rust is just the wrong tool (for OPs use case in that case). IDK but there is a reason why C++ dominates game dev and a reason why Rust still struggles with mainstream adoption compared to same agers like Go or TS.
Re:Speed of Rust vs. C by kbenson on Monday March 15, 2021 @01:22PM (#26468782)
Game dev has nothing to do with it.

The claim was that Rust made making something parallel easy/easier, and the illustrative example given was someone trying to parallelize something in a game engine. Whether Rust is good for game development or not is irrelevant to the point that was being made.

Even if everyone accepted that Rust was horrible for game development on most metrics, the example given would still carry the exact same weight, because it's really about "parallelizing this would be very hard in C++, but it was very easy because of Rust."

Re:Speed of Rust vs. C by brink on Saturday March 13, 2021 @07:50AM (#26446218)
The simplest (and often best) option is to use the Arc<Mutex<MyStruct>> pattern.

The Arc is an async reference counter that allows multiple ownership. And the nested Mutex enforces only one mutable borrow at a time.

Re:Speed of Rust vs. C by efficax on Saturday March 13, 2021 @09:32AM (#26446782)
I think you mean that Arc is an atomic reference counter (it uses atomic cpu instructions to prevent race conditions when incrementing and decrementing the ref count)
Re:Speed of Rust vs. C by brink on Saturday March 13, 2021 @09:57AM (#26446956)
Ah yes, sorry. I remember it in my head with "async", but you're right. :)
Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @07:58AM (#26446249)
Eh, with Arc you can share ownership easily, and there are probably a lot of cleverer concurrent data structures or entity component kinda things that'd just work too. But maybe you can arrange things so that one thread owns the scene but the other thread can still do useful work?
Re:Speed of Rust vs. C by ywei3410 on Saturday March 13, 2021 @08:24AM (#26446378)
This typically isn't possible because the rendering context is global and is needed for both loading and rendering. You need an Arc to guarantee the correct Drop mechanism.
Re:Speed of Rust vs. C by adamnemecek on Saturday March 13, 2021 @11:32AM (#26447632)
I'm not sure how your architecture but you might not even need to lock things. I find that using mpsc channels allows me to get around like 60% of locking. Essentially, you have some sort of main loop, then you spawn a tread, load whatever you need there and then send it to the main thread over mpsc. The main thread handles it on the next iteration of the main loop.
[dead]
Re:Speed of Rust vs. C by TazeTSchnitzel on Saturday March 13, 2021 @08:45AM (#26446501)
C being barebones does not mean it is faster. Because it has such weak typing and gives a huge amount of programmer freedom, compilers have to do a lot of work to be able to understand a C program well enough to optimise it.

Rust, on the other hand, requires the programmer to give the compiler more information about what they're doing.

A very simple example:

  void foobar(struct foo *f)
  {
    f->a += 2;
    foo();
    f->a += 2;
    bar();
    f->a += 2;
  }
Because C pointer types are so barebones, the compiler can't tell whether foo() and bar() can modify f->a just from looking at the above code. So it will always have to load and store that for each += operation.

Rust on the other hand has two kinds of reference, rather than pointers:

  fn foobar(f : &mut foo) {
    f.a += 2;
    foo();
    f.a += 2;
    bar();
    f.a += 2;
  }
This is more high-level. But it's good for performance! Rust has a rule that you can only have one mutable reference to a struct at one time. Therefore, foo() and bar() can't be modifying f.a and it can simplify this to `f.a += 6;`.

(You can see it in action for yourself here: https://godbolt.org/z/hWs67P. Sadly, Rust doesn't do this by default due to problems with LLVM, but eventually it can.)

Re:Speed of Rust vs. C by pdimitar on Saturday March 13, 2021 @08:53AM (#26446555)
Lately on another Rust thread somebody pointed out that C programs use a lot of indirection like pointers and vtable dispatches which actually detracts from the supposed mega-speed of the low-level C. I found that to be mind-blowing and felt stupid for not remembering that earlier.
Re:Speed of Rust vs. C by andrepd on Saturday March 13, 2021 @10:27AM (#26447179)
I don't think vtables are often used in C.
Re:Speed of Rust vs. C by codeflo on Saturday March 13, 2021 @10:44AM (#26447285)
I think they meant function pointers in general (callbacks and the like, see qsort). Also, a lot of C codebases end up implementing manual vtables of some sort where polymorphism is required.
Re:Speed of Rust vs. C by rstuart4133 on Sunday March 14, 2021 @06:05AM (#26454034)
It's true they aren't that common, but have you looked at the Linux kernel code? It's written in C, and vtables are everywhere.

I've also used them on occasions. They do a particular job people call pluggable implementations / dynamic typing / sub-classing depending on their background. If there isn't some central place that knows all the types (if there is you can use switch/case/match), there isn't much choice, it's vtables or nothing. But needing to do that job is rare, so seeing it in languages that don't use vtables promiscuously to implement OO is correspondingly rare.

Which is as it should be, because vtables are more expensive than a direct call, very expensive if they prevent inlining. One of rust's triumphs is it provides them, but you have to go out of your way to use them so it encourages avoiding their overheads.

Re:Speed of Rust vs. C by howinteresting on Saturday March 13, 2021 @12:17PM (#26448000)
Dynamic dispatch (vtables are one way to do it, and so is a function pointer) is incredibly common in C, because there's no language-built-in way to perform monomorphization.
Re:Speed of Rust vs. C by ragnese on Saturday March 13, 2021 @09:42AM (#26446850)
> Sadly, Rust doesn't do this by default due to problems with LLVM, but eventually it can.

Can it, though? I keep hearing/reading FUD around both unsafe and Pin making it unlikely to ever be able to ubiquitously enable the noalias stuff.

Re:Speed of Rust vs. C by kibwen on Saturday March 13, 2021 @11:43AM (#26447719)
You have correctly identified it as FUD. People have a bone to pick with Pin, so they irrationally latch on to it, but the general problem is the fact that the &mut invariants cannot currently permit any self-referential data, which is a useful concept in general (for intrusive data structures, etc) and whose lack that people have been hacking around since before 1.0, with crates like rental and owning_ref. The plan to fix this is to make self-referentiality a first-class concept in the language, as a principled exception to the usual &mut uniqueness invariant that preserves memory safety while properly encoding the aliasing guarantees.
Re:Speed of Rust vs. C by dataangel on Saturday March 13, 2021 @01:27PM (#26448680)
> The plan to fix this is to make self-referentiality a first-class concept in the language, as a principled exception to the usual &mut uniqueness invariant that preserves memory safety while properly encoding the aliasing guarantees.

Are there issues I can subscribe to or RFCs for this?

Re:Speed of Rust vs. C by kibwen on Monday March 15, 2021 @12:00PM (#26467593)
Re:Speed of Rust vs. C by ameliaquining on Saturday March 13, 2021 @12:42PM (#26448228)
Source? I would like this to be true, but I haven't actually seen it anywhere.
Re:Speed of Rust vs. C by steveklabnik on Saturday March 13, 2021 @01:10PM (#26448534)
https://news.ycombinator.com/item?id=26410487 (it's a significant part, though not the entirety, of this comment)
Re:Speed of Rust vs. C by kibwen on Monday March 15, 2021 @11:59AM (#26467580)
Re:Speed of Rust vs. C by Jweb_Guru on Saturday March 13, 2021 @10:21AM (#26447133)
Code affected by unsafe already has to go through `UnsafeCell` which disables most aliasing optimizations, and the stacked borrow semantics have explicit opt-outs for such cases. I don't believe there are any Rust semantic issues standing in the way of exploiting aliasing information in this way, just LLVM bugs (and the fact that its restrict model isn't currently equipped to handle the information at such a fine granularity).
Re:Speed of Rust vs. C by nyanpasu64 on Saturday March 13, 2021 @11:52AM (#26447803)
There is undefined behavior in Rust affecting real-world code, including Tokio's scheduler, and code produced by async fn definitions. UnsafeCell doesn't solve the problem. There's more information at https://gist.github.com/Darksonn/1567538f56af1a8038ecc3c664a....

Bug report at https://github.com/rust-lang/rust/issues/63818.

Reddit threads at (older) https://www.reddit.com/r/rust/comments/l4roqk/a_fix_for_the_... and (newer) https://www.reddit.com/r/rust/comments/lxw6cl/update_to_llvm....

Somewhat related HN thread at https://news.ycombinator.com/item?id=26406989.

Re:Speed of Rust vs. C by Jweb_Guru on Saturday March 13, 2021 @12:21PM (#26448036)
This is the `Pin<&mut>` example which I'm not that familiar with but was aware of. I think it's highly unlikely that this one, relatively niche use case is going to prevent Rust from ever being able to safely turn on aliasing optimizations. There have been several solutions proposed, e.g. adding a stricter UnsafeCell to the language; they may technically not be backwards-compatible, but given how `Pin` is used and the fact that this is a soundness issue, I think it should be fine.

The HN thread is mostly unrelated. I agree that it would have been better to integrate `Pin` directly into the language, though, but mostly for ergonomic reasons; it could still probably happen in an edition upgrade.

Re:Speed of Rust vs. C by kimundi on Saturday March 13, 2021 @11:47AM (#26447757)
The github discussion thread where that originates from also contain the language designers optimistically discussing how in the worst case `Pin` just has to be hardcoded to exclude these optimizations. Which wouldn't make it the first type in the std lib that works similary (see interior mutability and UnsafeCell), so I personally intepret that as "unlikely to be an issue".
Re:Speed of Rust vs. C by cygx on Saturday March 13, 2021 @09:16AM (#26446696)
That's what restrict is for:

    void foobar(struct foo *restrict f) { ... }
Re:Speed of Rust vs. C by masklinn on Saturday March 13, 2021 @12:19PM (#26448012)
And just like that we're back to

> There's a significant difference between what these languages can achieve in theory, and how they're used in practice.

Theoretically in C you can use restrict for this. Practically nobody does (rust users keep finding bugs and miscompilation in LLVM's noalias support), and it's a huge footgun because you're completely on your own and all bets are off if you misuse it.

Meanwhile in rust land, it's the default and the compiler checks your homework, and while you can always lie to the compiler it's much rarer that you'd even get in a position to do so.

Re:Speed of Rust vs. C by howinteresting on Saturday March 13, 2021 @12:21PM (#26448041)
But restrict is very hard to reason about correctly, and the consequences for making a mistake are potentially catastrophic.

There's a very real difference between what's possible in theory and what humans do in practice. I wish Hacker News people engaged more with the practice.

Re:Speed of Rust vs. C by TazeTSchnitzel on Saturday March 13, 2021 @09:22AM (#26446727)
Yes, C99 added that keyword, and you can use it in C code. (C++ is a more complicated matter, I believe…)

But I think it's pretty uncommon in practice. One reason is that the C compiler has no borrow checker to help you notice when you're using `restrict` unsafely.

(Also, there's the whole “strict aliasing” hell…)

Re:Speed of Rust vs. C by petschge on Saturday March 13, 2021 @02:34PM (#26449248)
It's not that uncommon in HPC codes. I.e. one of the places where speed matters.
Re:Speed of Rust vs. C by randomswede on Monday March 15, 2021 @07:34AM (#26464695)
If you can have "one mutable" and "more than one non-mutable" reference (not sure if this is the case), you still cannot safely do that optimization, as foo() and bar() could in principle be reading f.a and the optimized version would then not have the correct values of f.a when foo() and bar() are called.

Note, I genuinely don't know if this caveat applies to Rust. But, m general, not only mutable references need to be considered.

Re:Speed of Rust vs. C by zesterer on Saturday March 13, 2021 @07:19AM (#26446083)
> My overall feeling is that if I could spend infinite time and effort, my C programs would be as fast or faster than Rust, because theoretically there's nothing C can't do that Rust can.

The exact same argument applies to assembly code. There are very good reasons that it's not used nowadays except in incredibly rare circumstances or in the embedded world.

It doesn't matter in the slightest how fast your language is in theory. Not one iota.

The only thing that matters is how fast the programs you write with it are in practice. The evidence is clear: it is significantly easier to write faster programs in Rust than it is in C, and this applies to even the most skilled developers.

Re:Speed of Rust vs. C by gridspy on Saturday March 13, 2021 @04:29AM (#26445272)
The very short version:

There are many things which cause both frequent and rare strange crashes in multi-threaded code.

In C, all these things will compile OK. In safe Rust, practically none of them will compile.

It is much easier to fix compile issues in Rust to do with dangerous memory usage or thread sharing than it is to debug a compiled program.

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @06:06AM (#26445799)
Accessing files or database content from multiple threads without proper locking, or transactions, in place will compile just fine.
Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @06:31AM (#26445900)
Rust won’t prevent all manner of bugs, but if you need to prevent multiple parts of your application from accessing a resource concurrently, it’s fairly trivial to design types that would guarantee that at compile time.

If you need to do it across processes, then you need a file system that supports exclusive file opens.

The db question is a red-herring, because to properly solve for concurrency in the db, you need to use locks in the db (table and row locks), not the code accessing the db.

Re:Speed of Rust vs. C by Chilinot on Saturday March 13, 2021 @06:38AM (#26445927)
You dont necessarily need to use locks in the db. You can use transactions as well, unless you want to do major changes to the DB where transactions would be in constant conflict state.
Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @06:46AM (#26445956)
You’re right, though that wasn’t really the point of my reply. More that concurrency in the DB is a DB design choice and not the responsibility of the language accessing the DB. This is especially true when accessing the DB from multiple nodes, which most deployed software does.
Re:Speed of Rust vs. C by branko_d on Sunday March 14, 2021 @06:07AM (#26454044)
Locks and transactions are intertwined. Write locks are typically released only when the transaction ends, and read locks too at some transaction isolation levels.
Re:Speed of Rust vs. C by masklinn on Saturday March 13, 2021 @12:20PM (#26448030)
> Rust won’t prevent all manner of bugs

Nit: rust will prevent all manner of bugs. Rust won't prevent every manner of bugs.

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @06:54AM (#26445987)
Indeed, but the fearless concurrency sales pitch tends to overlook that.
Re:Speed of Rust vs. C by trunnell on Saturday March 13, 2021 @12:20PM (#26448019)
It’s hard to see how you could be arguing in good faith given that your point of “fearless concurrency” being an overstated “sales pitch” has now been answered with multiple substantive answers.

Please stop moving the goal posts from “program concurrency” to “distributed or multi-process transactions.” It subtracts from the conversation.

Rust is honest about what it does and doesn’t do.

Re:Speed of Rust vs. C by pjmlp on Sunday March 14, 2021 @10:43AM (#26455825)
Rust is honest, https://doc.rust-lang.org/nomicon/races.html

I am not moving goal posts, rather talking about issues that many apparently lack the knowledge to understand how many variants of data races exist in an application.

Quite understanable given the majority of developers that keep writing single threaded applications.

Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @08:16AM (#26446342)
The fearless concurrency sales pitch doesn't overpromise. You're trying to stretch it, but it's pretty clear on what kind of concurrency issues it covers (eg. data races).
Re:Speed of Rust vs. C by hderms on Saturday March 13, 2021 @08:52AM (#26446551)
Yeah it would be a grave misinterpretation of "fearless concurrency" to think Rust somehow validates that access to some shared resource with it's own semantics is also safe. I'm not educated on the subject but that problem seems pretty intractable for a language to solve in a general sense.
Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @12:30PM (#26448125)
Indeed, yet that is not how many Rust advocacy blog posts sell it.
Re:Speed of Rust vs. C by shakow on Sunday March 14, 2021 @07:09AM (#26454360)
Such as?
Re:Speed of Rust vs. C by pjmlp on Sunday March 14, 2021 @10:48AM (#26455858)
Any blog post that gives examples accessing shared variables and never goes beyond anything else, leaving to the reader that it works the same way regardless of what resources are being accessed.

https://blog.knoldus.com/how-we-can-do-fearless-concurrency-...

Now rewrite the same blog post using SQL queries to update the same counter variable on a table row.

The Rustonomicon is quite clear that it wouldn't work,

> However Rust does not prevent general race conditions.

https://doc.rust-lang.org/nomicon/races.html

Re:Speed of Rust vs. C by shakow on Sunday March 14, 2021 @12:13PM (#26456482)
You really had to dig a post that has less text than code?

> leaving to the reader that it works the same way regardless of what resources are being accessed.

If that's how readers envision that non-language-managed resources work, they should go back to CS102 right now.

And concerning the nomicon, it explicitly states that Rust can't handle all races condition, I don't get your point.

Re:Speed of Rust vs. C by orf on Saturday March 13, 2021 @09:42AM (#26446857)
What a silly point to make. The code you’re writing in rust could launch a nuke that destroys the world and it will also compile just fine.
Re:Speed of Rust vs. C by simias on Saturday March 13, 2021 @08:03AM (#26446272)
Rust has the expressive power to design an API that explicitly makes it impossible if you so desire though. For instance by using an API similar to mutexes where you have to lock to access the contents.
Re:Speed of Rust vs. C by pjmlp on Sunday March 14, 2021 @10:48AM (#26455863)
> However Rust does not prevent general race conditions.

https://doc.rust-lang.org/nomicon/races.html

Re:Speed of Rust vs. C by simias on Sunday March 14, 2021 @11:03AM (#26455973)
I never claimed otherwise. If you want to enforce invariants in your DB API you'll have to implement them yourselves, Rust won't do it for you because Rust doesn't know what a database is. Still, it's perfectly possible to design a DB API is such a way that it would prevent some issues, such as for instance doing changes without an active transaction.

But you're right to point out that Rust won't magically solve all your possible sources of crash and data corruption, it just does make it a lot easier to enforce arbitrary constraints. For instance if you decide that in order to avoid these issues you want all your DB stuff to only run in a single thread you could design your API in a way that would prevent DB handles from being shared between threads, all that enforced by the language. You couldn't accidentally leak a DB handle to a different thread.

Re:Speed of Rust vs. C by masklinn on Saturday March 13, 2021 @12:22PM (#26448051)
> Accessing […] database content from multiple threads without proper locking, or transactions, in place will compile just fine.

All the rust db interfaces I've seen so far forbid unlocked sharing of connections, statically (the connections are !Sync, in Rust speak).

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @12:29PM (#26448114)
They don't enforce the use of transactions, nor exclusive access to database tables.
Re:Speed of Rust vs. C by myrrlyn on Saturday March 13, 2021 @07:37PM (#26451605)
show me a c program that does this in a manner that a rust program can't emulate
Re:Speed of Rust vs. C by pjmlp on Sunday March 14, 2021 @05:27AM (#26453875)
C doesn't advertise fearless concurrency.
Re:Speed of Rust vs. C by bsder on Saturday March 13, 2021 @05:03AM (#26445465)
> Code converted from C to Rust seems much more voluminous.

This is a fairly odd claim.

If you have to deal with strings (ASCII and UTF-8) properly, C is stupidly verbose.

If you need a data structure more complex than an array of something, C is stupidly verbose.

If you want to deal with pattern matching/regexen, C is ridiculously verbose.

Do I agree that Rust is far more verbose for an embedded "blinky" (the embedded equivalent of "Hello, World!")? Yes.

But once I start doing things like processing messages in a communications stack (BLE, CANOpen, Ethernet, etc.), Rust starts looking better and better.

Re:Speed of Rust vs. C by drran on Sunday March 14, 2021 @01:39PM (#26457106)
Blink in rust is concise as well:

  // Main function
  #[arduino_uno::entry]
  fn main() -> ! {
    let peripherals = arduino_uno::Peripherals::take().unwrap();

    let mut pins = arduino_uno::Pins::new(
        peripherals.PORTB,
        peripherals.PORTC,
        peripherals.PORTD,
    );

    // Pin D13 is connected to L led
    let mut led = pins.d13.into_output(&mut pins.ddr);

    loop {
        led.toggle().void_unwrap();
        arduino_uno::delay_ms(500);
    }
  }
https://github.com/vlisivka/rust-arduino-blink/blob/main/src...
Re:Speed of Rust vs. C by scorpion95 on Saturday March 13, 2021 @05:11AM (#26445502)
When I converted code from C to Rust, I was left with much more code.

Are you just noting specifics, or was it your experience that there was less Rust required for a full C to Rust conversion?

Re:Speed of Rust vs. C by Jweb_Guru on Saturday March 13, 2021 @06:37AM (#26445920)
AFAIK it is a common experience that both C and C++ code tend to become fewer LOC in a move to Rust, a lot of it due to stuff like serde that greatly reduces boilerplate. It probably depends on your application and program size, though. I'm sure that if you're doing a lot of pointer wrangling or something it won't be smaller in Rust, while if your C program was just a bunch of SIMD intrinsics anyway like a lot of high performance code is now it'll probably be basically the same length.
Re:Speed of Rust vs. C by mcherm on Saturday March 13, 2021 @07:42AM (#26446180)
Did you ever take a look to try and figure out where the extra verboseness came from? For instance, was it spread equally across all functions or concentrated in those doing numeric computations (or whatever)? It would be interesting to learn something from this example.
Re:Speed of Rust vs. C by maccam94 on Saturday March 13, 2021 @01:12PM (#26448556)
Did you convert it by hand and translate the code into idiomatic rust? Or just run some C code through c2rust? Because the latter will not produce anything like a typical rust program, it will be C types and logic with minimal changes to make it compile in rust (and those changes will make it look very verbose).
Re:Speed of Rust vs. C by myrrlyn on Saturday March 13, 2021 @07:41PM (#26451632)
for one thing, naming a C struct requires more words than naming a Rust struct; for another, the names of functions that operate on them
Re:Speed of Rust vs. C by jsjohnst on Saturday March 13, 2021 @02:49PM (#26449371)
I mostly agree with your post but:

> If you need a data structure more complex than an array of something, C is stupidly verbose.

What’s stupidly verbose about Structs to you?

Re:Speed of Rust vs. C by Volt on Saturday March 13, 2021 @04:46PM (#26450293)
"Data structure" here probably means something like a linked list, binary tree, or hash table.
Re:Speed of Rust vs. C by jsjohnst on Saturday March 13, 2021 @09:48PM (#26452356)
Linked list, binary tree, and heck, even a hash table aren’t “stupidly verbose” to me in C either, hence my question to GP.
Re:Speed of Rust vs. C by bsder on Saturday March 13, 2021 @10:42PM (#26452609)
You have to allocate and deallocate--where and when does that occur? When the data structure needs to grow, all pointers need to be invalidated--where and when does that occur? How do you iterate across the data structure? Do those iterators hold a local pointer or do they hold a root pointer plus an accessor function pointer plus memoization? What happens when you want to copy a subset of the data structure? I can go on and on.

Every one of those things requires a fairly primitive function call that sometimes doesn't even need to exist in another language. For contrast, think about all the macrology that the Linux kernel does to iterate across every element of a linked list that is effectively "for element in list {}" in any higher language.

And, even worse, most of that stuff in C needs to be runtime-only, while some of this kind of thing gets elided by the compiler in other languages.

If you don't consider all that "stupidly verbose" I'm really curious what you would?

And this is long before we start talking about concurrency.

C allows you to write something that works "just enough" that you put it into production and then it bites you in the ass (similar to quadratic algorithms--functional enough to get to production and then bite you).

Re:Speed of Rust vs. C by Lvl999Noob on Saturday March 13, 2021 @04:18AM (#26445231)
The author did say that there is nothing that Rust does that C cannot. The difference is that in Rust, those things are easier, or many times, the default way, while in C, you would have to take care of way too many things to make sure things work.
Re:Speed of Rust vs. C by rbanffy on Saturday March 13, 2021 @05:17AM (#26445523)
I used to say that wrt to memory leaks with Java and C++ and it remains true when comparing C and Rust:

It's not that it's easier to write programs in [Java|Rust]. It's that it makes it much harder to write the bugs.

Re:Speed of Rust vs. C by rocqua on Saturday March 13, 2021 @06:14AM (#26445829)
Yesterday I upgraded an entire code-base from C to C++ just because it was faster than writing my own dynamically resizing array in C.

Writing programs in C is harder just because there are essentially no containers in the stdlib.

Re:Speed of Rust vs. C by JohnStrangeII on Saturday March 13, 2021 @06:26AM (#26445872)
Aren't there good container libraries for C?
Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @08:03AM (#26446274)
There are a lot of great libraries for sure, but they aren't in the stdlib and C doesn't make it as easy to use external libraries as languages with modern tooling. Everybody gets grumpy about dependencies and a lot of people probably figure it's easier to maintain their own container code in their application than to deal with that.
Re:Speed of Rust vs. C by rocqua on Saturday March 13, 2021 @08:36AM (#26446453)
They are either based on void * with performance issues, or macro based with weird ergonomics that look like function calls, but aren't.

It's doable, but not very easy.

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @09:06AM (#26446647)
You are right in a library-demographical sense, but not in a fundamental sense. There is a 3rd way. Have a look at the CTL I linked to (downvoted..maybe I should have explained more?).

Once you give up the closed source/prebuilt binary library idea and embrace the C++-like header library idea and write implemenations in terms of "assumed macro/inline function" definitions, the problem becomes straightforward with no performance issue and different ergonomics issues than you probably think.

It's a more "manual instantiation" than C++ templates or generics in other languages where just refering to them works, but most of C is quite manual. So, it fits the headspace & the hard parts of data structures/meddlesome hands remain factored out. Since you parameterize your files/code with #define/#include, you have to name your parameters which can make the instantiating client code more obvious than C++ templates with many arguments. OTOH, there is no/poor type checking of these parameters.

Re:Speed of Rust vs. C by rocqua on Saturday March 13, 2021 @02:19PM (#26449120)
I had a look, and it feels like template programming but with even worse guarantees.

Having a type declaration dependent on #define P whether it is plain old data or not, and needing to know what that means, is not the kind of ergonomics I'd want. That requires learning a whole new paradigm to ensure I am not doing wrong things.

In my mind it is so big an extension of the C language, that it leaves the C headspace and becomes its own headspace.

Re:Speed of Rust vs. C by cb321 on Sunday March 14, 2021 @07:34AM (#26454486)
Yeah. It's not for everyone. I think "different ergonomic issues" may cover that and I did mention the type checking already. :-)

It is a smaller learning curve from pure C than "all of Rust" or even "all of C++/STL". You got the basic idea in short order (that may be for ill as well as good..I was never trying to make a normative claim).

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @06:38AM (#26445928)
Re:Speed of Rust vs. C by scorpion95 on Saturday March 13, 2021 @04:48AM (#26445395)
Yes.

But it’s not just taking care of those things that must be done; it seems to bloat the code.

I think it’s a great alternative to C for large apps like Firefox, and perhaps it’s a good alternative to Go for services.

For general purpose, I personally want something fast that’s easy, clear, and concise like Ruby.

Do I just accept that Rust is the most evolved version of C, or is my gut correct that it’s bloated? Is it a good choice for general purpose as-is?

Re:Speed of Rust vs. C by hderms on Saturday March 13, 2021 @09:04AM (#26446639)
As someone who's worked predominantly in high level languages (Scala, Ruby, etc...) I've found Rust to be relatively straightforward to use for simple CLI tools or gRPC servers (tonic library is pretty nice). I haven't tried building a CRUD app yet, but I don't see any real reason why it would be impossible to have an ergonomic web framework in Rust.

The things I find most difficult: 1. Wrangling with the borrow checker can be painful before you know what you're doing (and even afterwards) but if you understand the standard library/patterns well, it seems to minimize the cost. Example being trying to write your own `get_or_else_insert` style method for a HashMap. Writing your own version is easy in other languages but hard in Rust. If you didn't know that methods like that already exist on HashMap you will experience a lot of pain until you understand the "right" way to do something.

2. Shared memory concurrency is definitely at the nexus of all the more difficult parts of Rust. Especially with async/await. There's no question in my mind that if you want to write a webserver that has async functions accessing shared memory, that you will for sure need to fill in any gaps in your knowledge as it will be difficult to get to a working program without understanding significantly more concepts than what it might take for a simple single-threaded CLI app

I'm pretty sure that it will be possible (if it isn't already) to get the Rust ecosystem to a state where writing a CRUD app is about as simple as in Go (and considerably easier/more ergonomic w.r.t certain things like JSON serialization).

Re:Speed of Rust vs. C by anfilt on Saturday March 13, 2021 @05:35AM (#26445617)
Firefox's is compiled code is mostly written in C++ not C. You conflate C with C++, Java, and C#. C++ while has source compatibility with C tends to end up much different than C. C will not give you the OOP hell-scape you can dig yourself into with those three languages. C code tends be simpler and much more close to the assembly that will be generated than you would get in those language. Moreover, Java and C# are not even compiled. Anyways C != C++. C++ has changed quite a bit since it's earlier days and has diverged from plain C in a lot of ways. Some people even feel C++ keeps adding too many new features too fast.
Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:18AM (#26446349)
> Some people even feel C++ keeps adding too many new features too fast.

It's not so much that they keep adding features, but that they (almost?) never remove any.

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @12:49PM (#26448293)
Python 3 has shown the world what happens when that is done without bringing the ecosystem along.
Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @01:15AM (#26453209)
Haskell has also removed some features over time.
Re:Speed of Rust vs. C by pjmlp on Sunday March 14, 2021 @04:18AM (#26453608)
Haskell or GHC?

If you mean GHC, the language version is whatever the pile of configuration flags at each source file ends up meaning, some of them even contradict themselves.

Great for language research, which is Haskell main purpose in life, hardly a good idea for getting industry love.

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @07:36AM (#26454500)
I am talking about Haskell, specifically the removal of 'n+k patterns' and 'monad comprehensions'.

About GHC: I think their approach with pragmas is great and something for other languages to emulate. It's also great in production, with the caveat that you might want to restrict that mechanism to surface level changes only, and nothing that changes the intermediate format.

Re:Speed of Rust vs. C by anaerobicover on Saturday March 13, 2021 @01:47PM (#26448850)
Are there many other programming languages that remove features?
Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @01:16AM (#26453212)
Python 3 made some backwards incompatible changes. Haskell removed some features over time, as well.
Re:Speed of Rust vs. C by ttt0 on Saturday March 13, 2021 @06:50AM (#26445971)
> C++ while has source compatibility with C

It doesn't really, some things from C won't compile in C++, but that's a minor nitpick

Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @08:05AM (#26446290)
I guess people mostly take source compatibility to mean that you can write the headers for your C library so that it can be used from C++. That's not the same thing as C being a proper subset of C++ or whatever, but it's still a vast enough advantage of C++ over most competitors that it might as well be.
Re:Speed of Rust vs. C by DJBunnies on Saturday March 13, 2021 @05:38AM (#26445636)
Ruby is not fast.
Re:Speed of Rust vs. C by Can_Not on Saturday March 13, 2021 @10:04PM (#26452429)
But if you want something between rust and ruby, checkout crystal (garbage collected, strongly typed with inference, llvm binary, ruby-like syntax, fast like golang).
Re:Speed of Rust vs. C by rcxdude on Saturday March 13, 2021 @05:19AM (#26445533)
> Code converted from C to Rust seems much more voluminous. Perhaps it’s easier to maintain if you know Rust well?

My experience is mostly the opposite. For many tasks Rust can be much more concise (see anything with string handling, for example).

Re:Speed of Rust vs. C by smt1 on Saturday March 13, 2021 @08:59AM (#26446600)
> Code converted from C to Rust seems much more voluminous.

I haven't seen that in practice. A good point of reference are implementations of things like ruby, python, or the erlang vm in rust compared to the C alternatives. This might be because Rust is also more expressive (probably by borrowing certain syntax/semantics from ocaml/haskell), though the borrow checker does add back some verbosity.

Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @08:43AM (#26446495)
But Rust works badly with mmapped (memory-mapped) files, as the article notes. So in C you could load (and save!) stuff almost instantly, whereas in Rust you still have to de-serialize the input stream.
Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:29AM (#26446761)
No you don't. I've written multiple programs that load things instantly off the file system via memory maps. See the fst crate[1], for example, which is designed to work with memory maps. imdb-rename[2] is a program I wrote that builds a simple IR index on your file system that can then instantly search it by virtue of memory maps.

Rust "works badly with memory mapped files" doesn't mean, "Rust can't use memory mapped files." It means, "it is difficult to reconcile Rust's safety story with memory maps." ripgrep for example uses memory maps because they are faster sometimes, and its safety contract[3] is a bit strained. But it works.

[1] - https://github.com/BurntSushi/fst/

[2] - https://github.com/BurntSushi/imdb-rename

[3] - https://docs.rs/grep-searcher/0.1.7/grep_searcher/struct.Mma...

Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @09:52AM (#26446920)
I didn't read your code but one problem I suspect you ran into is that you had to re-invent your container data structures to make them work in a mmapped context.
Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:58AM (#26446966)
No, I didn't. An fst is a compressed data structure, which means you use it in its compressed form without decompressing it first. If you ported the fst crate to C, it would use the same technique.

And in C, you have to design your data structures to be mmap friendly anyway. Same deal in Rust.

But this is moving the goal posts. This thread started with "you can't do this." But you can. And I have. Multiple times. And I showed you how.

Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @10:04AM (#26447005)
> which means you use it in its compressed form without decompressing it first.

So your code operates directly on a block of raw bytes? I can see how that can work with mmap without much problems.

My argument was more about structured data (created using the type system), which is a level higher than raw bytes.

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @10:15AM (#26447077)
> So your code operates directly on a block of raw bytes? I can see how that can work with mmap without much problems.

Correct. It's a finite state machine. The docs of the crate give links to papers if you want to drill down.

> My argument was more about structured data (created using the type system), which is a level higher than raw bytes.

Yes. You should be able to do in Rust whatever you would do in C. You can tag your types with `repr(C)` to get a consistent memory layout equivalent to whatever C does. But when you memory map stuff like this, you need to take at least all the same precautions as you would in C. That is, you need to build your data structures to be mmap friendly. The most obvious thing that is problematic for mmap structures like this that is otherwise easy to do is pointer indirection.

With that said, this technique is not common in Rust because it requires `unsafe` to do it. And when you use `unsafe`, you want to be sure that it's justified.

This is all really besides the point. You'd have the same problems if you read a file into heap memory. The main problem in Rust land with memory maps is that they don't fit into Rust's safety story in an obvious way. But this in and of itself doesn't make them inaccessible to you. It just makes it harder to reason about safety.

Re:Speed of Rust vs. C by morty_s on Saturday March 13, 2021 @12:10PM (#26447948)
Dang, burntsushi up in the house! Hey, just wanted to say I enjoy your work––I've learned a lot from it. Thank you!
Re:Speed of Rust vs. C by fractionalhare on Saturday March 13, 2021 @10:05AM (#26447015)
It's very tedious to debate with someone who explicitly makes assumptions about something (like code) without having read it, and puts the burden of refuting those assumptions on you...
Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @08:50AM (#26446539)
It doesn’t say it “works badly” it says the borrow checker can’t protect against external modifications to the file while memory-mapped, which has a host of issues in C as well.

You can mmap files in Rust just fine, but it’s generally as dangerous as it is in C.

Re:Speed of Rust vs. C by bakatubas on Saturday March 13, 2021 @09:51AM (#26446916)
I don’t get this obsession with “dangerous.” Honestly, what does that even mean? I think a better word is “error-prone.” Danger is more like, “oh my god a crocodile!”
Re:Speed of Rust vs. C by steveklabnik on Saturday March 13, 2021 @09:59AM (#26446969)
> Honestly, what does that even mean?

It has a very specific meaning in Rust: the user can cause memory unsafety if they make a mistake.

> I think a better word is “error-prone.”

The issue with the connotation there is that it's not about the rate of problems, it's about them going from "impossible" to "possible."

Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @10:15AM (#26447082)
There can be real danger when the code is used in certain applications. For example when controlling the gate of the crocodile cage in a zoo.
Re:Speed of Rust vs. C by kortex on Saturday March 13, 2021 @11:10AM (#26447474)
Concurrency bugs can absolutely cause dangerous danger of the deadly variety:

https://en.m.wikipedia.org/wiki/Therac-25

Re:Speed of Rust vs. C by bakatubas on Saturday March 13, 2021 @06:48PM (#26451303)
Unfortunately, as is most always the case of negligence instead of some particular language features:

“A commission attributed the primary cause to general poor software design and development practices rather than single-out specific coding errors. In particular, the software was designed so that it was realistically impossible to test it in a clean automated way.“

Ergo, concurrency doesn’t kill people, people do.

Re:Speed of Rust vs. C by majewsky on Saturday March 13, 2021 @07:25PM (#26451544)
You sound like you make a refutation, but you really don't. This whole discussion is about giving tools to developers that are systematically less error-prone, which your quote suggests would have been helpful to that specific development team.
Re:Speed of Rust vs. C by myrrlyn on Saturday March 13, 2021 @07:48PM (#26451678)
the main problem here is that C has the capability to declare mmap regions correctly: `volatile char[]` and Rust does not (`[Cell<u8>]` is close but not exactly right, and annoying)

most rust folks who use mmap don't mark the region as Celled, which means they risk UB in the form of incorrect behavior because the compiler assumes that the memory region is untouchable outside the single Rust program, and that's not true

(it's also not true generally b/c /dev/mem and /proc/pid/mem exist, but it's beyond Rust's scope that the OS allows intrusion like that)

Re:Speed of Rust vs. C by drchickensalad on Saturday March 13, 2021 @12:44PM (#26448246)
Errors are up to interpretation. It just means the thing didn't happen as requested. Errors are meant to be expected or not expected depending on the context.

Dangerous means dangerous. It's not up for interpretation.

Languages have multiple, very different words, for exactly this reason.

Re:Speed of Rust vs. C by bakatubas on Saturday March 13, 2021 @06:55PM (#26451349)
Agreed. But still, folks make it sound bad. For instance “danger” in the many context could also be reframed as “powerful”, could it not?
Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @08:57AM (#26446579)
But that may be of little solace. If you snapshot your entire heap into an mmapped file for fast I/O, then basically the entire advantage of Rust is gone.
Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @09:08AM (#26446658)
Is there literally no other code in the application?

Rust has plenty of situations where you do unsafe things but wrap that in safe APIs. If you’re returning regions of that mmapped file, for example, a lifetime can be associated to those references to ensure that those are valid for the duration of the file being mmapped in the program.

It can be used to ensure that if you need to write back to that mmapped file (inside the same program) that there are no existing references to it, because those would be invalid after an update to the file. You need to do the same in C, but there are no guardrails you can build in C to make that same assurance.

Re:Speed of Rust vs. C by ReactiveJelly on Saturday March 13, 2021 @09:30AM (#26446771)
> If you snapshot your entire heap into an mmapped file for fast I/O,

I've never heard of this trick. And my first reaction is "That would be a nightmare of memory unsafety if I did it in C++"

What's it used for? IPC?

Re:Speed of Rust vs. C by loeg on Saturday March 13, 2021 @11:13AM (#26447498)
I think emacs (used to?) do something awful like this. https://lwn.net/Articles/707615/
Re:Speed of Rust vs. C by howinteresting on Saturday March 13, 2021 @12:09PM (#26447941)
I'd call mmaping data structures into memory an advanced systems programming trick which can result in a nice performance boost but which also has some severe drawbacks (portability across big/little endian architectures and internal pointers being two examples).

I know some very skilled C++ and Rust developers who can pull it off. If you're at that skill level, Rust is not going to get in your way because you're just going to use unsafe and throw some sanitizers and fuzzers at it. I wouldn't trust myself to implement it.

Re:Speed of Rust vs. C by amelius on Saturday March 13, 2021 @09:44AM (#26446870)
You have to combine it with other techniques, e.g. journaling to make it safe, but this is not always necessary (e.g. when using large read-only data-structures)
Re:Speed of Rust vs. C by amluto on Saturday March 13, 2021 @10:37AM (#26447235)
In C you can access pointers to memory mapped files effortlessly in ways that are often extremely unsafe against the possible existence of other writers and against the making being unmapped and mapped elsewhere. It’s also traditional to pretend that putting types like int in a mapped file is reasonable, whereas one ought to actually store bytes and convert as needed. Rust at least requires a degree of honesty.
Re:Speed of Rust vs. C by high_density on Saturday March 13, 2021 @08:52AM (#26446546)
is it something deeply ingrained to rust? or is it something rust is working on?
Re:Speed of Rust vs. C by JulianMorrison on Saturday March 13, 2021 @09:20AM (#26446712)
It's more like, Rust wants to make guarantees that just aren't possible for a block of memory that represents a world-writable file that any part of your process, or any other process in the OS, might decide to change on a whim.

In other words, mmaped files are hard, and Rust points this out. C just provides you with the footgun.

Re:Speed of Rust vs. C by codeflo on Saturday March 13, 2021 @10:40AM (#26447260)
The problem is that compilers are allowed to make some general assumption about how they're allowed to reorder code, always based on the assumption that no other process is modifying the memory. For example, the optimizer may remove redundant reads. That's a problem if the read isn't really redundant -- if the pointer isn't targeting process-owned memory, but a memory mapped file that's modified by someone else. Programs might crash in very "interesting" ways depending on optimization flags.

C has this issue as well, but Rust's compiler/borrow checker is particularly strong at this kind of analysis, so it's potentially bitten even harder.

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @06:04AM (#26445790)
While it works great for some cases, one should not forget it doesn't cover external resources, specially those shared across processes.
Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @06:42AM (#26445940)
You have made this claim multiple times. Why do you see this as a language issue and not an OS issue? It becomes an even bigger problem when we talk about distributed systems and distributed resources. Is there a language that handles this?

These issues about multiple processes and distributed systems are framework and OS level concerns. Rust helps you build fast concurrent solutions to those problems, but you’re correct that it can not solve problems exterior to the application runtime. How is that a deficiency with Rust?

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @06:55AM (#26445991)
Fearless concurrency sales pitch.

Yes languages like Erlang and runtimes like Coyote and Orleans.

Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @07:25AM (#26446110)
Erlang has a great concurrency model with higher overhead than Rust, but similar cross thread safety, doesn’t do anything about exterior resources to the application.

I’ve not worked with Coyote, but if it is the system for .net, it describes itself as a framework, “Coyote provides developers a programming framework for confidently building reliable asynchronous software on the .NET platform”.

Orleans similarly describes itself as a framework, “Orleans is a cross-platform software framework for building scalable and robust distributed interactive applications based on the .NET Framework.”

Rust is a language, similar frameworks are being built with it, the point your making does not appear to be about the language.

Re:Speed of Rust vs. C by zelphirkalt on Saturday March 13, 2021 @12:13PM (#26447973)
If I understand correctly, the Erlang point was, that you can have a distributed system by using Beam to scale to multiple machines and have them communicate via message passing, which is all possible and encouraged, because of how you structure and write code in Erlang, as actors with mailboxes, isolating actors from each other, except for the messages, that are passed.

You say, that the Erlang concurrency model has higher overhead than Rust. In Rust there are probably multiple projects going on right now (one of them is Bastion, but I guess there are probably others), which try to provide Erlang like concurrency. What do you mean by overhead of a concurrency model (that of Erlang) being higher than the overhead a programming language (Rust)? As far as I know Erlang's lightweight processes are about as lightweight as you can get. Is there a Rust framework for Erlang like concurrency, which reduces the footprint of lightweight processes even more?

Re:Speed of Rust vs. C by bluejekyll on Saturday March 13, 2021 @12:57PM (#26448397)
That wasn’t meant to be a snide comment about Erlang in any way. All I meant by the comment about higher-overhead was that the language itself generally has more costs to run, i.e. runtime, memory usage, garbage collector, interpreted, etc, than Rust.

The “process” model of Erlang is about as lightweight as you can get, agreed.

In terms of capabilities of beam across systems, point taken. Though we start stretching some of the understanding of where languages end and runtimes begin... Rust and C make those boundaries a little more clear.

Re:Speed of Rust vs. C by fulafel on Saturday March 13, 2021 @07:32AM (#26446137)
How could an OS adapt its processes functionality to help Rust here?
Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @08:17AM (#26446345)
Capabilities would probably be helpful :V
Re:Speed of Rust vs. C by acje on Saturday March 13, 2021 @11:05AM (#26447434)
Re:Speed of Rust vs. C by pmarin on Saturday March 13, 2021 @04:05AM (#26445167)
Without real world data "fearlessly parallelizing all the things!" is an awful idea due to all the overhead involved.

The most important design decision while writing a parallel algorithm is to decide for what amount of data is not worth it.

Re:Speed of Rust vs. C by riquito on Saturday March 13, 2021 @04:12AM (#26445202)
He tried with few effort and noticed that for his use case the code is faster, I fail to understand this rebuttal of the parent's comment
Re:Speed of Rust vs. C by rbanffy on Saturday March 13, 2021 @05:26AM (#26445566)
The average cellphone today has more than 4 cores. A decent desktop can deal with 16 threads on 8 cores.

There is a lot of untapped parallelism readily available waiting for the right code.

Re:Speed of Rust vs. C by ShinTakuya on Saturday March 13, 2021 @06:08AM (#26445810)
It's not about number of available threads, the very act of scheduling tasks across multiple threads has scheduling and communication overheads, and in many situations actually ends up being slower than running it on the same thread.

That said, I think the original comment was rightly pointing out how easy it was to make the change and test it, which in this case did turn out to be noticeably faster.

Re:Speed of Rust vs. C by PicassoCTs on Saturday March 13, 2021 @06:26AM (#26445874)
Parallelization is the nuclear energy of comp science. Loads of potential, high risk reward and they would have gotten away with it, if it were not for those meddling humans. Its non-trivial and can only be handled by accomplished engineers. Thus it is not used - or is encapsulated, out of sight, out of reach of meddling hands. (CPU Microcode shovelling non-connected work to pipelines comes to mind / NN-Net training frameworks, etc.)
Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:23AM (#26446372)
> [...] or is encapsulated, out of sight, out of reach of meddling hands.

That's the real issue here! Most language have poor abstractions for parallelism and concurrency. (Many languages don't even differentiate between the two.)

Encapsulating and abstracting is how we make things usable.

Eg letting people roll hash tables by themselves every time they want to use one, would lead to people shooting themselves in the foot more often than not. Compared to that, Python's dicts are dead simple to use. Exactly because they move all the fiddly bits out of the reach of meddling hands.

Re:Speed of Rust vs. C by rbanffy on Saturday March 13, 2021 @06:34PM (#26451226)
> Exactly because they move all the fiddly bits out of the reach of meddling hands.

You don't even need to hide those out of reach. You just need to make it dead simple to use and pretty much nobody will want to touch the fiddly bits.

And those who do know they had it coming.

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @01:15AM (#26453206)
Oh, definitely. You just need to make it so that people don't have to fiddle with it and don't fiddle with it by accident.

You seldom have to protect against malicious attempts. (But when you do, it's a much harder task.)

Re:Speed of Rust vs. C by fulafel on Saturday March 13, 2021 @07:35AM (#26446147)
As a general thought about parallelizing all the things it's true though. When looking for speedups, parallelization granularity has to be tuned and iterated with benchmarking, else your speedups will be poor or negative.

I think the example case in this subthread was about making some long app operations asynchronous and overlapping, which is a more forgiving use case than trying to make a piece of code faster by utilizing multiple cores.

Re:Speed of Rust vs. C by alerighi on Saturday March 13, 2021 @06:50AM (#26445969)
Also Rust is risky to parallelize: you can get deadlocks.

I don't get the obsession of parallel code in low level languages by the way. If you have an architecture where you can afford real parallelism you can afford higher level languages anyway.

In embedded applications you don't usually have the possibility to have parallel code, and even in low level software (for example the classical UNIX utilities), for simplicity and solidity using a single thread is really fine.

Threads also are not really as portable as they seem, different operating systems have different way to manage threads, or even don't supports thread at all.

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:35AM (#26446801)
This is a bad take. ripgrep, to my knowledge, cannot be written in a higher level language without becoming a lot slower.[1] And yet, if I removed its use of parallelism by default, there will be a significantly degraded user experience by virtue of it being a lot slower.

This isn't an "obsession." It's engineering.

[1] - I make this claim loosely. Absence of evidence isn't evidence of absence and all that. But if I saw ripgrep implemented in, say, Python and it matched speed in the majority of cases, I would learn something.

Re:Speed of Rust vs. C by pjmlp on Saturday March 13, 2021 @12:51PM (#26448326)
Python isn't really something I would even think as possible example, Common Lisp, D, Nim, Swift, most likely.
Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @01:17PM (#26448609)
So? I said, "higher level language." I didn't say, "Python specifically."

I would guess D could do it.

I don't know enough about Nim or Swift.

I would learn something if Common Lisp did it. I'd also learn something if Haskell or Go did it.

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @01:44PM (#26448822)
I am not trying to contradict anyone here, but any language mature enough to have an impl/way to not have arbitrary performance ceilings needs access to inline assembly/SIMD. Cython/Nim/SBCL can all do that..probably Haskell..Not so sure about Go or Swift. Anyway, many languages can respond well to optimization effort. I doubt anyone disagrees.

At the point of realizing the above no ceiling bit, the argument devolves to more one about (fairly subjective) high/low levelness of the code itself/the effort applied to optimizing, not about the language the code is written in. So, it's not very informative and tends to go nowhere (EDIT: especially when the focus is on a single, highly optimized tool like `rg` as opposed to "broad demographic traits" of pools of developers, and "levelness" is often somewhat subjective, too).

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @02:00PM (#26448959)
You're missing the context I think. Look at what I was responding to in my initial message in this thread:

> If you have an architecture where you can afford real parallelism you can afford higher level languages anyway.

My response is, "no you can't, and here's an example."

> but any language mature enough to have an impl/way to not have arbitrary performance ceilings needs access to inline assembly/SIMD

If you ported ripgrep to Python and the vast majority of it was in C or Assembly, then I would say, "that's consistent with my claim: your port isn't in Python."

My claim is likely more subtle than you might imagine. ripgrep has many performance sensitive areas. It isn't enough to, say, implement the regex engine in C and write some glue code around that. It won't be good enough. (Or at least, that's my claim. If I'm proven wrong, then as I said, I'd learn something.)

> At the point of realizing the above no ceiling bit, the argument devolves to more one about (fairly subjective) high/low levelness of the code itself/the effort applied to optimizing, not about the language the code is written in. So, it's not very informative and tends to go nowhere.

I agree that it's pretty subjective and wishy washy. But when someone goes around talking nonsense like "if parallelism is a benefit then you're fine with a higher level language," you kind of have to work with what you got. A good counter example to that nonsense is to show a program that is written is a "lower" level language that simultaneously benefits from parallelism and wouldn't be appropriate to do in a higher level language. I happen to have one of those in my back-pocket. :-) (xsv is another example. Compare it with csvkit, even though csvkit's CSV parser is written in C, it's still dog slow, because the code around the CSV parser matters.)

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @03:09PM (#26449547)
Ok. "Afford parallelism => afford high level" with the implication of HL=slow does sound pretty off base. So, fair enough.

FWIW, as per your subtle claim, it all seems pretty hot spot optimizable to me, at least if you include the memchr/utf8-regex engine in "hot spot". I do think the entire framing has much measurement vagueness ("hot", "vast majority", "levelness", and others) & is unlikely to be helpful, as explained. In terms of "evidence", I do not know of a competitor who has put the care into such a tool to even try to measure, though. { And I love rg. Many thanks and no offense at all was intended! }

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @03:34PM (#26449738)
ack might be an example. It's Perl, not Python, and its author is on record as saying that performance isn't his goal. So it's a bit of a strained one. But yes, it's true, I don't know any other serious grep clone in a language like Python. This is why I hedged everything initially by saying that I know that absence of evidence isn't evidence of absence. :-) And in particular, I framed this as, "I would learn something," rather than, "this is objective fact." So long as my standard is my own experience, the hand wavy aspect of this works a bit better IMO.

> I do not know of a competitor who has put the care into such a tool to even try to measure, though.

Right. Like for example, I am certain enough about my claim that I would never even attempt to do it in the first place. I would guess that others think the same. With that said, people have written grep's in Python and the like, and last time I checked, they were very slow. But yeah, the "development effort" angle of this likely makes such tools inappropriate for a serious comparison to support my claim. But then again, if I'm right, the development effort required to make a Python grep be as fast as ripgrep is insurmountable.

> it all seems pretty hot spot optimizable to me

As long as we're okay with being hand wavy, then I would say that it's unlikely. Many of the optimizations in ripgrep have to do with amortizing allocation, and that kind of optimization is just nearly completely absent in a language like Python unless you drop down into C. This amortization principle is pervasive and applies as deep as regex internals to the code the simply prints ripgrep's output (which is in and of itself a complex beast and quite performance sensitive in workloads with lots of matches), and oodles of stuff inbetween.

> { And I love rg. Many thanks and no offense at all was intended! }

:-) No offense taken. This is by far the best convo I'm having in this HN post. Lol.

Note that I've made similar claims before. In the last one, there is a lot more data: https://news.ycombinator.com/item?id=17943509

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @04:47PM (#26450308)
When I used to write in Cython + NumPy I would pre-allocate numpy arrays written into by Cython. It's C-like, but because of the gradual typing I think firmly in the higher level (for some value of "er"). One can certainly do that stuff in Nim/SBCL/etc. (and one sees it done).

While allocation is pretty pervasive, I'm skeptical that everywhere or even most places you do it is an important perf bottleneck. Without a count of these 20 times it matters and these 40 it doesn't, it's just kind guesswork from an all too often frail human memory/attention that "ignores the noise" by its very nature. You might be right. Just trying to add some color. :-)

Another way to think of this is to imagine your own codebase "in reverse". "If I drop this optim, would I see it on that profile?" Or look at the biggest piles of code in your repo and ask "Is this in the critical path/really perf necessary?" and the like. Under the assumption that higher level things would be a lot shorter that kind of thought experiment can inform. Maybe an approach toward more objectivity, anyway. Little strewn about tidbits in every module don't really count { to me :-) } - that speaks more to abstraction problems.

But I don't think there is a lot of value in all the above gendankenizing. While I realize some bad "just throw money at it" kicked this off, one of my big objections to the entire framing is that I think people and their APIs really "alter the level" of a language. Indeed their experience with the language has big impact there. Every one reading this knows C's `printf(fmt, arg1, arg2,..)`. Yet, I'd bet under 1% have heard of/thought to do an allocating (or preallocated) string builder variant like `str(sub1, sub2, ..., NULL)` or using/acquiring something like glibc's `asprintf`. People will say "C is low level - It has no string concatenation!". Yet, inside of an hour or two most medium-skill devs could write my above variadic string builder or learn about vasprintf. Or learn about Boehm-Wiser for garbage collected C or 100 other things like that CTL I mentioned elsewhere in this thread.

So what "level" is C, the language? Beats me. Does it have concatenation? Well, not spelled "a+b" but maybe spelled not much worse "str(a,b,NULL)". Level all just depends so much on how you use it. Performance is similar. Much C++ (and Rust for that matter) is terribly inefficient because of reputations for being "fast languages" leading to less care (or maybe just being done by junior devs..). These "depends" carry over to almost anything..not just Rust or C, but sometimes even English. I am usually told I write in much too detailed a way and a trimmer way might have higher persuasion/communication performance! { How's that for "meta"? ;-) }

> This is by far the best convo I'm having in this HN post. Lol.

Cool, cool. There can be a lot of "Rust Rage" out there (in both directions, probably). :)

Anyway, I don't think we'll resolve anything objective here, but don't take a lack of response as indicating anything other than that. You aren't making any strong objective claims to really rebut and I'm glad that you personally undertook the challenge to do ripgrep in any language. I do think many might have done..maybe Ada, too, and probably many more, but maybe all at the same "realized levelness". You just did not know them/feel confident about getting peformance in them. Which is fine. A.Ok, even! I guess your other biggy is Go and that might actually not have worked of all the alternatives bandied about by pjmlp and myself so far.

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @06:16PM (#26451079)
> While allocation is pretty pervasive, I'm skeptical that everywhere or even most places you do it is an important perf bottleneck. Without a count of these 20 times it matters and these 40 it doesn't, it's just kind guesswork from an all too often frail human memory/attention that "ignores the noise" by its very nature. You might be right. Just trying to add some color. :-)

In general I agree. But I'm saying what I'm saying because of all the times I've had to change my code to amortize allocation rather than not do it. It's just pervasive because there are all sorts of little buffers everywhere in different parts of the code. And those were put there because of experimenting that said the program benefited from them.

The key here is that the loops inside of ripgrep can grow quite large pretty quickly. There's the obvious "loop over all files," and then there's "loop over all lines" and then "loop over all matches." ripgrep has to do work in each of those loops and sometimes the work requires allocation. Even allocations at the outermost loop (looping over all files) can cause noticeable degradations in speed for some workloads.

This is why I'm so certain.

The numpy example is a good one where a substantial amount of code has been written to cater to one very specific domain. And in that domain, it's true, you can write programs that are very fast.

> So what "level" is C, the language?

Oh I see, I don't think I realized you wanted to go in this direction. I think I would just say that I absolutely agree that describing languages as "levels" is problematic. There's lots of good counter examples and what not. For example, one could say that Rust is both high level and low level and still be correct.

But like, for example, I would say that "Python is high level" is correct and "Python is low level" is probably not. But they are exceptionally general statements and I'm sure counter-examples exist. They are, after all, inherently relativistic statements, so your baseline matters.

That's kind of why I've stayed in "hand wavy" territory here. If we wanted to come down to Earth, we could, for example, replace "high level languages" in the poster's original statement with something more precise but also more verbose that this discussion still largely fits.

> I am usually told I write in much too detailed a way and a trimmer way might have higher persuasion/communication performance! { How's that for "meta"? ;-) }

Yeah, it's hard to be both pithy and precise. So usually when one is pithy, it's good to take the charitable interpretation of it. But we are technical folks, and chiming in with clarifications is to be expected.

> I don't think we'll resolve anything objective here

Most definitely. At the end of the day, I have a prior about what's possible in certain languages, and if that prior is proven wrong, then invariably, my mental model gets updated. Some priors are stronger than others. :-)

> You aren't making any strong objective claims to really rebut

Right. Or rather, my claims are rooted in my own experience. If we were going to test this, we'd probably want to build a smaller model of ripgrep in Rust, then try implementing that in various languages and see how far we can get. The problem with that is that the model has to be complex enough to model some reasonable real world usage. As you remove features from ripgrep, so to do you remove the need for different kinds of optimizations. For example, if ripgrep didn't have replacements or didn't do anything other than memory map files, then that's two sources of alloc amortization that aren't needed. So ultimately, doing this test would be expensive. And that's ignoring the quibbling folks will ultimately have about whether or not it's fair.

> I guess your other biggy is Go and that might actually not have worked of all the alternatives bandied about by pjmlp and myself so far.

I would guess Go would have a much better shot than Python. But even Go might be tricky. Someone tried to write a source code line counter in Go, put quite a bit of effort into it, and couldn't get over the GC hurdle: https://boyter.org/posts/sloc-cloc-code/ (subsequent blog posts on the topic discuss GC as well).

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @08:24PM (#26451867)
I feel we've talked past each other about what is/is not Python a few times. There is Cython and Pythran and Pypy and ShedSkin and Numba and others that are targeting, for lack of a more precise term, "extreme compatibility with" CPython, but also trying to provide an escape hatch for performance which includes in-language low levelness including allocation tricks that are not "mainstream CPython" (well, Pypy may not have those...).

My first reply was questioning "what counts" as "Python". Cython is its own language, not just "C", nor just "Python", but can do "low level things" such as using C's alloca. Maybe the only prior update here is on the diversity of "Python" impls. There are a lot. This is another reason why language levelness is hard to pin down which was always my main point, upon which we do not disagree. Maybe this is what you meant by "exceptionally general", but I kinda feel like "there isn't just one 'Python'" got lost. { There used to be a joke.."Linux isn't" related to the variety of distros/default configs/etc. :-) }

Advice-wise, I would say that your claim can be closer to easily true if you adjust it to say "ripgrep needs 'low level tricks' to be fast and a language that allows them, such as Rust". That phrasing side-steps worrying about levelnesses in the large of programming languages, re-assigns it to techniques which is more concrete and begs the question of technique enumeration. That is the right question to beg, though, if not in this conversation then in others. You might learn how each and every technique has representation in various other programming languages. It's late for me, though. So, good night!

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @08:35PM (#26451953)
Ah I see. You are right. I missed that you were going after that. I'm personally only really familiar with CPython, so that is indeed what I had in mind. To be honest, I don't really know what a ripgrep in Cython would look like. Is there a separate Cython standard library, for example? Or do you still use Python's main standard library?

We don't have to tumble down that rabbit hole though. If someone wrote a ripgrep in Cython and matched performance, then I would definitely learn something.

> "ripgrep needs 'low level tricks' to be fast and a language that allows them, such as Rust"

I might use that, sure. I think my point above was that I had to riff off of someone else's language. But I think we covered that. :-) In any case, yes, that phrasing sounds better.

Anyway, good chatting with you, good night!

Re:Speed of Rust vs. C by petdance on Monday March 15, 2021 @10:33AM (#26466521)
> I do not know of a competitor who has put the care into such a tool to even try to measure, though.

As an aside, I'm the author of ack, and I would ask that folks not use the word "competitor" to describe different projects in the same space. Speaking for me/ack and burntsushi/ripgrep, there is absolutely no competition between us. We have different projects that do similar things, and neither of us is trying to best the other. We are each trying to make the best project we can for the needs we are looking to fill. ripgrep won't replace ack, ack won't replace ripgrep, and neither one will replace plain ol' grep. Each has its place.

I believe this so strongly that I created a [feature comparison chart](https://beyondgrep.com/feature-comparison/) comparing various greplike tools, and a related blog post I wrote on this: [The best open source project for someone might not be yours, and that's OK](https://blog.petdance.com/2018/01/02/the-best-open-source-pr...)

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @03:15AM (#26453412)
I suspect Don Stewart might be able to do it in Haskell.

That's basically by knowing enough about GHC to carefully trigger all the relevant optimizations.

Re:Speed of Rust vs. C by burntsushi on Sunday March 14, 2021 @11:21AM (#26456127)
Hah. I'm highly skeptical. But I suppose if anyone could do it, it'd be him. I would certainly learn something. :-)

I've tried optimizing Haskell code myself before. It did not go well. It was an implementation of the Viterbi algorithm actually. We ported it to Standard ML and C and measured performance. mlton did quite well at least.

We published a paper about the process of writing Viterbi in Haskell in ICFP a few years back: https://dl.acm.org/doi/pdf/10.1145/2364527.2364560?casa_toke...

Unfortunately, the performance aspect of it was only a small part, and we didn't talk about the C or mlton ports in the paper.

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @11:23PM (#26462303)
Very interesting!

I suspect you could make a very Haskell-like language that's also really fast, but you'd have to base it on linear types from the ground up, and make everything total by default. (Hide non-total parts behind some type 'tag' like we do with IO in current Haskell (and have something like unsafePerformPartial when you know your code is total, but can't convince the compiler).)

That way the compiler can be much more aggressive about making things strict.

Re:Speed of Rust vs. C by cb321 on Saturday March 13, 2021 @01:12PM (#26448560)
Cython with all the appropriate cdef type declarations can match C and so might also do it. Not sure Cython exactly counts as "Python"..it's more a superset/dialect { and I also doubt such a port would hold many lessons for @burntsushi, but it bore noting. }
Re:Speed of Rust vs. C by yholio on Saturday March 13, 2021 @07:10AM (#26446054)
You would go to parallelism precisely on those platforms where simpler performance fixes (changing some data structures or implementing limited sections in a fast language) are insuficient. Eficient parallelization of an existing algorithm is a major undertaking.
Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:25AM (#26446386)
> In embedded applications you don't usually have the possibility to have parallel code, and even in low level software (for example the classical UNIX utilities), for simplicity and solidity using a single thread is really fine.

Depends on which of the classic utilities you are talking about.

Many of them are typically IO bound. You might not get much out of throwing more CPU at them.

Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @08:31AM (#26446420)
ripgrep? :)
Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:38AM (#26446820)
Indeed. Many of the optimizations ripgrep (and the underlying regex engine) does only show benefits if the data you're searching is already in memory.[1] The same is true of GNU grep. This is because searching data that's in your OS's file cache is an exceptionally common case.

[1] - I'm assuming commodity SSD in the range of a few hundred MB/s read speed. This will likely become less true as the prevalence of faster SSDs increases (low single digit GB/s).

Re:Speed of Rust vs. C by tsegratis on Saturday March 13, 2021 @09:47AM (#26446887)
ripgrep is based on re2, a c library

I would guess it contains more c than rust code...

But what I love about this article is its lack of hype. It makes clear arguments both ways and all of them I can get behind

Hype doesn't help

Edit: To all my downvoters; I anticipated you :) With love and best wishes

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @10:00AM (#26446975)
No it's not. Its regex library is written in Rust, but was inspired by RE2. It shares no code with RE2. (And RE2 is a C++ library, not C.)

Off the top of my head, the only C code in ripgrep is optional integration with PCRE2. In addition to whatever libc is being used on POSIX platforms. Everything else is pure Rust.

Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:32PM (#26451928)
It couldn't figure it out from looking through ripgrep's website: does ripgrep support intersection and complement of expressions? Like eg https://github.com/google/redgrep does.

Regular languages are closed under those operations after all.

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:21PM (#26452187)
No, it doesn't. It's only theoretically easy to implement. In practice, they explode the size of the underlying FSM. Moreover, in a command line tool, it's somewhat easy to work around that through the `-v` switch and shell pipelining.

Paul's talk introduced redgrep is amazing by the way. Give it a watch if you haven't yet: https://www.youtube.com/watch?v=Ukqb6nMjFyk

ripgrep's regex syntax is the same as Rust's regex crate: https://docs.rs/regex/1.4.4/regex/#syntax (Which is in turn similar to RE2, although it supports a bit more niceties.)

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @01:24AM (#26453240)
> No, it doesn't. It's only theoretically easy to implement.

Oh, I didn't say anything about easy! I am on and off working on a Haskell re-implementation (but with GADTs and in Oleg's tagless final interpreter style etc, so it's more about exploring the type system).

> In practice, they explode the size of the underlying FSM.

You may be right, but that's still better than the gymnastics you'd have to do by hand to get the same features out of a 'normal' regex.

> Moreover, in a command line tool, it's somewhat easy to work around that through the `-v` switch and shell pipelining.

Alas, that only works, if your intersection or complement happen at the top level. You can't do something like

(A & not B) followed by (C & D)

that way.

> Paul's talk introduced redgrep is amazing by the way. Give it a watch if you haven't yet: https://www.youtube.com/watch?v=Ukqb6nMjFyk

I have, and I agree!

Perhaps I'll try and implement a basic version of redgrep in Rust as an exercise. (I just want something that supports basically all the operations regular languages are closed, but don't care too much about speed, as long as the runtime complexity is linear.)

Re:Speed of Rust vs. C by burntsushi on Sunday March 14, 2021 @11:05AM (#26455986)
Yeah sorry, I've gotten asked this question a lot. The issue is that building a production grade regex engine---even when it's restricted to regular languages---requires a lot more engineering than theory. And these particular features just don't really pull their weight IMO. They are performance footguns, and IMO, are also tricky to reason about inside of regex syntax.

If you get something working, I'd love to look at it though! Especially if you're building in a tagless final interpreter style. I find that approach extremely elegant.

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @11:54PM (#26462476)
For my current attempts, I bit off more than I could chew:

I tried to build a system that not only recognizes regular languages, but also serves as a parser for them (a la Parsec).

The latter approach pushes you to support something like fmap, but the whole derivatives-based approach needs more 'introspection' so support general mapping via fmap (ie a->b) is out, and you can only support things that you have more control over than functions.

(And in general, I am doing bifunctors, because I want the complement of the complement be the original thing.)

Sorry, if that's a bit confused.. If I was a better theoretician, I could probably work it out.

I haven't touched the code in a while. But recently I have thought about the theory some more. The Brzozowski derivative introduced the concept of multiplicative inverse of a string. I am working out the ramifications of extending that to the multiplicative inverse of arbitrary regular expressions. (The results might already be in the literature. I haven't looked much.)

I don't expect anything groundbreaking to come out of that, but I hope my understanding will improve.

> And these particular features just don't really pull their weight IMO. They are performance footguns, and IMO, are also tricky to reason about inside of regex syntax.

Well, in theory I could 'just' write a preprocessor that takes my regex with intersection and complement and translates it to a more traditional one. I wouldn't care too much if that's not very efficient.

I'm interested in those features because of the beauty of the theory, but it would also help make production regular expressions more modular.

Eg if you have a regular expression to decide on what's a valid username for someone to sign up to your system. You decide to use email addresses as your usernames, so the main qualification is that users can receive an email on it. But because they will be visible to other users, you have some additional requirements:

'.{0,100} & [^@]@[^@] & not (.(root|admin|<some offensive term>).@.) & not (.<sql injection>.*)'

That's a silly example. I think in production, I would be more likely to see something as complicated as this in eg some ad-hoc log parsing.

> The issue is that building a production grade regex engine---even when it's restricted to regular languages---requires a lot more engineering than theory.

Amen to that!

Re:Speed of Rust vs. C by tsegratis on Saturday March 13, 2021 @11:26AM (#26447586)
Ah, thanks burntsushi, I believe you are the ripgrep author even?

Great work btw. Ripgrep is the best

... I will have to restrict my comment to just LLVM being a larger, c++, dependency

... Just angling for more downvotes ;) Thanks for the reply

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @11:44AM (#26447729)
To be clear, ripgrep has no runtime dependency on any LLVM or C++ library. rustc does.
Re:Speed of Rust vs. C by tsegratis on Saturday March 13, 2021 @12:21PM (#26448034)
The interesting thing here is that rust has good threading and fantastic crates

I played with making a regex library in rust. Which, as per RE2 design involves constructing graphs and glueing them together as the regex is traversed

This requires a cycle catching gc, or, just a preallocated arena... It was my first foray into rust and felt I would need to be hitting into unsafe, which I wasn't ready for. Array indexing might decompose into an arena, but syntactically just a bit messier (imho)

Would be interesting to see how the RE2 does it in rust (didn't know that)

I like how the article shows both sides of the fence, it makes me realize:

I get a lot of optimizations from ptr stuffing in c. But sometimes we should lay down the good, for the better

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @12:34PM (#26448158)
You're overcomplicating it. When it comes to finite state machines at least, it's very easy to use an ID index instead of the raw pointer itself. That's exactly what the regex crate does.

For reference, I am also the author of the regex crate. The only unsafe it uses specific to finite automata is to do explicit elimination of bounds checks in the core hybrid NFA/DFA loop.

Re:Speed of Rust vs. C by rstuart4133 on Sunday March 14, 2021 @06:25AM (#26454131)
> When it comes to finite state machines at least, it's very easy to use an ID index instead of the raw pointer itself.

As an old C programmer, the difference between an array index and a pointer caught me by surprise. In C a pointer is just an unchecked offset into memory. A real array index is just a unchecked offset into ... maybe a smaller chunk of raw memory.

But in rust, an array index is something that comes with additional bounds checking overheads with every use. And the memory it points to is also constrained - the entire array has to be initialised, so if the index passes the bounds check you are guaranteed rusts memory consistency invariants are preserved. Indexes also allow you to escape the borrow checker. If you own the slice, there is no need to prove you can access an element of the slice.

So yeah, you can use indexes instead of pointers, but for rust that's like saying you can use recursion instead of iteration. Indexing and pointers are two very different things in rust.

Re:Speed of Rust vs. C by burntsushi on Sunday March 14, 2021 @11:10AM (#26456032)
I guess so. But note that I didn't equate them. I just said that you can use an ID index instead. For the particular program of FSMs, they work very well.

If bounds checks prove to be a problem, you can explicitly elide them. Indeed, Rust's regex does just that. :-)

Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:33PM (#26451938)
> I played with making a regex library in rust. Which, as per RE2 design involves constructing graphs and glueing them together as the regex is traversed

You could instead go with a derivatives approach.

https://en.wikipedia.org/wiki/Brzozowski_derivative

Re:Speed of Rust vs. C by burntsushi on Saturday March 13, 2021 @09:23PM (#26452194)
Has anyone built a production grade regex engine using derivatives? I don't think I've seen one. I personally always get stuck at how to handle things like captures or the very large Unicode character classes. Or hacking in look-around. (It's been a while since I've given this thought though, so I'm not sure I'll be able to elaborate much.)
Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @01:40AM (#26453295)
I've made some attempts, but nothing production grade.

About large character classes: how are those harder than in approaches? If you build any FSM you have to deal with those, don't you?

One way to handle them that works well when the characters in your classes are mostly next to each other unicode, is to express your state transition function as an 'interval map'

What I mean is that eg a hash table or an array lets you build representations of mathematical functions that map points to values.

You want something that can model a step function.

You can either roll your own, or write something around a sorted-map data structure.

Eg in C++ you'd base the whole thing around https://en.cppreference.com/w/cpp/container/map/upper_bound (or https://hackage.haskell.org/package/containers-0.4.0.0/docs/... in Haskell.)

The keys in your sorted map are the 'edges' of your characters classes (eg where they start and end).

Does that make sense? Or am I misunderstanding the problem?

> I personally always get stuck at how to handle things like captures [...]

Let me think about that one for a while. Some Googling suggests https://github.com/elfsternberg/barre but they don't seem to support intersection, complement or stripping prefixes.

What do you want your capture groups to do? Do you eg just want to return pointers to where you captured them (if any)?

I have an inkling that something inspired by https://en.wikipedia.org/wiki/Viterbi_algorithm might work.

https://github.com/google/redgrep/blob/main/parser.yy mentions something about capture, but not sure if that has anything to do with capture groups.

Re:Speed of Rust vs. C by burntsushi on Sunday March 14, 2021 @11:19AM (#26456107)
> About large character classes: how are those harder than in approaches? If you build any FSM you have to deal with those, don't you?

I mean specifically in the context of derivatives. IIRC, the formulation used in Turon's paper wasn't amenable to large classes.

Yes, interval sets work great: https://github.com/rust-lang/regex/blob/master/regex-syntax/...

This is why I asked if a production grade regex engine based on derivatives exists. Because I want to see how the engineering is actually done.

> What do you want your capture groups to do? Do you eg just want to return pointers to where you captured them (if any)?

Look at any production grade regex engine. It will implement captures. It should do what they do.

> I have an inkling that something inspired by https://en.wikipedia.org/wiki/Viterbi_algorithm might work.

Nothing about Viterbi is fast, in my experience implementing it in the past. :-)

> https://github.com/google/redgrep/blob/main/parser.yy mentions something about capture, but not sure if that has anything to do with capture groups.

It looks like it does, and in particular see: https://github.com/google/redgrep/blob/6b9d5b02753c4ece17e2f...

But that's only for parsing the regex itself. I don't see any match APIs that utilize them. I wouldn't expect to either, because you can't implement capturing inside a DFA. (You need a tagged DFA, which is a strictly more powerful thing. But in that case, the DFA size explodes. See the re2c project and their associated papers.)

If I'm remembering correctly, I think the problem with derivatives is that they jump straight to a DFA. You can't do that in a production regex engine because a DFA's worst case size is exponential in the size of the regex.

Re:Speed of Rust vs. C by eru on Sunday March 14, 2021 @11:57PM (#26462489)
> If I'm remembering correctly, I think the problem with derivatives is that they jump straight to a DFA. You can't do that in a production regex engine because a DFA's worst case size is exponential in the size of the regex.

Oh, that's interesting! Because I actually worked on some approaches that don't jump directly to the DFA.

The problem is the notion of (extended) NFA you need is quite a bit more complicated when you support intersection and complement.

Re:Speed of Rust vs. C by burntsushi on Monday March 15, 2021 @05:25PM (#26469287)
Indeed. And in the regex crate and RE2, for example, captures are only implemented in the "NFA" engines (specifically, the PikeVM and the bounded backtracker). So if you support captures, then those engines have to be able to support everything.
Re:Speed of Rust vs. C by tsegratis on Tuesday March 16, 2021 @06:00AM (#26474790)
Can I ask; what about a zdd?

The seem similar to closed languages with a disjunct and conjunct

Though I don't think I will, I was considering adding zdd or bdd to a PEG, to provide that conjunct

ofc, sat solver can represent a regex with conjuncts, but is this a good way of going about it, particularly with unbounded strings??

Would love to hear your thoughts on that

Re:Speed of Rust vs. C by mplanchard on Saturday March 13, 2021 @11:37AM (#26447678)
I don’t think people are downvoting you because they disagree on a matter of opinion. You’ve literally got the author of ripgrep having replied to you to tell you that what you’ve said is categorically false.
Re:Speed of Rust vs. C by tsegratis on Saturday March 13, 2021 @12:38PM (#26448187)
I anticipated my own falsity. I'm aware and at home with it
Re:Speed of Rust vs. C by eru on Saturday March 13, 2021 @08:34PM (#26451943)
Huh? Why do you say something that you anticipate to be false?
Re:Speed of Rust vs. C by tsegratis on Sunday March 14, 2021 @11:55AM (#26456358)
Simply bervity

I anticipated I could well be wrong. I ALSO anticipated it would be a hard statement for people to take

I think it was a reasonable statement -- I can't research everything I say, and I had read re2 and regexes in rust to be the same

Interesting to read about redgrep and derivatives approach. Currently I'm programming a language that adds turing completeness to PEG expressions -- as in functions, but extended so the lhs is like a PEG -- just as function body can call sub functions, so too can the lhs

I'm hoping this will give a simple unified language

--

Philosophically:

We make mistakes. If we can't handle that, then either we don't speak or program; or we deny it, program in c, then have flamewars and real wars

Or thirdly, we accept it, program in rust, and let others correct us

We can say you are my rustc compiler. So in effect I used a rust philosophy..... While programming in c

Re:Speed of Rust vs. C by mplanchard on Sunday March 14, 2021 @02:21PM (#26457454)
I guess the thing is that if we’re not sure whether or not what we’re saying is true, it can be considerate to phrase it that way, e.g. “I think ripgrep’s regex library is written in C” rather than stating it as a fact. While it is particularly likely that folks on this website will correct mistaken statements, stating them as fact seems more likely to potentially spread misinformation.

But anyways, cheers and good luck with your programming language!

Re:Speed of Rust vs. C by tsegratis on Sunday March 14, 2021 @01:47PM (#26457179)
In one word: Jesus
Re:Speed of Rust vs. C by carols10cents on Saturday March 13, 2021 @01:29PM (#26448700)
Why would you guess about how much C or Rust code that ripgrep contains when you could very quickly look? https://github.com/BurntSushi/ripgrep
Re:Speed of Rust vs. C by ben0x539 on Saturday March 13, 2021 @04:56PM (#26450395)
Hm, how do I go from the github repo to a language breakdown of the dependency tree?
Re:Speed of Rust vs. C by fulafel on Saturday March 13, 2021 @08:35AM (#26446451)
A lot of modern embedded hw are running operating systems providing threads (such as Linux) and multi-core CPUs.
Re:Speed of Rust vs. C by ReactiveJelly on Saturday March 13, 2021 @09:32AM (#26446786)
Deadlocks are unique to Rust, eh?