From patchwork Wed Nov 20 15:03:14 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jan Hubicka X-Patchwork-Id: 1198224 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-514168-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=ucw.cz Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="J5zujIo3"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 47J5YL3XMSz9sPj for ; Thu, 21 Nov 2019 02:03:33 +1100 (AEDT) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; q=dns; s= default; b=NnHgsIGZW4Jr7d0Z2ycm7k/pZsVHVynv5m3Hcf3EK+Bi3Uj4BVvjF caSdPHoS+vyilNrCXwm8rAw6g0yAjyPaAaSWhXk52JFLnObjLdlWqz3mpKE7Md6n ll6QK+Knc0bA2fOu3V9OqrXFgXABMZUB0PSRzZDIOoWUO8wh00EX6U= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:date :from:to:subject:message-id:mime-version:content-type; s= default; bh=c3ABwfY6w0Hcr55eQs820ES9k1Q=; b=J5zujIo36v4Ycjd4y9FS kjOSwWYxMJ7yrSlKElWUaSaRzD9ARc1PQX8xYD5g0HahxIZqQqJEeBOBeP4sg6q/ 9DLA0+EU1+TtANq0jNAOHkrohtZW5UMDjItQSLT/jZdE53D6XOBqqn/fxF/fime0 uOWuroBdWqs+T/CkcZ1CaHA= Received: (qmail 106100 invoked by alias); 20 Nov 2019 15:03:20 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 106083 invoked by uid 89); 20 Nov 2019 15:03:20 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-10.0 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS autolearn=ham version=3.3.1 spammy=Reduce, sk:reduce_ X-HELO: nikam.ms.mff.cuni.cz Received: from nikam.ms.mff.cuni.cz (HELO nikam.ms.mff.cuni.cz) (195.113.20.16) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 20 Nov 2019 15:03:16 +0000 Received: by nikam.ms.mff.cuni.cz (Postfix, from userid 16202) id 7945A287F86; Wed, 20 Nov 2019 16:03:14 +0100 (CET) Date: Wed, 20 Nov 2019 16:03:14 +0100 From: Jan Hubicka To: gcc-patches@gcc.gnu.org, rguenther@suse.de Subject: Free memory_block pool Message-ID: <20191120150314.yqcngkw6adhipvkc@kam.mff.cuni.cz> MIME-Version: 1.0 Content-Disposition: inline User-Agent: NeoMutt/20170113 (1.7.2) Hi, I have noticed that for Firefox around 1GB of peak memory use goes into the fact that we never free memory_block_pool::freelist. This patch adds memory_block_pool::trim which reduces freelist to a given size. It is called from ggc_collect which is a convenient place to return heap allocations too and fully freeed prior forking in ggc_collect. I originaly was freeing block directly in memory_block_pool::release but that makes it non-leaf function which prevents optimization. So I decided to go this way we get tiny bit better code given that we already have ggc_collect that is conveninet place to do such a bookeeping. Bootstrapped/regtested x86_64-linux, tested on Firefox build, OK? Honza * memory-block.h (memory_block_pool::freelist): New constant. (memory_block_pool::clear_free_list): Rename to ... (memory_block_pool::reduce_free_list): ... this. (memory_block_pool::trim): New function. (memory_block_pool::block_list): Add m_prev. (memory_block_pool::m_num_blocks): New field. (memory_block_pool::m_block_end): New field. (memory_block_pool::allocate): Maintain m_num_blocks and m_blocks_end. (memory_block_pool::release): Likewise. * memory-block.cc (memory_block_pool::memory_block_pool): Initialize new fields. (memory_block_pool::clear_free_list): Rename to ... (memory_block_pool::reduce_free_list): ... this one; free from end and add NUM parameter. (memory_block_pool::trim): New. * ggc-page.c (ggc_collect): Call memory_block_pool::trim. * lto.c: Call memory_block_pool::trim. Index: memory-block.h =================================================================== --- memory-block.h (revision 278464) +++ memory-block.h (working copy) @@ -28,12 +28,15 @@ class memory_block_pool public: /* Blocks have fixed size. This is necessary for sharing. */ static const size_t block_size = 64 * 1024; + /* Number of blocks we keep in the freelists. */ + static const size_t freelist_size = 1024 * 1024 / block_size; memory_block_pool (); static inline void *allocate () ATTRIBUTE_MALLOC; static inline void release (void *); - void clear_free_list (); + static void trim (int nblocks = freelist_size); + void reduce_free_list (int); private: /* memory_block_pool singleton instance, defined in memory-block.cc. */ @@ -42,10 +45,13 @@ private: struct block_list { block_list *m_next; + block_list *m_prev; }; /* Free list. */ block_list *m_blocks; + block_list *m_blocks_end; + int m_num_blocks; }; /* Allocate a single block. Reuse a previously returned block, if possible. */ @@ -57,6 +63,9 @@ memory_block_pool::allocate () void *result = instance.m_blocks; instance.m_blocks = instance.m_blocks->m_next; + instance.m_num_blocks--; + if (!instance.m_blocks) + instance.m_blocks_end = NULL; VALGRIND_DISCARD (VALGRIND_MAKE_MEM_UNDEFINED (result, block_size)); return result; } @@ -67,7 +76,12 @@ memory_block_pool::release (void *uncast { block_list *block = new (uncast_block) block_list; block->m_next = instance.m_blocks; + if (instance.m_blocks) + instance.m_blocks->m_prev = block; + else + instance.m_blocks_end = block; instance.m_blocks = block; + instance.m_num_blocks++; VALGRIND_DISCARD (VALGRIND_MAKE_MEM_NOACCESS ((char *)uncast_block + sizeof (block_list), Index: memory-block.cc =================================================================== --- memory-block.cc (revision 278464) +++ memory-block.cc (working copy) @@ -26,18 +27,27 @@ along with GCC; see the file COPYING3. /* Global singleton-like instance. */ memory_block_pool memory_block_pool::instance; -memory_block_pool::memory_block_pool () : m_blocks (NULL) {} +/* Default constructor. */ +memory_block_pool::memory_block_pool () + : m_blocks (NULL), m_blocks_end (NULL), m_num_blocks (0) +{ +} -/* Return all blocks from free list to the OS. */ +/* Reduce free list to NUM blocks. */ void -memory_block_pool::clear_free_list () +memory_block_pool::reduce_free_list (int num) { - while (m_blocks) + gcc_checking_assert (num >= 0); + while (m_num_blocks > num) { - block_list *next = m_blocks->m_next; - XDELETEVEC (m_blocks); - m_blocks = next; + block_list *prev = m_blocks_end->m_prev; + XDELETEVEC (m_blocks_end); + m_blocks_end = prev; + prev->m_next = NULL; + m_num_blocks--; } + if (!m_num_blocks) + m_blocks = m_blocks_end = 0; } /* Allocate a chunk for obstack. Use the pool if requested chunk size matches @@ -62,3 +72,10 @@ mempool_obstack_chunk_free (void *chunk) else XDELETEVEC (chunk); } + +/* Return allocated memory back to malloc (and to system). */ +void +memory_block_pool::trim (int num) +{ + instance.reduce_free_list (num); +} Index: ggc-page.c =================================================================== --- ggc-page.c (revision 278464) +++ ggc-page.c (working copy) @@ -2186,6 +2186,9 @@ ggc_collect (void) float allocated_last_gc = MAX (G.allocated_last_gc, (size_t)param_ggc_min_heapsize * 1024); + /* It is a also good time to get memory block pool into limits. */ + memory_block_pool::trim (); + float min_expand = allocated_last_gc * param_ggc_min_expand / 100; if (G.allocated < allocated_last_gc + min_expand && !ggc_force_collect) return; Index: lto/lto.c =================================================================== --- lto/lto.c (revision 278464) +++ lto/lto.c (working copy) @@ -387,6 +387,7 @@ lto_wpa_write_files (void) temp_priority.safe_push (part->insns); temp_filenames.safe_push (xstrdup (temp_filename)); } + memory_block_pool::trim (0); for (int set = 0; set < MAX (lto_parallelism, 1); set++) {