From patchwork Mon Nov 28 17:26:46 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Siddhesh Poyarekar X-Patchwork-Id: 1709900 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@legolas.ozlabs.org Authentication-Results: legolas.ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=sourceware.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org; receiver=) Authentication-Results: legolas.ozlabs.org; dkim=pass (1024-bit key; secure) header.d=sourceware.org header.i=@sourceware.org header.a=rsa-sha256 header.s=default header.b=HLalteiE; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (P-384) server-digest SHA384) (No client certificate requested) by legolas.ozlabs.org (Postfix) with ESMTPS id 4NLXTZ2fCHz23nB for ; Tue, 29 Nov 2022 04:27:14 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id DD2D0385515B for ; Mon, 28 Nov 2022 17:27:11 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org DD2D0385515B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=sourceware.org; s=default; t=1669656431; bh=eclsd3hO0VQVQ7rqkcWH77h//caas6ulr5eRAStJzCs=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To: From; b=HLalteiEdF2BnrB3iBdwHWDrx4EPFH23+TKg0sod5oAI6N/1WR4RH8B4yQIzvpAEA u0r0LLu8x+OPr4wFqzXNrbqaSJv920yszocF+ExIIyqyaxPSKtoMwWucB5+inIuRKn MYtcXq6tiRDHtJvqjB0UemJc5avGr4u7uBgtuQ1E= X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from black.elm.relay.mailchannels.net (black.elm.relay.mailchannels.net [23.83.212.19]) by sourceware.org (Postfix) with ESMTPS id 5293F3858C62 for ; Mon, 28 Nov 2022 17:26:53 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 5293F3858C62 X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org Received: from relay.mailchannels.net (localhost [127.0.0.1]) by relay.mailchannels.net (Postfix) with ESMTP id AE907101417 for ; Mon, 28 Nov 2022 17:26:51 +0000 (UTC) Received: from pdx1-sub0-mail-a304.dreamhost.com (unknown [127.0.0.6]) (Authenticated sender: dreamhost) by relay.mailchannels.net (Postfix) with ESMTPA id 43F20101100 for ; Mon, 28 Nov 2022 17:26:51 +0000 (UTC) ARC-Seal: i=1; s=arc-2022; d=mailchannels.net; t=1669656411; a=rsa-sha256; cv=none; b=ft24xVkm9EA692loVawkbq4eEj5+aOo0NDAg4X4sZFY6AQTplVzVXXKv7h6ghePdqloJEG tA0FuO9SlHd8jTUWhjn5IYH9oImYiaVmiaXowSDGClKrVxIurDmKbiIlWRgbf/9rcl8MCH SFvuquq8XXoWO/9LxNZPKlQjvXKzi6MYyY8pzITCx2kXyFq3dFwQw+mx+yFLwAu9inlpLi vK91HHkUYvmZfeEzFMFQTSIXPI5K1TacH+DZ+XXavaNijxlMJfnO3q+z0enVbgt3iOmD8x tc56YhVeh/6Eb35X86FjR7j/sA8cFkBmKs0KZrXWNkcG9O8/kssC+igKofUnow== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=mailchannels.net; s=arc-2022; t=1669656411; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=eclsd3hO0VQVQ7rqkcWH77h//caas6ulr5eRAStJzCs=; b=Mneiw8+tvAHmX+3hm2zrt3jly0BQaqEN7i68U2XayIwegOiPO25ZxrhrpvkXtRzxmyzNy4 YStd4OP5sjLphebsOdj7qF5sQ6SuE6YsgIH00doAor8e4fPNLkyhVFei1vRoiYGJdGULtW UmzRWVxjianBOTZAGOhxPVFsCHpqVdHEKGKSHq/Z/pCM/D3A62Bad/FwnJfOS1GPudCyM3 V7MZxRC4qz8lnCas/37hbau5yJ9ltPQXZk20NnZ2XDQ/WEYloDFewmYiOntnHcpBUAk66U C66XDCoKyf9klmd7zBv3hqlhld48JakgBycbJgy5OGBwpEACcINgi8fHBkZneg== ARC-Authentication-Results: i=1; rspamd-7bd68c5946-gzx78; auth=pass smtp.auth=dreamhost smtp.mailfrom=siddhesh@sourceware.org X-Sender-Id: dreamhost|x-authsender|siddhesh@gotplt.org X-MC-Relay: Neutral X-MailChannels-SenderId: dreamhost|x-authsender|siddhesh@gotplt.org X-MailChannels-Auth-Id: dreamhost X-Power-Tart: 5a1368fc536a91f2_1669656411513_1278659986 X-MC-Loop-Signature: 1669656411513:4121639117 X-MC-Ingress-Time: 1669656411513 Received: from pdx1-sub0-mail-a304.dreamhost.com (pop.dreamhost.com [64.90.62.162]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384) by 100.126.30.34 (trex/6.7.1); Mon, 28 Nov 2022 17:26:51 +0000 Received: from fedora.redhat.com (bras-base-toroon4834w-grc-23-76-68-24-147.dsl.bell.ca [76.68.24.147]) (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) (Authenticated sender: siddhesh@gotplt.org) by pdx1-sub0-mail-a304.dreamhost.com (Postfix) with ESMTPSA id 4NLXT64KKnz4C for ; Mon, 28 Nov 2022 09:26:50 -0800 (PST) To: libc-alpha@sourceware.org Subject: [PATCH v2] realloc: Return unchanged if request is within usable size Date: Mon, 28 Nov 2022 12:26:46 -0500 Message-Id: <20221128172646.244742-1-siddhesh@sourceware.org> X-Mailer: git-send-email 2.38.1 In-Reply-To: <20221125200948.2399996-1-siddhesh@sourceware.org> References: <20221125200948.2399996-1-siddhesh@sourceware.org> MIME-Version: 1.0 X-Spam-Status: No, score=-1172.2 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_NONE, KAM_DMARC_STATUS, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H2, SPF_HELO_NONE, SPF_SOFTFAIL, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Siddhesh Poyarekar via Libc-alpha From: Siddhesh Poyarekar Reply-To: Siddhesh Poyarekar Errors-To: libc-alpha-bounces+incoming=patchwork.ozlabs.org@sourceware.org Sender: "Libc-alpha" If there is enough space in the chunk to satisfy the new size, return the old pointer as is, thus avoiding any locks or reallocations. The only real place this has a benefit is in large chunks that tend to get satisfied with mmap, since there is a large enough spare size (up to a page) for it to matter. For allocations on heap, the extra size is typically barely a few bytes (up to 15) and it's unlikely that it would make much difference in performance. Also added a smoke test to ensure that the old pointer is returned unchanged if the new size to realloc is within usable size of the old pointer. Signed-off-by: Siddhesh Poyarekar Reviewed-by: DJ Delorie --- Changes from v1: - Fixed up test as per review comments - Do the realloc bypass only when the new size is within trim_threshold bytes of the usable size so that shrinking does not hold up memory. malloc/malloc.c | 10 ++++++++++ malloc/tst-realloc.c | 23 +++++++++++++++++++++++ 2 files changed, 33 insertions(+) diff --git a/malloc/malloc.c b/malloc/malloc.c index 2a61c8b5ee..ef8c794fb7 100644 --- a/malloc/malloc.c +++ b/malloc/malloc.c @@ -1100,6 +1100,8 @@ static void munmap_chunk(mchunkptr p); static mchunkptr mremap_chunk(mchunkptr p, size_t new_size); #endif +static size_t musable (void *mem); + /* ------------------ MMAP support ------------------ */ @@ -3396,6 +3398,14 @@ __libc_realloc (void *oldmem, size_t bytes) if (__glibc_unlikely (mtag_enabled)) *(volatile char*) oldmem; + /* Return the chunk as is whenever possible, i.e. there's enough usable space + but not so much that we end up fragmenting the block. We use the trim + threshold as the heuristic to decide the latter. */ + size_t usable = musable (oldmem); + if (bytes <= usable + && (unsigned long) (usable - bytes) <= mp_.trim_threshold) + return oldmem; + /* chunk corresponding to oldmem */ const mchunkptr oldp = mem2chunk (oldmem); /* its size */ diff --git a/malloc/tst-realloc.c b/malloc/tst-realloc.c index 5eb62a770f..3b78a2420a 100644 --- a/malloc/tst-realloc.c +++ b/malloc/tst-realloc.c @@ -17,6 +17,7 @@ #include #include +#include #include #include #include @@ -142,6 +143,28 @@ do_test (void) free (p); + /* Smoke test to make sure that allocations do not move if they have enough + space to expand in the chunk. */ + for (size_t sz = 3; sz < 256 * 1024; sz += 2048) + { + p = realloc (NULL, sz); + if (p == NULL) + FAIL_EXIT1 ("realloc (NULL, %zu) returned NULL.", sz); + size_t newsz = malloc_usable_size (p); + printf ("size: %zu, usable size: %zu, extra: %zu\n", + sz, newsz, newsz - sz); + uintptr_t oldp = (uintptr_t) p; + void *new_p = realloc (p, newsz); + if ((uintptr_t) new_p != oldp) + FAIL_EXIT1 ("Expanding (%zu bytes) to usable size (%zu) moved block", + sz, newsz); + free (new_p); + + /* We encountered a large enough extra size at least once. */ + if (newsz - sz > 1024) + break; + } + return 0; }