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 [IPv6:2a01:4f8:1c0c:6b10::1]) (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 5541A1F44D for ; Mon, 22 Apr 2024 16:02:46 +0000 (UTC) Authentication-Results: dcvr.yhbt.net; dkim=pass (1024-bit key; secure) header.d=ml.ruby-lang.org header.i=@ml.ruby-lang.org header.a=rsa-sha256 header.s=mail header.b=E2wpB+aI; 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=Gm4qMkAB; dkim-atps=neutral Received: from nue.mailmanlists.eu (localhost [127.0.0.1]) by nue.mailmanlists.eu (Postfix) with ESMTP id B41A0843DE; Mon, 22 Apr 2024 16:02:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=ml.ruby-lang.org; s=mail; t=1713801752; bh=X6NrOOz0qgK+sQBS7JtS9QHFhK2EgGfM6EyY+p+f98c=; 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=E2wpB+aIgV37mR3ZpyPh5zMfvgJLe3hkd4cdtdhVGcbbv+zbPBfpwSWw6/v1s6LMv ifPX2NFdQSjMMJoZlRMDleSFtBcLp84pWf4yEVeVKGON/gI5oCP2GG7jYcaEeABVN+ XxgNXpoEFaUFs9EQ0GrVIc9h7MylE1+Fp6388Fz8= Received: from s.wrqvtvvn.outbound-mail.sendgrid.net (s.wrqvtvvn.outbound-mail.sendgrid.net [149.72.120.130]) by nue.mailmanlists.eu (Postfix) with ESMTPS id 7F4C781479 for ; Mon, 22 Apr 2024 16:02:28 +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=Gm4qMkAB; dkim-atps=neutral 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=ffmN70iffBehhVUvrr5SZQM48i11JFJ4NFWYn/rFlck=; b=Gm4qMkABJH1qw/FsSLfhzqiUib/ZckQNjQxB+G2BTRLN2QGCFfgm54usJK+BLh/KVAY+ uaPR8iNIk4a4hg3ssfYd96L4+m/tbiP7XmkRGaMEtrbanUihZzmpGCtFH+LyVM54VGAi2x /eFKtX4o56TTTAWCMaKJOWWhzmPwGPGVgsv5RfhvPxrVoSIc8UhkUxcuR1sah4ku/uyP+n 4k6j+mcuBghuXQMHwlPkKiyZxNhzhF7ZLUiA8wQkQin81yTD+Lfo8fCaZvtDPGwCVb6svl q2vmYfyb8KkdKGkCznGd30fTA1QvX8xyXJSM44gZGtbKCyqXusaL1+wjjkdFj7Pg== Received: by filterdrecv-5744f46764-5dm7p with SMTP id filterdrecv-5744f46764-5dm7p-1-66268A13-1B 2024-04-22 16:02:27.450995544 +0000 UTC m=+843272.601608545 Received: from herokuapp.com (unknown) by geopod-ismtpd-25 (SG) with ESMTP id 7-ZpvGEtTOmsb6zZ2QgkZg for ; Mon, 22 Apr 2024 16:02:27.397 +0000 (UTC) Date: Mon, 22 Apr 2024 16:02:27 +0000 (UTC) Message-ID: References: Mime-Version: 1.0 X-Redmine-Project: ruby-master X-Redmine-Issue-Tracker: Feature X-Redmine-Issue-Id: 20443 X-Redmine-Issue-Author: eightbitraptor X-Redmine-Issue-Priority: Normal X-Redmine-Sender: eightbitraptor 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: 94240 X-SG-EID: =?us-ascii?Q?u001=2E9VAa+KF84+ACjWkSb8mcy8gS+fYyyXFRcDVQpXgr7nDVEZYc6+Pq9ajFu?= =?us-ascii?Q?WmefySeLz3zn3rchgcytbyt4srfHH8FuYLgsYRD?= =?us-ascii?Q?3WTVvJnqa+pjLp+YiWWS7sJrBg1gctiz9SZERVP?= =?us-ascii?Q?SpGcc3O3RlI+OJ24q0EAo8mmcKWEbGiKOs223v6?= =?us-ascii?Q?+lM4UC4fMdva1T+pboSmbr6K1P2jMBtb95C3oJf?= =?us-ascii?Q?RC01DEIHt=2FwsKpAmrL=2FYOvPKp0gsaaTqMnKhYqD?= =?us-ascii?Q?Ee1ev9Nfq+T4Ny1f4YDaaCrF0FfEV8R5K3FnFZA?= =?us-ascii?Q?VrfPaw3E=3D?= To: ruby-core@ml.ruby-lang.org X-Entity-ID: u001.I8uzylDtAfgbeCOeLBYDww== Message-ID-Hash: 5NSKOSU3D724WUIOXUXOP4PSZWRHNITM X-Message-ID-Hash: 5NSKOSU3D724WUIOXUXOP4PSZWRHNITM 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.3 Precedence: list Reply-To: Ruby developers Subject: [ruby-core:117644] [Ruby master Feature#20443] Allow Major GC's to be disabled List-Id: Ruby developers Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: "eightbitraptor (Matthew Valentine-House) via ruby-core" Cc: "eightbitraptor (Matthew Valentine-House)" Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Issue #20443 has been reported by eightbitraptor (Matthew Valentine-House). ---------------------------------------- Feature #20443: Allow Major GC's to be disabled https://bugs.ruby-lang.org/issues/20443 * Author: eightbitraptor (Matthew Valentine-House) * Status: Open ---------------------------------------- [[Github PR #10598]](https://github.com/ruby/ruby/pull/10598) ## Background Ruby's GC running during Rails requests can have negative impacts on currently running requests, causing applications to have high tail-latency. A technique to mitigate this high tail-latency is Out-of-band GC (OOBGC). This is basically where the application is run with GC disabled, and then GC is explicitly started after each request, or when no requests are in progress. This can reduce the tail latency, but also introduces problems of its own. Long GC pauses after each request reduce throughput. This is more pronounced on threading servers like Puma because all the threads have to finish processing user requests and be "paused" before OOBGC can be triggered. This throughput decrease happens for a couple of reasons: 1. There are few heuristics available for users to determine when GC should run, this means that in OOBGC scenarios, it's possible that major GC's are being run more than necessary. 2. The lack of any GC during a request means that lots of garbage objects have been created and not cleaned up, so the process is using more memory than it should - requiring major GC's run as part of OOBGC to do more work and therefore take more time. This ticket attempts to address these issues by: 1. Provide `GC.disable_major` and its antonym `GC.enable_major` to disable and enable only major GC 2. Provide `GC.needs_major?` as a basic heuristic allowing users to tell when Ruby should run a Major GC. These ideas were originally proposed by @ko1 and @byroot in [this rails issue](https://github.com/rails/rails/issues/50449) Disabling GC major's would still allow minor GC's to run during the request, avoiding the ballooning memory usage caused by not running GC at all, and reducing the time that a major takes when we do run it, because the nursery objects have been cleaned up during the request already so there is less work for a major GC to do. This can be used in combination with `GC.needs_major?` to selectively run an OOBGC only when necessary ## Implementation This PR adds 3 new methods to the `GC` module - `GC.disable_major` This prevents major GC's from running automatically. It does not restrict minors. When `objspace->rgengc.need_major_gc` is set and a GC is run, instead of running a major, new heap pages will be allocated and a minor run instead. `objspace->rgengc.need_major_gc` will remain set until a major is manually run. If a major is not manually run then the process will eventually run out of memory. When major GC's are disabled, object promotion is disabled. That is, no objects will increment their ages during a minor GC. This is to attempt to minimise heap growth during the period between major GC's, by restricting the number of old-gen objects that will remain unconsidered by the GC until the next major. When `GC.start` is run, then major GC's will be enabled, a GC triggered with the options passed to `GC.start`, and then `disable_major` will be set to the state it was in before `GC.start` was called. - `GC.enable_major` This simply unsets the bit preventing major GC's. This will revert the GC to normal generational behaviour. Everything behaves as default again. - `GC.needs_major?` This exposes the value of `objspace->rgengc.need_major_gc` to the user level API. This is already exposed in `GC.latest_gc_info[:need_major_by]` but I felt that a simpler interface would make this easier to use and result in more readable code. eg. ```ruby out_of_band do GC.start if GC.needs_major? end ``` Because object aging is disabled when majors are disabled it is recommended to use this in conjunction with `Process.warmup`, which will prepare the heap by running a major GC, compacting the heap, and promoting every remaining object to old-gen. This ensures that minor GC's are running over the smallets possible set of young objects when `GC.disable_major` is true. ## Benchmarks We ran some tests in production on Shopify's core monolith over a weekend and found that: **Mean time spent in GC, as well as p99.9 and p99.99 GC times are all improved.** Screenshot 2024-04-22 at 16 41 49 **p99 GC time is slightly higher.** Screenshot 2024-04-22 at 16 44 55 We're running far fewer OOBGC major GC's now that we have `GC.needs_major?` than we were before, and we believe that this is contributing to a slightly increased number of minor GC's. raising the p99 slightly. **App response times are all improved** We see a 9% reduction in average and p99 response times when compared against standard GC (4% p99.9 and p99.99). Screenshot 2024-04-22 at 16 55 53 This drops slightly to an 8% reduction in average and p99 response times when compared against standard OOBGC (3.59 p99.9 and 4% p99.99) Screenshot 2024-04-22 at 16 56 10 -- 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/postorius/lists/ruby-core.ml.ruby-lang.org/