Using Go for NTPsec

Eric S. Raymond esr at thyrsus.com
Wed Jul 7 12:06:56 UTC 2021


Hal Murray <halmurray at sonic.net>:
> > You're thinking in C. This is a problem, because mutex-and-mailbox
> > architectures don't scale up well.  Human brains get overwhelmed at about 4
> > mutexes; beyond that the proliferation of corner cases get to be more than
> > the meat can handle.
> 
> I'm missing something.  What is the problem with lots of mutexes?  I'm 
> guessing you are thinking of deadlocks.  They don't happen if code running 
> with the lock held doesn't call any code that needs another lock -- a leaf 
> node in the tree.  I think my brain can handle lots of leaf nodes.

How do you know something is a leaf node?  Lock claims can be
arbitrarily fall down a call chain, after all.

Humans are simply very, very bad at noticing unplanned mutex
interactions.  This is why finding more tractable concurrency
primitives is a major theme in recent language designs.  Nobody know
what the overall best set of primitives is for defect reduction (and
"best" may not be singular or even well-defined), but pretty much
anything is better than mutex-and-mailbox.

> Does Go have any utilities to scan code and build the lock tree?

No.  Naked locks are available in Go but they're considered an
option of last resort and used seldom.

> How do you avoid analogous deadlocks with channels?

By being careful. :-)

There's no way to automate your way out of this, and that is the major
known problem with CSP (communicating sequential processes) as a
concurrency-primitive set - indeed, early notice of this problem is
the reason there was very little experimentation with CSP between
occam (1983) and Go (2009).

Go is actually something of a surprise; according to the conventional
wisdom in this area CSP should not have been as successful as the Go
implementation in Go has turned out to be.  That is, deadlocks *should*
be a bigger problem in the real world than they are.

I don't know why this is.  The Go designers did something subtle that
I don't understand, and nobody else seems to either.  I have
researched this because I find it puzzling and interesting, and not
found any plausible theory.

Other primitive sets have different problems. In general, the more
different things you can do with a concurrency-primitive set, the more
it challenges human cognitive limitations and blows up defect rates.

So in the history of language design you see a lot of attempts to
invent more limited and tractable primitives - Ada rendezvous, for
example, or generators in Icon - followed by dissatisfaction when they
turn out not to be enough of an improvement over mutex-and-mailbox to
sweep the field.

Since the collapse of Dennard scaling the pace of invention in this
area has increased.  Which is why Rust has library support for several
different primitive sets.  Don't try mixing them if you value your
sanity.

> What is the cost of a lock vs a channel pass?  Given that the channel needs to 
> schedule another thread, I'll guess that costs significantly more.

You're right, it does.

There are occasional complaints about this - here's a representative one.

https://dparrish.com/2016/03/go-channels-slow-for-bulk-data

On the other hand, there isn't enough visible bitching about channel overhead to
suggest that it's a pervasive problem.  I found a good dive into benchmarking
here

https://syslog.ravelin.com/so-just-how-fast-are-channels-anyway-4c156a407e45

that may explain why.  Part of his takeaway is

* When it makes sense to use channels don’t worry overmuch about their
  performance: they’re pretty good! Normally the work you will do per
  item will greatly exceed the 90–250 ns it takes to move the item
  through the channel, so it’s just not worth worrying about.

> The lock I'm actually interested in is the one that protects the data that the 
> server thread needs to fill in the packet.  We need that even if we aren't 
> messing with the no-GC flag.
> 
> There is another problem with your proposal.  You skipped step 3.5, do the 
> authentication.  We need several CPUs working on that step in order to keep up 
> with a gigabit link.

Interesting.  OK, then the critical-region goroutine needs to manage
some subthreads of its own.
-- 
		<a href="http://www.catb.org/~esr/">Eric S. Raymond</a>




More information about the devel mailing list