www. O S N E W S .com
News Features Interviews
BlogContact Editorials
.
The benefits and costs of writing a POSIX kernel in Go
By Thom Holwerda on 2018-10-08 23:51:05

This paper presents an evaluation of the use of a high-level language (HLL) with garbage collection to implement a monolithic POSIX-style kernel. The goal is to explore if it is reasonable to use an HLL instead of C for such kernels, by examining performance costs, implementation challenges, and programmability and safety benefits.

The paper contributes Biscuit, a kernel written in Go that implements enough of POSIX (virtual memory, mmap, TCP/IP sockets, a logging file system, poll, etc.) to execute significant applications. Biscuit makes liberal use of Go's HLL features (closures, channels, maps, interfaces, garbage collected heap allocation), which sub- jectively made programming easier. The most challenging puzzle was handling the possibility of running out of kernel heap memory; Biscuit benefited from the analyzability of Go source to address this challenge.

On a set of kernel-intensive benchmarks (including NGINX and Redis) the fraction of kernel CPU time Biscuit spends on HLL features (primarily garbage collection and thread stack expansion checks) ranges up to 13%. The longest single GC-related pause suffered by NGINX was 115 microseconds; the longest observed sum of GC delays to a complete NGINX client request was 600 microsec- onds. In experiments comparing nearly identical system call, page fault, and context switch code paths written in Go and C, the Go version was 5% to 15% slower.

Scientific papers about operating system experiments - who doesn't love them?

 Email a friend - Printer friendly - Related stories
.
Post a new comment
Read Comments: 1-10 -- 11-20 -- 21-30 -- 31-40 -- 41-50 -- 51-54
.
RE[3]: Excellent find Thom!
By Lennie on 2018-10-10 17:52:27
Well you can combine Rust and C(++) and I assume assembly language in the same project.

Because Mozilla is doing it for their C++ code base:

https://research.mozilla.org/serv...

"Hopefully, Rust is a pretty intuitive language for C++ programmers. Most of the syntax is pretty similar. The big difference (in my experience) is that the sometimes vague concepts of good systems programming are strictly enforced by the compiler. This can be infuriating at first - there are things you want to do, but the compiler won't let you (at least in safe code), and sometimes these things are safe, but you can't convince the compiler of that. However, you'll quickly develop a good intuition for what is allowed. Communicating your own notions of memory safety to the compiler requires some new and sometimes complicated type annotations. But if you have a strong idea of lifetimes for your objects and experience with generic programming, they shouldn't be too tough to learn."

https://github.com/nrc/r4cppp
Permalink - Score: 3
.
RE[7]: Comment by FlyingJester
By kwan_e on 2018-10-10 18:12:28
> The main use case I can think of where this Go kernel might be a problem is anything requiring very low latency. So, for example, high throughput network routing. A 15% dip in performance here might add 15% to the bottom line latencies, and a corresponding loss of throughput.

Ironically one of the many systems you'd want the most security. Which brings us back to square one. The systems we want the most security are also the systems where performance is also paramount, and why both the languages and their security bugs go hand in hand. Software engineering is about information hiding, but performance requires breaking through some abstractions to treat them as they are.

> Anywhere else, that performance lost will be eaten by Moore's Law in a couple of months. Otherwise, it's just 15% on top of typically less than 15% kernel time for the other use cases.

This attitude is why end-user software still hasn't improved efficiency in years, as discussed many times on OSNews. A wise person once said: "all computers wait at the same speed". Moore's Law doesn't really help, since software also increases in complexity over those same months.

> I, personally, would happily pay that price on any of my (non low-latency critical) computers.

How about your battery-powered handheld computers? 15% of its charge being used to clean up garbage?
Permalink - Score: 3
.
RE[10]: Comment by FlyingJester
By christian on 2018-10-10 21:09:21
> christian,

> Being a slab based allocator, marking a block of memory is simply a matter of bit twiddling to the mark bitmap as to mark the block as in use. Once everything is marked, the mark bitmap simply becomes the in-use bitmap used when allocating new memory from the heap. The sweep stage of my GC is simply replacing the in-use bitmap with the mark bitmap. If there are no finalizers declared for a slab type, that's it, no more to do. If a finalizer is defined, it has to be called with each block that is now determined to be dead, but I've only actually used the finalizer for testing.

I'm curious, in your implementation, I assume you stop the other processes from running while you scan?
If so, then you may as well do the GC on the same cores as your program since it cannot run anyways.


At the moment, I only do GC in the idle thread, so other threads are stopped by default waiting on something else.

>


> This is work that can easily be done in parallel with other useful work, and adding more cores just makes it truly parallel.

I think it's possible, but I don't think it's easy because you can't scan objects while work is being done on them due to race conditions. Unless you do something clever like in the link earlier, access to objects will need to be protected by synchronization primitives. This adds complexity and overhead. Or am I misunderstanding something?



This is all very much theoretical at the moment, as I'm uni-processor only at this point, and GC when idle, so there can be no race conditions.

What I envisage, though, is that the GC can mark all threads that are not running. The running threads can continue on their merry way, and if they call into the allocator at all, they can take that opportunity to briefly stop and mark their own thread roots, mark whatever it is they've just allocated, then continue on. Else, they can spot the outstanding GC in progress at their next schedule point. Or, if GC is invoked because memory is really low, they can be interrupted with an IPI to finish their portion of the marking as soon as possible. This last case would be the main potential problem, as IPIs are relatively slow and the remaining marking of unknown bounds, though most of the live data should have already been marked (we don't mark memory twice, we ignore already marked data.)
Permalink - Score: 2
.
RE[8]: Comment by FlyingJester
By Alfman on 2018-10-11 00:44:16
kwan_e,

> Ironically one of the many systems you'd want the most security. Which brings us back to square one. The systems we want the most security are also the systems where performance is also paramount, and why both the languages and their security bugs go hand in hand. Software engineering is about information hiding, but performance requires breaking through some abstractions to treat them as they are.

I agree that for a router, you want the absolute minimum latency possible and a GC is probably not the way to go. To be fair though, there are a lot of cases where security is more important than small performance gains. Think banking, HIPAA, PCI, etc. It's not that performance isn't important, but that security is clearly more important.


> This attitude is why end-user software still hasn't improved efficiency in years, as discussed many times on OSNews. A wise person once said: "all computers wait at the same speed". Moore's Law doesn't really help, since software also increases in complexity over those same months.

I've worked at software development companies that produced some downright sluggish software. The project managers would justify this using the same arguments we all know, but it usually resulted in much higher hardware requirements and also a subpar experience.

So yea I do agree that software should be designed for yesterday's hardware rather than tomorrow's. This way the performance will be snappy for typical users. It's a big gripe of mine that in this day and age, software can still be so sluggish.


> How about your battery-powered handheld computers? 15% of its charge being used to clean up garbage?

It's not 15% overall because the phone won't be running inside the kernel 100% of the time. It'd be more in the ballpark of 2% overhead overall depending on how much time is actually spent in the kernel. I personally wouldn't push for GC in the kernel, but at the same time I don't necessarily think it's an unreasonable idea. To the extent that someone wants to try, I say go for it, we could all learn from their experiences, both positive and negative :)
Permalink - Score: 2
.
RE[11]: Comment by FlyingJester
By Alfman on 2018-10-11 01:08:46
christian,

> This is all very much theoretical at the moment, as I'm uni-processor only at this point, and GC when idle, so there can be no race conditions.

Yeah, that simplifies the problem, but not a long term solution obviously. On the other hand, it could actually be a long term solution if you treat the other CPU cores as a cluster rather than an SMP machine...it's food for thought.

> What I envisage, though, is that the GC can mark all threads that are not running. The running threads can continue on their merry way, and if they call into the allocator at all, they can take that opportunity to briefly stop and mark their own thread roots, mark whatever it is they've just allocated, then continue on.

Ok. The thing I'd be concerned about is one thread modifying a reference at the same moment the GC is trying to scan/mark it. You could obviously use locks, but performance would suffer. Anyways it'll be interesting to hear from you when you get to implementing SMP.
Permalink - Score: 3
.
RE[9]: Comment by FlyingJester
By kwan_e on 2018-10-11 04:03:16
> To be fair though, there are a lot of cases where security is more important than small performance gains. Think banking, HIPAA, PCI, etc. It's not that performance isn't important, but that security is clearly more important.

In these cases, I'd fully expect them to be written in easier, higher level languages, with security policies designed around human flaws. But that takes us out of kernel space and malevolent parties would get better results with phishing and social engineering rather than hoping to trigger a kernel bug.

For sure, memory access bugs dominate CVEs, but I feel like there have been more security breaches traced to the end-user side (and middleware bugs, such as SQL injection attacks) than have been traced to memory access bugs.
Permalink - Score: 3
.
RE[10]: Comment by FlyingJester
By Alfman on 2018-10-11 13:31:24
kwan_e,

> In these cases, I'd fully expect them to be written in easier, higher level languages, with security policies designed around human flaws. But that takes us out of kernel space and malevolent parties would get better results with phishing and social engineering rather than hoping to trigger a kernel bug.

I find our computer language norms a bit ironic though. Clearly the kernel plays a special role in accepting syscalls from all processes, yet apart from that it really resembles a big client/server design. It's become accepted practice to write middleware and client software in "easier, higher level languages", yet for kernels we remain quite partial to C. From a technical point of view, I'm not sure that I can explain why we should use C in the kernel and not use C in middleware or why we should use high level languages in middleware but not use HLL in the kernel. The kernel is mostly just a big message passing mechanism, not altogether different from the middleware software.

I believe our choices and language preferences by now are mostly just following the conventions we grew up with.


> For sure, memory access bugs dominate CVEs, but I feel like there have been more security breaches traced to the end-user side (and middleware bugs, such as SQL injection attacks) than have been traced to memory access bugs.

Arguably many kinds of bugs can be effectively neutralized at the library/language level when we approach the problem with an eye for safety. SQL injection used to be a huge recurring problem when the standard practice for building SQL commands was to concatenate strings. Now we have better ways to do it: SQL parameters. SQL injection can be virtually eradicated (except for those who insist on not using parameters). As an added benefit, SQL parameters can eliminate data conversion overhead and help the SQL parser lookup cached queries.
Permalink - Score: 3
.
RE[11]: Comment by FlyingJester
By kwan_e on 2018-10-11 16:25:17
> The kernel is mostly just a big message passing mechanism, not altogether different from the middleware software.

It's kernels all the way down.
Permalink - Score: 3
.
RE[10]: Comment by FlyingJester
By moondevil on 2018-10-11 18:32:16
According to the Linux Security Summit 2018 talks, 68% of the kernel exploits were caused by out-of-bounds memory corruption.
Permalink - Score: 3
.
RE[11]: Comment by FlyingJester
By kwan_e on 2018-10-11 21:19:45
> According to the Linux Security Summit 2018 talks, 68% of the kernel exploits were caused by out-of-bounds memory corruption.

Yes, but how many of them lead to actual security breaches. An exploit does not necessary lead to an actual incident. You can have exploits for every part of the kernel, but have they actually resulted in sensitive data being accessed?

Compared to when government employees just leave hard drives around, or banks who lose a truck full of backup tapes, or a shopping website leaving customer details in plain text accessible from the internet.
Permalink - Score: 2

Read Comments 1-10 -- 11-20 -- 21-30 -- 31-40 -- 41-50 -- 51-54

There are 1 comment(s) below your current score threshold.

Post a new comment
Username

Password

Title

Your comment

If you do not have an account, please use a desktop browser to create one.
LEAVE SPACES around URLs to autoparse. No more than 8,000 characters are allowed. The only HTML/UBB tags allowed are bold & italics.
Submission of a comment on OSNews implies that you have acknowledged and fully agreed with THESE TERMS.
.
News Features Interviews
BlogContact Editorials
.
WAP site - RSS feed
© OSNews LLC 1997-2007. All Rights Reserved.
The readers' comments are owned and a responsibility of whoever posted them.
Prefer the desktop version of OSNews?