From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on starla X-Spam-Level: X-Spam-Status: No, score=-1.1 required=3.0 tests=DKIM_SIGNED,DKIM_VALID, DKIM_VALID_AU,MAILING_LIST_MULTI,SPF_HELO_PASS,SPF_PASS autolearn=ham autolearn_force=no version=3.4.6 Received: from nue.mailmanlists.eu (nue.mailmanlists.eu [94.130.110.93]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by dcvr.yhbt.net (Postfix) with ESMTPS id C6E481F4C1 for ; Mon, 25 Nov 2024 02:03:06 +0000 (UTC) Authentication-Results: dcvr.yhbt.net; dkim=pass (1024-bit key; unprotected) header.d=ml.ruby-lang.org header.i=@ml.ruby-lang.org header.a=rsa-sha256 header.s=mail header.b=D0jdtmXE; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=ruby-lang.org header.i=@ruby-lang.org header.a=rsa-sha256 header.s=s1 header.b=TlNv6Fq0; dkim-atps=neutral DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ml.ruby-lang.org; s=mail; t=1732500154; bh=XvzQgkSEF0/G4axy1TdSlG+gKX7FL0J6WG4wYPk7xaU=; h=Date:References:To:Reply-To:Subject:List-Id:List-Archive: List-Help:List-Owner:List-Post:List-Subscribe:List-Unsubscribe: From:Cc:From; b=D0jdtmXEOqtK9BW21bBLCpXT81zbNNrKpjNGz5RGJXaqPfm/+v3s17HXcRIYH9tu8 cspiBEeBASnW3GXXemihFXnvyJnKN1F0181Z3tQcxnVtm3gx8wxjCRM4r4yffrVIan +iOVlPW5M5ab7xJEdtDMdLJ8e/a57YPEaicT8ArQ= Received: from nue.mailmanlists.eu (localhost [IPv6:::1]) by nue.mailmanlists.eu (Postfix) with ESMTP id 1DFF744BFB for ; Mon, 25 Nov 2024 02:02:34 +0000 (UTC) Authentication-Results: nue.mailmanlists.eu; dkim=pass (2048-bit key; unprotected) header.d=ruby-lang.org header.i=@ruby-lang.org header.a=rsa-sha256 header.s=s1 header.b=TlNv6Fq0; dkim-atps=neutral Received: from s.wrqvwxzv.outbound-mail.sendgrid.net (s.wrqvwxzv.outbound-mail.sendgrid.net [149.72.154.232]) by nue.mailmanlists.eu (Postfix) with ESMTPS id 5337844B11 for ; Mon, 25 Nov 2024 02:02:22 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ruby-lang.org; h=from:references:subject:mime-version:content-type: content-transfer-encoding:list-id:to:cc:content-type:from:subject:to; s=s1; bh=9NlRSvhVVqcfeMxS60rRDg+ozgHAtXz3/WPGbIepuIQ=; b=TlNv6Fq0mXJmu1XzTW3Rgu7r0DdgAOvsMj0MIzymcn3oKd7kXSj6EAFo+j5OYU9CpsQY oEfVAlYnMwI5n2Aj5WBcvQ0t/l4M/2eu3SbO1/IlXQN4xuQRcBIg0ZeISmslOEHu3hC6a+ X+sqR3JGwqvklD2RPmhqVkmX6/FEEZCl+OHOVwy/KKwMzgIPB8oEGUE/2X4ZsBrM+s4e0N v8brPy+mww5y1Jr6svxg8z26cujJ22YmKKVb44lSwOZVtpLJ4FuRfML/RICeR7mxeWpOZw +gRMTzPUYn+q/lI2WNQu/J37kBEXE1dyRRCAheSYV8QeSNWMur78dtBNuOiK/AGw== Received: by recvd-5f54b5d587-kg8m9 with SMTP id recvd-5f54b5d587-kg8m9-1-6743DAAC-6 2024-11-25 02:02:20.526532672 +0000 UTC m=+880710.824354391 Received: from herokuapp.com (unknown) by geopod-ismtpd-31 (SG) with ESMTP id xG5-5TnJS6mARsaPysA8Ew for ; Mon, 25 Nov 2024 02:02:20.441 +0000 (UTC) Date: Mon, 25 Nov 2024 02:02:20 +0000 (UTC) Message-ID: References: Mime-Version: 1.0 X-Redmine-Project: ruby-master X-Redmine-Issue-Tracker: Feature X-Redmine-Issue-Id: 20861 X-Redmine-Issue-Author: tenderlovemaking X-Redmine-Issue-Priority: Normal X-Redmine-Sender: Dan0042 X-Mailer: Redmine X-Redmine-Host: bugs.ruby-lang.org X-Redmine-Site: Ruby Issue Tracking System X-Auto-Response-Suppress: All Auto-Submitted: auto-generated X-Redmine-MailingListIntegration-Message-Ids: 96677 X-SG-EID: =?us-ascii?Q?u001=2EHy4LB1bizMxDg=2Fk6r7dYDS9qUDe3jZN8DIPm4OS+F86l7XdLFEAVX=2F2lh?= =?us-ascii?Q?z0Jj=2Ft7J6DgKnq5Qaf6Ba4+egck=2FoKuUHMa9Cn6?= =?us-ascii?Q?7D+EQ8vUJVtE2rrtA5rw3CHPgSyL84I1DHjfAXy?= =?us-ascii?Q?RS=2FOGgvOLt0QnNmKCT0XK9Cu5FoWUxO085pg=2FJr?= =?us-ascii?Q?QzEmW5rmFDrq6SgSJq8wwnUYVuem0wWtlZ0SJji?= =?us-ascii?Q?sJdTPWrA3cxMd64wLkUEIpBQ9Ul+wvMTUZbYWag?= =?us-ascii?Q?kXReUNfF+Yq+u7vRBo2dWSl1cg=3D=3D?= To: ruby-core@ml.ruby-lang.org X-Entity-ID: u001.I8uzylDtAfgbeCOeLBYDww== Message-ID-Hash: JHJDDANXPBGHAGVMLL7Q2AFGSV6CTUWU X-Message-ID-Hash: JHJDDANXPBGHAGVMLL7Q2AFGSV6CTUWU X-MailFrom: bounces+313651-b711-ruby-core=ml.ruby-lang.org@em5188.ruby-lang.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; emergency; loop; banned-address; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.9 Precedence: list Reply-To: Ruby developers Subject: [ruby-core:120000] [Ruby master Feature#20861] Add an environment variable for tuning the default thread quantum List-Id: Ruby developers Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "Dan0042 (Daniel DeLorme) via ruby-core" Cc: "Dan0042 (Daniel DeLorme)" Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Issue #20861 has been updated by Dan0042 (Daniel DeLorme). byroot (Jean Boussier) wrote in #note-6: > Yes, quite literally: `Thread.current.quantum = 20` or something like that. > > Which IMO is much easier to reason about than priorities. And generally you have threads that are meant as "main" threads and some that are meant as "background" and you'd want them to have different quantums, hence why I'd rather skip the environment variable and go straight to an accessor. > > But perhaps a `Thread.default_quantum = XX` would be needed too. What happened to this idea? According to the latest comments it seems we're back to the idea of an environment variable, but that means we - can't set the quantum after process start (let's say some performance monitoring periodically adjusts the value) - can't set the quantum per thread (but that seem to be fine according to #note-8) - can't set the quantum to a different value in a forked process As long as those limitations are not a problem, then an environment variable is fine. ---------------------------------------- Feature #20861: Add an environment variable for tuning the default thread quantum https://bugs.ruby-lang.org/issues/20861#change-110744 * Author: tenderlovemaking (Aaron Patterson) * Status: Open ---------------------------------------- The default thread quantum is currently [hard coded at 100ms](https://github.com/ruby/ruby/blob/c7708d22c33040a74ea7ac683bf7407d3759edfe/thread_pthread.c#L323). This can impact multithreaded systems that are trying to process Ruby level CPU bound work at the same time as IO work. I would like to add an environment variable `RUBY_THREAD_DEFAULT_QUANTUM_MS` that allows users to specify the default thread quantum (in milliseconds) via an environment variable. It defaults to our current default of 100ms. I've submitted the patch [here](https://github.com/ruby/ruby/pull/11981). Here is a Ruby program to demonstrate the problem: ```ruby def measure x = Process.clock_gettime(Process::CLOCK_MONOTONIC) yield Process.clock_gettime(Process::CLOCK_MONOTONIC) - x end def fib(n) if n < 2 n else fib(n-2) + fib(n-1) end end # find fib that takes ~500ms fib_i = 50.times.find { |i| measure { fib(i) } >= 0.05 } sleep_i = measure { fib(fib_i) } threads = [ Thread.new { 100.times { sleep(sleep_i) # sometimes stalled waiting for fib's quantum to finish } puts "done 1" }, Thread.new { 100.times { fib(fib_i) }; puts "done 2" }, ] # We expect the total time to be about 100 * sleep_i (~5 seconds) because # theoretically the sleep thread could be done nearly completely in parallel to # the fib thread. # # But because the `sleep` thread is iterating over the sleep call, it must wait # for the `fib` thread to complete its quantum, before it can start the next iteration. # # This means each sleep iteration could take up to `sleep_i + 100ms` # # We're calling that stalled time "waste" total = measure { threads.each(&:join) } waste = total - (sleep_i * 100) p TOTAL: total, WASTE: waste ``` The program has two threads. One thread is using CPU time by computing `fib` in a loop. The other thread is simulating IO time by calling `sleep` in a loop. When the `sleep` call completes, it can stall, waiting for the quantum in the fib thread to expire. That means that each iteration on sleep can actually take `sleep time + thread quantum`, or in this case ~600ms when we expected it to only take ~500ms. Ideally, the above program would take `500ms * 100` since all `sleep` calls should be able to execute in parallel with the `fib` calls. Of course this isn't true because the sleep thread must acquire the GVL before it can continue the next iteration, so there will always be _some_ overhead. This feature is for allowing people to tune that overhead. If we run this program with the default quantum the output looks like this: ``` $ ./miniruby -v fibtest.rb ruby 3.4.0dev (2024-11-01T14:49:50Z quantum-computing c7708d22c3) +PRISM [arm64-darwin24] done 2 done 1 {TOTAL: 12.672821999993175, WASTE: 4.960721996147186} ``` The output shows that our program spent about 5 seconds stalled, waiting to acquire the GVL. With this patch we can lower the default quantum, and the output is like this: ``` $ RUBY_THREAD_DEFAULT_QUANTUM_MS=10 ./miniruby -v fibtest.rb ruby 3.4.0dev (2024-11-01T22:06:35Z quantum-computing 087500643d) +PRISM [arm64-darwin24] done 2 done 1 {TOTAL: 8.898526000091806, WASTE: 1.4168260043952614} ``` Specifying the ENV to change the quantum to 10ms lowered our waste in the program to ~1.4 seconds. It's common for web applications to do mixed CPU and IO bound tasks in threads (see the Puma webserver), so it would be great if there was a way to customize the thread quantum depending on your application's workload. -- https://bugs.ruby-lang.org/ ______________________________________________ ruby-core mailing list -- ruby-core@ml.ruby-lang.org To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org ruby-core info -- https://ml.ruby-lang.org/mailman3/lists/ruby-core.ml.ruby-lang.org/