Hacker News new | ask | show | jobs
by sshine 920 days ago
Tooting the Rust horn in predictable ways:

Why would you want to restart a service frequently?

  - Flush incorrect state
  - Reset memory leaks
  - ...others reasons?
Rust's borrow system makes it harder (but not impossible) to have memory leaks.

Rust's immutable-by-default semantics makes it harder (but not impossible) to end up where your long-running process'es state is incorrect.

You can still mark everything as `&mut` and litter the code with ref-counts. I've seen a lot of this "removing the safety rails because it's more convenient" among C/C++ developers who were forced into using Rust.

I think a bigger attack vector for anything dynamic, including a type-safe, memory-safe Axum back-end service, is denial-of-service because requests take too long to process. Application development is always vulnerable for being feature-driven: features sure do like resources! A service doesn't need bugs to get killed efficiently. It just needs to get slow over time.

2 comments

> Why would you want to restart a service frequently?

As mentioned in the original comment - I haven’t found a web framework which supports timeouts for idle TCP connections (they all seem to be built on top of Hyper, which doesn’t support them). And so even tweaking kernel parameters to bump up the connection limit to a few hundred thousand (any higher than that and I start hitting a different set of problems), and only having a few thousand actually active connections, my app still runs out of sockets and hangs after a few hours.

Close to memory leaks, but not exactly: memory fragmentation. Unlike runtimes with managed memory such as JVM, Rust apps cannot take a pause and defragment the memory heap, which depending on frequency and sizes of allocations sooner or later will lead to your app taking up a huge chunk of memory and not using it efficiently.
Wouldn’t this be a criticism of any long-running program which uses dynamic allocation, not only Rust? It’s the operating system’s job to manage fragmentation in the allocator, right? And it’s straightforward to switch to jemalloc, which often improves on the system allocator.
> And it’s straightforward to switch to jemalloc, which often improves on the system allocator.

It is true that jemalloc is much better than the standard malloc, but it still suffers from memory fragmentation, although typically a program can run for much longer with it.

> It’s the operating system’s job to manage fragmentation in the allocator, right?

No, not really. The operating system does nothing with the memory space of the process, other than providing syscalls for giving the process more pages.

> Wouldn’t this be a criticism of any long-running program which uses dynamic allocation, not only Rust?

What some thicker runtimes such as JVM do is that 1) they track all pointers present in the data used by the program and do not allow programs to cast them to raw integers (or back); 2) they can defragment the heap by moving the memory chunks around to fill in the gaps and at the same time they rewrite all pointers that point to moved chunks so that they still point to the same data.

I know what JVM does, I was talking about other “native-allocator” stacks like C and C++, which are used in many very popular long-running services.