From patchwork Tue Aug 29 06:33:10 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pranith Kumar X-Patchwork-Id: 9926795 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id B06786022E for ; Tue, 29 Aug 2017 06:34:50 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 9CDBA28879 for ; Tue, 29 Aug 2017 06:34:50 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 914C728887; Tue, 29 Aug 2017 06:34:50 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00, DKIM_ADSP_CUSTOM_MED, DKIM_SIGNED, FREEMAIL_FROM, RCVD_IN_DNSWL_HI, T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id DAD0B28885 for ; Tue, 29 Aug 2017 06:34:49 +0000 (UTC) Received: from localhost ([::1]:43061 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dma6r-0000ax-3p for patchwork-qemu-devel@patchwork.kernel.org; Tue, 29 Aug 2017 02:34:49 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38837) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dma5Q-0000Oz-If for qemu-devel@nongnu.org; Tue, 29 Aug 2017 02:33:21 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dma5N-00041p-Fz for qemu-devel@nongnu.org; Tue, 29 Aug 2017 02:33:20 -0400 Received: from mail-yw0-x244.google.com ([2607:f8b0:4002:c05::244]:38508) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dma5N-00041Y-Ao for qemu-devel@nongnu.org; Tue, 29 Aug 2017 02:33:17 -0400 Received: by mail-yw0-x244.google.com with SMTP id e9so1482690ywh.5 for ; Mon, 28 Aug 2017 23:33:17 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=Xhv6YyNkd0YzJVXcGfx1b7s2fegYGj+fKIXfaU96ZM8=; b=rHjHIc4/qKjZSeIC35dC59JtFTNJH5D3veVpG4OO1UB6ao/tOBBM5lK2mtWGGz7XBN wNuRFfAtBhwXLyAAdMFyaFmJkECkx1e2JIrtRywHKN7qRnQvtFapa4PlHCL6t2xdrxV3 hGC/iUPtJJtsp9xvYa8cbIy50SYHA2uOeS3+rLvg8H/xG8h1VQ75OUJkC3tALrsrpwBz TPbkWF6euuUsuHatfcHL9k77qSpsNzFY55/UTLivDbmB9/c0RHWlZI4oze+0dqGowQAR Rfc4greUoY5wob8hIaqwhGZmMwMtS2ZrrvSQPnX59+ig0NDtF+CAqhIAO9PfBcY4CLCZ YS0A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Xhv6YyNkd0YzJVXcGfx1b7s2fegYGj+fKIXfaU96ZM8=; b=Az1iHxqvy1HSl4GHubC5gz0RWeUTX8xvFWQjVCuq3NKNTjjs0WSwdKVYLhItTl8qPn 1XvI3LedPJUsSzBEZ0M9X6yUJU+vSWqKO7usE3BwtsimVLDxLAGqwKPr8AZSdIGkpiTz 0D2H7vuH4I3nwKCxQnjhDWAxl02WwreCEu0sNonWj2t5uf0e8ftPVNZN5dVspOCFyNJu uXzjx0MgoA910/jHHx10kW+JRBEePnqBwvuST8rkHAemg7Kgv4OlsfQdxqF3Mo0PhYYT VPkHlVGjJARLY5Fp0TPRWsvz12fmSlB9OP0MZGSuFdU7ivyrruQSA6zmwe347CFoeB4Z 1qkw== X-Gm-Message-State: AHYfb5h7sz2Vj596PkAOH34ZEsVxJ2FHeZ873oBQGoM+gFb8AZRHrq5R FlSJLkG2cT+RQw== X-Received: by 10.129.77.194 with SMTP id a185mr2736319ywb.310.1503988396692; Mon, 28 Aug 2017 23:33:16 -0700 (PDT) Received: from localhost.localdomain ([98.192.46.210]) by smtp.gmail.com with ESMTPSA id x4sm817923ywa.44.2017.08.28.23.33.15 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 28 Aug 2017 23:33:15 -0700 (PDT) From: Pranith Kumar To: alex.bennee@linaro.org, Paolo Bonzini , Richard Henderson , Sergey Fedorov , qemu-devel@nongnu.org (open list:All patches CC here) Date: Tue, 29 Aug 2017 02:33:10 -0400 Message-Id: <20170829063313.10237-2-bobby.prani@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170829063313.10237-1-bobby.prani@gmail.com> References: <20170829063313.10237-1-bobby.prani@gmail.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2607:f8b0:4002:c05::244 Subject: [Qemu-devel] [RFC v3 PATCH 2/5] cpus-common: Cache allocated work items X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: qemu-devel@nongnu.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP Using heaptrack, I found that quite a few of our temporary allocations are coming from allocating work items. Instead of doing this continously, we can cache the allocated items and reuse them instead of freeing them. Stats from an ARM64 guest (boot+shutdown): heaptrack stats(before): allocations: 1471317 leaked allocations: 73824 temporary allocations: 651293 heaptrack stats(after): allocations: 1143130 leaked allocations: 73693 temporary allocations: 487342 The improvement in speedup is minor and within error margins, however I think the patch is still worth. We can also explore atomics instead of taking a lock for the work item pool. Signed-off-by: Pranith Kumar --- cpus-common.c | 75 +++++++++++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 60 insertions(+), 15 deletions(-) diff --git a/cpus-common.c b/cpus-common.c index 59f751ecf9..ccf5f50e4e 100644 --- a/cpus-common.c +++ b/cpus-common.c @@ -24,6 +24,7 @@ #include "sysemu/cpus.h" static QemuMutex qemu_cpu_list_lock; +static QemuMutex qemu_wi_pool_lock; static QemuCond exclusive_cond; static QemuCond exclusive_resume; static QemuCond qemu_work_cond; @@ -33,6 +34,49 @@ static QemuCond qemu_work_cond; */ static int pending_cpus; +typedef struct qemu_work_item { + struct qemu_work_item *next; + run_on_cpu_func func; + run_on_cpu_data data; + bool free, exclusive, done; +} qemu_work_item; + +typedef struct qemu_wi_pool { + qemu_work_item *head; + int num_items; +} qemu_wi_pool; + +qemu_wi_pool *wi_free_pool; + +static void qemu_init_workitem_pool(void) +{ + wi_free_pool = g_malloc0(sizeof(qemu_wi_pool)); +} + +static void qemu_wi_pool_insert(qemu_work_item *item) +{ + qemu_mutex_lock(&qemu_wi_pool_lock); + qemu_work_item *curr = atomic_read(&wi_free_pool->head); + item->next = curr; + wi_free_pool->head = item; + qemu_mutex_unlock(&qemu_wi_pool_lock); +} + +static qemu_work_item *qemu_wi_pool_remove(void) +{ + qemu_mutex_lock(&qemu_wi_pool_lock); + qemu_work_item *curr = atomic_read(&wi_free_pool->head); + if (curr == NULL) { + goto out; + } + wi_free_pool->head = curr->next; + curr->next = NULL; + + out: + qemu_mutex_unlock(&qemu_wi_pool_lock); + return curr; +} + void qemu_init_cpu_list(void) { /* This is needed because qemu_init_cpu_list is also called by the @@ -43,6 +87,9 @@ void qemu_init_cpu_list(void) qemu_cond_init(&exclusive_cond); qemu_cond_init(&exclusive_resume); qemu_cond_init(&qemu_work_cond); + + qemu_init_workitem_pool(); + qemu_mutex_init(&qemu_wi_pool_lock); } void cpu_list_lock(void) @@ -106,14 +153,7 @@ void cpu_list_remove(CPUState *cpu) qemu_mutex_unlock(&qemu_cpu_list_lock); } -struct qemu_work_item { - struct qemu_work_item *next; - run_on_cpu_func func; - run_on_cpu_data data; - bool free, exclusive, done; -}; - -static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) +static void queue_work_on_cpu(CPUState *cpu, qemu_work_item *wi) { qemu_mutex_lock(&cpu->work_mutex); if (cpu->queued_work_first == NULL) { @@ -132,7 +172,7 @@ static void queue_work_on_cpu(CPUState *cpu, struct qemu_work_item *wi) void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data, QemuMutex *mutex) { - struct qemu_work_item wi; + qemu_work_item wi; if (qemu_cpu_is_self(cpu)) { func(cpu, data); @@ -156,9 +196,11 @@ void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data, void async_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data) { - struct qemu_work_item *wi; + qemu_work_item *wi = qemu_wi_pool_remove(); - wi = g_malloc0(sizeof(struct qemu_work_item)); + if (!wi) { + wi = g_malloc0(sizeof(qemu_work_item)); + } wi->func = func; wi->data = data; wi->free = true; @@ -299,9 +341,11 @@ void cpu_exec_end(CPUState *cpu) void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data) { - struct qemu_work_item *wi; + qemu_work_item *wi = qemu_wi_pool_remove(); - wi = g_malloc0(sizeof(struct qemu_work_item)); + if (!wi) { + wi = g_malloc0(sizeof(qemu_work_item)); + } wi->func = func; wi->data = data; wi->free = true; @@ -312,7 +356,7 @@ void async_safe_run_on_cpu(CPUState *cpu, run_on_cpu_func func, void process_queued_cpu_work(CPUState *cpu) { - struct qemu_work_item *wi; + qemu_work_item *wi; if (cpu->queued_work_first == NULL) { return; @@ -343,7 +387,8 @@ void process_queued_cpu_work(CPUState *cpu) } qemu_mutex_lock(&cpu->work_mutex); if (wi->free) { - g_free(wi); + memset(wi, 0, sizeof(qemu_work_item)); + qemu_wi_pool_insert(wi); } else { atomic_mb_set(&wi->done, true); }