[HN Gopher] Ruby "Thread Contention" Is Simply GVL Queuing
       ___________________________________________________________________
        
       Ruby "Thread Contention" Is Simply GVL Queuing
        
       Author : ciconia
       Score  : 80 points
       Date   : 2025-02-03 08:43 UTC (14 hours ago)
        
 (HTM) web link (island94.org)
 (TXT) w3m dump (island94.org)
        
       | taf2 wrote:
       | If i'm reading this correctly for web applications setting
       | RUBY_THREAD_DEFAULT_QUANTUM_MS=10 or maybe even
       | RUBY_THREAD_DEFAULT_QUANTUM_MS=1 could be more optimal then the
       | current default of 100, allowing for more throughput at the cost
       | of potentially slower single shot response times?
        
         | masklinn wrote:
         | IIRC it's complicated because it can depend on the relative run
         | times, and how fast the IO OPs are. By lowering the quantum
         | you're increasing the switching overhead (because there's more
         | handoffs), but it might allow the io thread to complete much
         | sooner and stop contending with the cpu thread.
         | 
         | Python's "new gil" (it's some 15 years old...) uses a similar
         | scheme, with a much lower timeout (5ms? 10?), but it still
         | suffers from this sort of contentions, and things get worse as
         | the number of CPU threads increase because they can hand the
         | gil off to one another bypassing the io thread.
        
         | jewel wrote:
         | I think you have that backwards; it should decrease latency and
         | decrease throughput.
         | 
         | I don't imagine the overhead will be too bad though, so it may
         | decrease latency while keeping throughput essentially the same.
         | 
         | Of course you'll want to benchmark on your specific load. For
         | example, at my day job it'd make no difference because we don't
         | use threads, each Passenger worker has just one thread and
         | handles one request at a time.
        
         | codesnik wrote:
         | I actually had a less than pleasant surprise when debugging
         | sidekiq process with a higher than usual threads count, and
         | noticing 100ms-multiples in my traces. 100ms before switch
         | indeed seems to be too high for an app with a potential to
         | misbehave.
        
       | Alifatisk wrote:
       | I've started to use Ruby for mathematical and scientific
       | computing using IRuby. I am not in need for high performance
       | computing yet so Ruby is still sufficient. Oh boy what a joy it
       | is to use.
        
         | Toutouxc wrote:
         | How I wish Ruby had been adopted as the glue-lingua franca
         | instead of Python. I get zero joy from writing Python.
        
           | te_chris wrote:
           | Agree 100%.
           | 
           | I've made peace with python, accepted that I need to use it,
           | but I hate it. Death to for loops.
        
             | kstrauser wrote:
             | Really? That's one of the things I like about Python: how
             | its for loops consistently consume an iterator, and that's
             | it. Anything that looks like an iterator can be looped
             | across or used in a comprehension without special casing.
        
               | ahartmetz wrote:
               | I remember some Ruby tutorial that proudly showcased a
               | 5.times begin loop_body end loop. Too cutesy IMO.
        
           | pjmlp wrote:
           | Python was on the right spot as Tcl/Perl successor, Ruby only
           | became known thanks to Rails and arrived too late for that.
           | 
           | Already in early 2000's CERN was scripting their builds,
           | Fortran and C++ tooling with Python.
           | 
           | Their Grid Computing tutorials, predating what we now call
           | Cloud, already used Python.
        
             | masklinn wrote:
             | Yeah like many things Python's overnight success was the
             | result of a decade of work. Python started involving
             | scientists (and creating science-oriented SIGs) in the mid
             | 90s. Numpy's original ancestor was Numeric, first released
             | in 1995.
        
           | agos wrote:
           | I've probably not tried hard enough, but I always got zero
           | joy from writing Ruby. Way too much magic.
        
             | graypegg wrote:
             | Totally valid point, but I do think magic is more a
             | property of the clever (usually reflection-based magic)
             | things people make with Ruby, less so the language. The
             | draw towards magic is actually because of the logically-
             | consistent object model Ruby is built around that I find to
             | be less magical and edge-case-filled than other script-y
             | languages.
             | 
             | If you just use it as a glue language to call out to other
             | things, prepare data, and iterate over results: it's pretty
             | clear and concise.
             | 
             | (I do personally like the reflection-magic in a lot of Ruby
             | apps, so I might be overlooking something that feels normal
             | to me, but is some very weird behaviour to anyone else!)
        
             | dismalaf wrote:
             | Too much magic? Ruby is super straightforward and
             | consistent.
             | 
             | Unless you're talking Rails, which indeed uses a lot of
             | metaprogramming under the hood and is quite different than
             | programming in basic Ruby.
        
             | IshKebab wrote:
             | I agree. And it's impossible to follow. No type hints,
             | missing syntax, generated identifiers all over the place,
             | etc. Awful awful language. I'd rather write Perl.
        
               | Toutouxc wrote:
               | > missing syntax, generated identifiers
               | 
               | I've been writing Ruby for almost ten years now, and I
               | honestly have no idea what these refer to.
        
               | IshKebab wrote:
               | 1. It leaves out parentheses in places where they really
               | should be there for clarity. Ok it's not nearly as bad as
               | e.g. OCaml, but it's still a downside.
               | 
               | 2. Basically Ruby code seems to favour magically
               | generating methods and variables based on other strings,
               | which makes them impossible to search for.
               | 
               | Other languages sometimes do that too, e.g. ill-advised
               | __dict__ Python tricks, or with macros in C++ or Rust.
               | But it's definitely worse in Ruby, and it's a common
               | complaint (search for "magic" in these comments).
               | 
               | I literally have given up following Gitlab's code before.
               | That never happens in better languages, e.g. I can easily
               | follow VSCode's codebase (Typescript) or gitlab-runner
               | (Go).
        
             | alberth wrote:
             | > Way too much magic.
             | 
             | Are you referring to Ruby, or specifically Rails?
        
               | horsawlarway wrote:
               | At least for me - Rails solidified my distaste, but Ruby
               | gets tarnished by it.
               | 
               | It's like seeing a c++ codebase riddled with macros. Is
               | c++ directly responsible for the madness? Probably not,
               | but the tooling allowed it.
               | 
               | And Ruby takes a double whammy on this front because
               | Rails was really what drove the popularity. Hard to
               | describe the frustration of hitting a very large Rails
               | codebase and literally not even being able to find the
               | definition for a class because it's got a fairly generic
               | name and is getting auto-loaded in the bowels of the
               | codebase by someone who thought they were clever like 7
               | years ago.
               | 
               | It's like a special version of DLL hell. Or all the pains
               | of global window/self vars coming from script tags in JS,
               | but at least that gave some breadcrumbs, and the
               | ecosystem is generally moving away from it even if ESM is
               | still painful in a lot of ways.
               | 
               | Either way - I don't like hidden things. I'd much rather
               | see the sausage get made then try to save a couple lines
               | of typing, and the older I get, the more I judge
               | languages on the simple metric of "How well does text-
               | based search work for finding relevant code?". Rails
               | performs really badly on that metric.
        
               | Spivak wrote:
               | Ruby except with Python style imports where you had
               | better god damn explain in explicit detail where every
               | symbol in the file came from would pretty much be my
               | ideal. Python from blah import * is banned in pretty much
               | every codebase but in Ruby that, or worse autoloading, is
               | all you have.
        
             | craigmcnamara wrote:
             | It's only magic if you don't understand how it works.
        
             | chihuahua wrote:
             | Same. I've been using Ruby+Rails for the past year as my
             | company's entire back-end is Ruby. I found it to be ugly
             | and almost intentionally designed to be difficult to read.
             | The tools for Ruby (RubyMine, Ruby LSP for VSCode) are slow
             | and unreliable. It also seems that debugging Ruby works
             | sometimes, but not always, which is ridiculous. RubyMine
             | has its own wacky debugger support, which breaks whenever
             | there's a new Ruby release. VSCode tries to use rdbg, but
             | frequently stops working.
        
           | williamcotton wrote:
           | It's so great for writing DSLs. This magic might turn some
           | people off but the result of this meta-programming makes for
           | some very expressive and concise code.
        
           | kace91 wrote:
           | I keep hearing about the dev satisfaction with ruby, but I'm
           | starting to work with it and I haven't yet felt it at all - I
           | see many footgun design decisions like clashing classes not
           | being an error, and blocks feel like a more
           | cumbersome/limited version of lambdas/first class functions.
           | 
           | I'm not saying this to attack the language, just pointing my
           | current mental picture to ask: what's the magic everybody
           | loves? I know there is something there because it's an almost
           | unanimous view among ruby devs, so I want to get it.
        
             | GenericCanadian wrote:
             | As someone who's worked with Ruby for 12 years here are
             | some insights:
             | 
             | Ruby makes message passing first class. That just changes
             | how you think about programs. In exchange you give up
             | passing functions so our anonymous functions are our blocks
             | (actually just another object that can receive messages).
             | So you don't `list(something)` you `something.list` and
             | that lets you change what `.list` does depending on who
             | `something` is very easily.
             | 
             | Ruby's defining feature is that the line between language
             | author and program author is razer thin. You can completely
             | change the language yourself by extending core classes.
             | This is why we have `1.day` in Rails even though its not
             | supported in the main language. DHH (author of Rails) could
             | add that without consulting Matz (author of Ruby). So lots
             | of stuff gets prioritized to make developers happy because
             | its easy to add.
             | 
             | In Ruby the messages you receive are passed up the chain of
             | ancestors. Your ancestors are a linked list of classes
             | going back to a root class like `Object`. You can modify
             | this linked list at will with mixins and inheritance with
             | complete control (should I go before or after this other
             | receiver).
             | 
             | Ruby's REPL and debugging experience is amazing. I often
             | keep one tab with an `irb` or `rails console` open to
             | sketch things while developing the code for it elsewhere.
             | I'm also always inside a debugger to figure things out.
             | When I'm in Rust or Python I'm met with a very different
             | environment.
        
               | kace91 wrote:
               | I get the debugging experience, as I've already found it
               | pleasant and painless compared to the difficulty of
               | setting debugging environments in other languages. But
               | for the messages first approach and thinness, what's the
               | real world benefit in practice?
        
             | Toutouxc wrote:
             | > clashing classes not being an error
             | 
             | You're probably talking about the ability to reopen (or
             | "monkey patch") classes (which is why defining the same
             | class again can't be an error). That's a powerful tool if
             | you use it carefully, especially for debugging or hacking
             | on someone else's code.
             | 
             | > blocks feel like a more cumbersome/limited version of
             | lambdas
             | 
             | Yes, that's basically what they are. You could totally
             | write JS-like code and pass even multiple lambdas to
             | methods. However, the most common use case -- passing a
             | single important lambda (e.g. to a "map" or "each" method)
             | -- gets special treatment and its own language feature.
             | 
             | > what's the magic everybody loves
             | 
             | For me it's the "batteries included" factor. Ruby can do a
             | lot out of the box and most of the interfaces are well
             | designed with tons of useful methods with descriptive
             | names. It feels like someone cares about my experience and
             | is trying to anticipate what I might actually need.
             | 
             | Also the object oriented mechanisms are easy to understand
             | and don't feel weirdly bolted on like in Python.
        
               | strken wrote:
               | Reopening classes is a powerful tool, but it would be a
               | lot safer if the syntax was limited to class_eval and
               | didn't let you define the same class twice.
        
           | tombert wrote:
           | A small part of me is still holding out hope that Julia will
           | catch on. A guy can dream...
        
         | amw-zero wrote:
         | It's the most "enjoyable" language to write in my opinion. I
         | totally agree. I wish I got to use it more at work, now it's
         | all Go and Python.
        
           | chihuahua wrote:
           | After the past year where I worked for a company that uses
           | Ruby for its back-end:
           | 
           | In a hypothetical scenario where I'm in a room with Yukihiro
           | Matsumoto, Hitler, and Stalin, and I have a gun with only 2
           | bullets, I would shoot Matsumoto twice.
        
       | jeffbee wrote:
       | This is what thread contention means in any language and runtime.
       | Threads "contend" for mutexes by waiting.
        
         | electroly wrote:
         | Most mutexes aren't fair; it's not strictly equivalent to
         | queueing. That said, I agree with your larger point that I
         | don't understand what the author finds revelatory about this.
        
           | jeffbee wrote:
           | Maybe not but even spinlocks logically contend this way. For
           | example the Go and Abseil mutex libraries, which are similar,
           | account cycles spun toward contention statistics.
        
           | loeg wrote:
           | Fairness isn't really relevant to the analysis in the
           | article. I agree with jeffbee.
        
         | amw-zero wrote:
         | Yes, but I think it's a revelation to many people that things
         | like this map to queueing. Literally _everything_ related to
         | performance is queueing, but we use different words for
         | different scenarios, like "contention."
        
           | loeg wrote:
           | > Literally _everything_ related to performance is queueing
           | 
           | Well, _scaling_ is queuing. But other things: cache hit
           | rates, data packing efficiency, efficient use of hardware
           | intrinsics, etc, don't relate to queuing.
        
           | unification_fan wrote:
           | How is the concept of algorithmic complexity analogous to
           | queuing?
        
       | amw-zero wrote:
       | Loved this writeup, because queues are the most important and
       | general concept in reasoning about performance. When you realize
       | this, you start seeing them everywhere. Locks, async IO...
       | everything is just interacting queues.
        
       | loeg wrote:
       | Yes, all contention is just queueing on shared resources...
        
       | mrinterweb wrote:
       | Ben Sheldon, I really appreciate how you wrote this article. It
       | feels like it was written in a very direct way that is more
       | easily consumable for people who's attention tends to drift on
       | long-form articles. I feel like you covered a complex topic
       | succinctly, and I appreciate that. Helped me get a better
       | understanding of thread contention. Thanks.
        
       ___________________________________________________________________
       (page generated 2025-02-03 23:01 UTC)