Hacker News new | ask | show | jobs
by cydonian_monk 3688 days ago
Exactly. It's beyond my authority to change the language in use, but I would love to have alternatives to argue for. C isn't a terrible option, or is perhaps the least terrible option, but it's not leaving my corner of the corporate universe until a proven alternative establishes itself.
1 comments

What in particular makes Rust (or Go or Swift) unsuitable?
GC languages are almost certainly not even in consideration for most embedded applications. There aren't good strategies for general garbage collection that don't insert random pauses for starters, and you also have a non-negligible impact on RAM usage on systems where RAM might be a premium.

A lot of the things rust brings to the table aren't always relevant on embedded platforms. Dynamic memory allocation on embedded is the exception, not the rule. Everything is statically allocated, so memory management is relatively simple -- everything sticks around forever.

The things that make C/C++ good for embedded are sorta what make it unfortunate for general purpose use. The things that make Rust/Go/Swift good for general purpose use make it unfortunate for embedded use.

> A lot of the things rust brings to the table aren't always relevant on embedded platforms. Dynamic memory allocation on embedded is the exception, not the rule. Everything is statically allocated, so memory management is relatively simple -- everything sticks around forever.

In that case, you can simply not use the dynamic allocation features of Rust, just as you can simply not use malloc() in C.

Absolutely, but then what does it buy you over C/C++? It has a few 'nice to haves' over that, but in this domain those won't tend to be nice enough to motivate most people to bother setting up toolchains purposed for it.

  > GC languages
Rust is not a GC'd language, it essentially uses RAII to deterministically determine at compilation time when memory will be freed.

  > Dynamic memory allocation on embedded is the exception
Rust fully supports running entirely without dynamic allocation. There is a subset of the standard library defined explicitly for this purpose.
> Rust is not a GC'd language

Right, I was referring to Go and Swift with the comment about GC. Since rust didn't have that problem, I mentioned why major adoption might not be forthcoming.

I understand that you can statically allocate all you want in Rust, but it's memory safety, particularly with regards to object ownership is one of its major selling points. Object ownership and lifetimes are trivial when everything is static.

The other arguable selling point to rust is its standard library, but much like C++ the standard library would be left aside in most embedded applications.

So it doesn't buy you much of anything at all, but it takes some work to setup, plus you are fighting the momentum that C/C++ has. Unless there is some other compelling reason to use it, I don't expect much adoption.

Doesn't the design of Go, the language, basically require that the implementation involve a runtime with a GC system? So that would make it a non-viable choice for programming in applications where memory footprint and real-time performance must be tightly controlled.

Rust is a better choice, and it's designed with this in mind. It's still young, though, and I think there might be some as-yet-unsolved issues (these are things I've vaguely heard of and could be totally off-base) like binary size, ease of dealing with raw pointers, etc.

If I was doing this sort of programming for a personal project, I'd probably try using Rust, because I like it.

Dunno about Swift, though IIRC the current reference implementation may also currently rely on GC.

  > like binary size, ease of dealing with raw pointers, etc
The majority in the size of typical Rust binaries is the huge amount of space (400 kb or so) that it takes to statically link jemalloc. But if you're building for a device that doesn't support dynamic allocation then you're not going to be including jemalloc, so binary size shouldn't be a problem.

As for raw pointers, they're exactly as capable as raw pointers in C, though they're deliberately more verbose as well, because even in embedded contexts one should be favoring references over raw pointers, since references are still fully checked for safety even in embedded mode and yet are represented by raw pointers at runtime and hence have zero runtime overhead.

Rusts binary size issues are just a matter of defaults, and they're an additive bloat, not multiplicative (If the corresponding rust binary for a 5kb C binary is 200kb, then the corresponding rust binary for a 100kb C binary is 305kb). Most people don't care about a few extra kilobytes in their binary, so Rust has chosen defaults that make some things easier but also add some extra binary size. You can turn these off and get tiny binaries if you wish without much effort.
Ironic, but the one think they are missing is an easy convenient way to call C libraries.

Rust is very promising language, but unless you plan to write everything from scratch, you have to depend on 3rd party driver implementations for most stuff. Databases for example. There isn't a single database vendor that has Rust drivers.

Calling C from Rust is very convenient. All you have to do is declare the structs and function signatures and then it's like calling any other unsafe function.
IMHO it is OK if you are only going to call a few simple one, but for calling a few hundred complex ones (callbacks with variable argument list, etc..), it becomes a bit cumbersome.

BTW I am not implying that is Rust's fault, actually I can't think a syntax that would make it less verbose, and I am a huge Rust fan.

Not really, there are tools that can take C header files and spit out bindings. Rust also supports vararg C functions even though Rust itself doesn't support varargs. Writing safe Rust wrappers around these unsafe C bindings can sometimes be tedious, but this isn't worse than using C directly (which is inherently unsafe).
I didn't say it is not supporting them. I said that is a bit cumbersome to have to write the shims for them.

I wasn't aware of the tools that do this automatically. Just found one and it looks promising.

actually I can't think a syntax that would make it less verbose.

something like C::function_from_c() is one option

For very extensive C APIs like this (Lua, GTK, etc.) we typically see people create thin, Rust-friendly wrappers to reduce the amount of manual API calls that need to be written out.
Go is unsuitable as a replacement for C because it is garbage collected. End of discussion.

Rust is unsuitable as a replacement for C because its memory management is poorly thought out (ie. its a joke). Here's the relevant paragraphs from the Rust FAQ. Really?

"Rust avoids the need for GC through its system of ownership and borrowing, but that same system helps with a host of other problems, including resource management in general and concurrency.

For when single ownership does not suffice, Rust programs rely on the standard reference-counting smart pointer type, Rc, and its thread-safe counterpart, Arc, instead of GC.

We are however investigating optional garbage collection as a future extension. The goal is to enable smooth integration with garbage-collected runtimes, such as those offered by the Spidermonkey and V8 JavaScript engines. Finally, some people have investigated implementing pure Rust garbage collectors without compiler support."

> For when single ownership does not suffice, Rust programs rely on the standard reference-counting smart pointer type, Rc, and its thread-safe counterpart, Arc, instead of GC.

This is a library thing, not a language thing.

If single ownership is enough for you, go ahead and use it. But if you need a different memory management strategy, that is available too.

Rust, the language, provides a single clear memory management strategy. It also provides the ability to design your own abstractions for different strategies, and implements some of these in the stdlib.

C/C++ have refcounting and GC libraries too. Does that make them a joke?

You don't describe why you think it's a joke.
Steve - did you read the FAQ? They really don't know what direction to go. At least Swift stuck with ARC, being a necessity as they were tasked with merging Swift with the Objective-C runtime for interoperability. Rust's multiple methods of memory management makes it strange, at best, for programmers to decide how to build a program or an API. Are the owners of Rust planning on adding a GC? Really?
I helped edit the FAQ.

  > They really don't know what direction to go.
That's incorrect. A systems language needs to be flexible; it cannot dictate that everyone must do something a single way.

Does the presence of libraries for refcounting or even GC in C (most famously Boehm) mean that C has an incoherent story around memory?

  > Rust's multiple methods of memory management makes it strange, at best,
  > for programmers to decide how to build a program or an API.
It does not. Each has their place. Need single ownership? Use a type that has it. Need multiple ownership? Use a type that has it.

  >  Are the owners of Rust planning on adding a GC? Really?
Not really. There's a few different things here: first is integrations with other systems that have a GC. As an example, consider Servo: it has to interact with Spidermonkey's GC, since it interfaces with JavaScript code. Consider the opposite system: Rust embedded inside of another language, let's say Python, where you want to be able to talk to Python's GC for various reasons.

The second is something like Bohem: if a system wants to use GC for some reason, they have an interface to add a GC'd type. But Rust proper, the language, will not have GC. It's completely contradictory to the goals of the language.

> Are the owners of Rust planning on adding a GC? Really?

To address this specifically: Current plans for Rust are mostly along the lines of adding the bare necessities in the stdlib to allow GC implementations to be written.

There are mostly-niche use-cases for having a GC in Rust. I've written some of the motivation here[1] (note that that blog post is about a pure library GC independent of Rust, which is different from what is planned; but the motivations are similar).

One major use case is if you want to talk to a language which has a GC. Say you're writing a native extension to a Ruby or Node and want to deal with the GCd types within Rust code in a safe way without pausing the GC. Or if you're writing an interpreter for a GCd language. Or you're writing some code that deals with complicated cyclic graph-like datastructures.

These are all pretty niche, but the workarounds in these cases aren't pretty so it's nice to have some form of GC capabilities in Rust. This is not a price you pay by default, and it's not something that affects anyone but the people who need these types. It will probably take the form of some low level APIs that use LLVM stack rooting to collect roots, and some traits in the stdlib, which can be used by an independent GC library (not part of the stdlib) or a language bindings library (also not part of the stdlib).

Rust itself will never get a GC as part of the language.

[1]: http://manishearth.github.io/blog/2015/09/01/designing-a-gc-...

Steve wrote the FAQ and most of the docs
I would hesitate to say I write the FAQ these days; after Brian's efforts to revamp it, it was VERY MUCH a community effort.
This post is a joke without a material argument to support your claim.