From: Bob Hutchison Date: 2006-09-05T21:45:30+09:00 Subject: Re: The real difference between Mutex and Sync On Sep 5, 2006, at 4:25 AM, khaines@enigo.com wrote: > On Tue, 5 Sep 2006, Kent Sibilev wrote: > >> This patch will make Mutex a bit slower, but much better in terms of >> garbage collection: >> >> Index: lib/thread.rb >> =================================================================== >> RCS file: /src/ruby/lib/thread.rb,v >> retrieving revision 1.16.2.2 >> diff -r1.16.2.2 thread.rb >> 99c99 >> < @waiting.push Thread.current >> --- >>> @waiting.unshift Thread.current >> 115c115 >> < t = @waiting.shift >> --- >>> t = @waiting.pop > > While I am not benchmarking with performance in mind, that change > doesn't seem to have any significant effect on overall speed, which > doesn't surprise me. Speed-wise, it is just flipping the location > of the expensive array operation from the unlock to the lock. > > And yes, that simple change does seem to make a significant > difference, because pop will realloc the array. I've attached a trivial script that demonstrates on OS X and likely linux (unlikely windows because of the ps stuff) the problem. To see the bug, run it like: ruby blowup2.rb A *simple* fix is to just remove the reference to whatever is pointed to by the first element. To see this work, run the script as: ruby blowup2.rb fix This trick will probably lead to a quicker fix (and if you are daring you might actually patch the C implementation of shift to do it for you). Might want to hear what Matz has to say about that. Cheers, Bob ---- Bob Hutchison -- blogs at Recursive Design Inc. -- Raconteur -- xampl for Ruby -- $VERBOSE = nil STDOUT.sync = true trap('INT'){ exit } fixit = 0 < ARGV.size m = 1000000 n = 1000 all_arrays = [] first = true n.times do |i| if 0 < m then a = ["x" * m ] all_arrays << a a[0] = nil if fixit and 0 < a.size a.shift else a = [] all_arrays << a end if 0 == (all_arrays.size % 10) then GC.start stdout = `ps v -p #{ Process.pid }` stdout = stdout.split(%r/\n/) if first then printf("\n %s\n", stdout.first) first = false end printf("%6d:: %s\n", all_arrays.size, stdout.last) end end