From patchwork Mon Aug 28 03:53:25 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Pranith Kumar X-Patchwork-Id: 9924119 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 1D7CA60329 for ; Mon, 28 Aug 2017 03:54:35 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 0ACF11FF2C for ; Mon, 28 Aug 2017 03:54:35 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id F3A79285DA; Mon, 28 Aug 2017 03:54:34 +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 73AD31FF2C for ; Mon, 28 Aug 2017 03:54:34 +0000 (UTC) Received: from localhost ([::1]:36794 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dmB8D-0003oV-O3 for patchwork-qemu-devel@patchwork.kernel.org; Sun, 27 Aug 2017 23:54:33 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:55710) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1dmB7E-0003hZ-DE for qemu-devel@nongnu.org; Sun, 27 Aug 2017 23:53:33 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1dmB7C-0003wK-Gp for qemu-devel@nongnu.org; Sun, 27 Aug 2017 23:53:32 -0400 Received: from mail-yw0-x241.google.com ([2607:f8b0:4002:c05::241]:34176) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1dmB7C-0003vz-Av for qemu-devel@nongnu.org; Sun, 27 Aug 2017 23:53:30 -0400 Received: by mail-yw0-x241.google.com with SMTP id h127so2734778ywf.1 for ; Sun, 27 Aug 2017 20:53:30 -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=dRw9oTjsSlN4Y4flZNeZWXuYy0aQltMSKQSBYL5ypk4=; b=uPepT6cNmOYXBZ4n8VNo9HAHcfwMAffHapEXA3L7VIKucecQ2NzFXn0ZFDONjGczgJ 0epzUy/+ESE61emWv7h53xBYOvMkBhl7wq0d++N78VPKOEERfUaNpvcJ+ISReblXewIc AKMWwPMjXNtB32+JeYLwTINb4nan60sf9zZCyqwx0eonxMooH5/u3FS8cQV27MzGlk+B NWvQXwc1RkmVa8K5aFiIYTcsL0nZ7dsr47ef7gYIgTGMP7WdHbjXx/eL9KrElJzGmxRN kzc8TdMGIoimgFhK8phzSnuH44oCrB585BL54ZeVDFyIO4pg3eTXGs/t937Ck70jjnyc REkw== 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=dRw9oTjsSlN4Y4flZNeZWXuYy0aQltMSKQSBYL5ypk4=; b=RtKlfLcOubaoCo3AFA5R2U5DuaIdlhrbL1YVlNeUuoYs0YqI+CKa12xXzgVD+IwwR1 ar+3eY890XsHJJSd/VMYRN4zk/+HPOaFRg2vTzEUwfvv5FF8ckDEgkz7ySUh4N+A42t8 As9i9ng/gKaaASs7M47S7dArb1NRHpyFBRA3rnJjMKWHQ3EamXeeWYDNZCwXU7b1SSVQ nD5ZrblUAlAiLccOb51pBclMcEs4b4M+ZEUFwNqB5w9WGLWl2Lh3RutB2S5iFW0jtmLb t1O9FTZxnY9P4T+cMh8HPv10ZYb+51uv8EbfXD1U+/ffpwLgQAWEJyYbwv6ZOvysfJiw /DqA== X-Gm-Message-State: AHYfb5iG5l/sxMB1lSUbTyt5k+66If5YlzWW4Mao9gZ76w5qGLlfp5QV FgNQGwMMqeCsXQ== X-Received: by 10.37.160.141 with SMTP id y13mr2187377ybh.353.1503892409640; Sun, 27 Aug 2017 20:53:29 -0700 (PDT) Received: from localhost.localdomain ([98.192.46.210]) by smtp.gmail.com with ESMTPSA id i64sm4820865ywi.64.2017.08.27.20.53.28 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 27 Aug 2017 20:53:29 -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: Sun, 27 Aug 2017 23:53:25 -0400 Message-Id: <20170828035327.17146-2-bobby.prani@gmail.com> X-Mailer: git-send-email 2.13.0 In-Reply-To: <20170828035327.17146-1-bobby.prani@gmail.com> References: <20170828035327.17146-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::241 Subject: [Qemu-devel] [RFC PATCH 2/3] 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. This reduces the number of allocations by 25% (200000 -> 150000 for ARM64 boot+shutdown test). Signed-off-by: Pranith Kumar --- cpus-common.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 70 insertions(+), 15 deletions(-) diff --git a/cpus-common.c b/cpus-common.c index 59f751ecf9..a1c4c7d1a3 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,58 @@ 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 *first, *last; +} 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)); + wi_free_pool->first = NULL; + wi_free_pool->last = NULL; +} + +static void qemu_wi_pool_insert(qemu_work_item *item) +{ + qemu_mutex_lock(&qemu_wi_pool_lock); + if (wi_free_pool->last == NULL) { + wi_free_pool->first = item; + wi_free_pool->last = item; + } else { + wi_free_pool->last->next = item; + wi_free_pool->last = 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 *ret = wi_free_pool->first; + + if (ret == NULL) + goto out; + + wi_free_pool->first = ret->next; + if (wi_free_pool->last == ret) { + wi_free_pool->last = NULL; + } + ret->next = NULL; + + out: + qemu_mutex_unlock(&qemu_wi_pool_lock); + return ret; +} + void qemu_init_cpu_list(void) { /* This is needed because qemu_init_cpu_list is also called by the @@ -43,6 +96,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 +162,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 +181,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); @@ -145,6 +194,7 @@ void do_run_on_cpu(CPUState *cpu, run_on_cpu_func func, run_on_cpu_data data, wi.free = false; wi.exclusive = false; + queue_work_on_cpu(cpu, &wi); while (!atomic_mb_read(&wi.done)) { CPUState *self_cpu = current_cpu; @@ -156,9 +206,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 +351,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 +366,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 +397,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); }