From: Francis Cianfrocca Date: 2006-05-23T03:37:16+09:00 Subject: Re: sysread changes behavior in the presence of threads? As a very rough rule of thumb, when I design a thread-hot system, I generally try to make the contention ratio of every mutex no worse than 1:100. I try for 1:1000 if I can get it. Regardless of the weight of the mutex mechanism (Ruby's can hardly be worse than the one in multi-processor Windows builds), the cost of a missed mutex-acquisition ends up being about that high. People often complain to me that keeping lock-sets as small as possible works against the goal of making threads easier to use. Well, it doesn't because threads are hard to use, period. I've found that with careful analysis, it's *generally* possible to keep a lock set minimal, ideally no larger than one read and one write. Any more than that (incuding function calls), and you're often synchronizing more than you really need to. Java programmers (who suffer simultaneously from horrible thread-management in their language, and a culture of serious thread-overuse) love to tell you about their new "wait-free" programming model. Not a new idea, it just encourages you to make your lock-sets so minimal that they will fit within a machine operation that is guaranteed to run in one bus cycle. (Intel chips have half-a-dozen such operations.) Just proves my point all the more. On 5/22/06, Joel VanderWerf wrote: > Francis Cianfrocca wrote: > > We're threadjacking, so I'll keep it short. The point of taking a very > > I like this thread, but I'll nudge it in the ruby direction... > > > restrictive view of synchronization is to prevent incorrect concurrency. > > Your example depends on the implementation of aMap and of calculateValue > > not > > to do evil things. (One of the evil things they can do is simply to run for > > several milliseconds, or make a blocking I/O call. This can give you a bad > > case of mutex contention, which is exceptionally costly in many modern > > implementations.) This means that the program may change behavior with > > respect to concurrency across platforms, hardware, and also across time (as > > the code inside those called functions changes). Ruby adds the further > > dimension that the code you call under lock may have been metaprogrammed on > > the fly. > > If you're talking about ruby threads, sync mechanisms are expensive with > or without contention, since they are built on top of Thread.critical. > > require 'thread' > require 'benchmark' > > N = 1_000_000 > > Benchmark.bmbm(12) do |bm| > > bm.report("no Thread.critical") do > x = 0 > N.times do > x += 1 > end > end > > bm.report("Thread.critical") do > x = 0 > N.times do > Thread.critical = true > x += 1 > Thread.critical = false > end > end > > bm.report("Thread.exclusive") do > x = 0 > N.times do > Thread.exclusive do > x += 1 > end > end > end > > end > > __END__ > > Rehearsal ------------------------------------------------------ > no Thread.critical 1.040000 0.010000 1.050000 ( 1.063126) > Thread.critical 1.130000 0.000000 1.130000 ( 1.153935) > Thread.exclusive 2.660000 0.000000 2.660000 ( 2.704054) > --------------------------------------------- total: 4.840000sec > > user system total real > no Thread.critical 0.360000 0.000000 0.360000 ( 0.366529) > Thread.critical 0.910000 0.010000 0.920000 ( 0.922671) > Thread.exclusive 2.670000 0.000000 2.670000 ( 2.692268) > > > -- > vjoel : Joel VanderWerf : path berkeley edu : 510 665 3407 > >