From nobody Wed Nov 5 14:27:33 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) client-ip=208.118.235.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zoho.com: domain of gnu.org designates 208.118.235.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com Return-Path: Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) by mx.zohomail.com with SMTPS id 1534872261096497.3091369434286; Tue, 21 Aug 2018 10:24:21 -0700 (PDT) Received: from localhost ([::1]:55048 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fsAOB-0005Fu-VS for importer@patchew.org; Tue, 21 Aug 2018 13:24:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:33157) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1fsA4M-0001hV-To for qemu-devel@nongnu.org; Tue, 21 Aug 2018 13:03:52 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1fsA49-0006FC-6Q for qemu-devel@nongnu.org; Tue, 21 Aug 2018 13:03:44 -0400 Received: from mail-wr1-x442.google.com ([2a00:1450:4864:20::442]:37034) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1fsA3z-0005wo-Ij for qemu-devel@nongnu.org; Tue, 21 Aug 2018 13:03:31 -0400 Received: by mail-wr1-x442.google.com with SMTP id u12-v6so16461248wrr.4 for ; Tue, 21 Aug 2018 10:03:26 -0700 (PDT) Received: from 640k.lan (dynamic-adsl-78-12-184-244.clienti.tiscali.it. [78.12.184.244]) by smtp.gmail.com with ESMTPSA id v6-v6sm2608955wmc.43.2018.08.21.10.03.24 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 21 Aug 2018 10:03:24 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=PqC73kbg/Q5/0rJ6SUcm1XeC+VJnEpv1c0foIGcv1GI=; b=MyYqC39foEhKlrFHtYT6VamDVDFNSJDRH4IRNn4BudbRbUHtMwHwUXPjSPDTYeaI5O KeZbUXNgFSzU/ZzbeT1/WOOp9oDcK6naZg6YhPrQyZGEglEtpSUR9utbfP60yYvirtkQ p8v5QHCW+jlEtU+BFiR5pLA/aJOodanB+pYLjV0zuB3Uurq9p55I/WxVCO5NUb3LyBR+ qMQO09V/kTPbGfcXC4lItsLycRSf7O6iFJDXnjwtVj7yyqXsc7HGNKrsYFhoyKmtGzSe BcyOEPeHgg8NedICBkRV40BmiopDsP7KWbPALiyd4Vf6sh+Wh0l3TMx+zz8WnI9Re+Le 6Y8A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=PqC73kbg/Q5/0rJ6SUcm1XeC+VJnEpv1c0foIGcv1GI=; b=MXklycrUnNbS4eHxlIASJB5itX0mTkCSJNwQ4Hjt/V4VHwdK+fxr7THhAWGh8c+4Fg WEreaINvVP1KOuoDCUreyTiWzfm7EWXrt9+ir83ZG1FrXYY4OdB5ySaeCYBSzK/9Ey8T da1EzvUGIybIpF03tCrLEw+WNaEt5CspdyPSYnZC0HAswH500IDY1WzXPBdUjcOVnu3Z 8LWvme3UIFDukqJ+IzyiCJzO0s+FbjkThxu6gjOToIQkLUTcHicettO/2caXJLIJP31W 79cGr3Ayj6U1WEWagmOCBu6nt7lTjlRP2o9eZUhcWW3ZQwjIfmSMk6dJ3Av9C2IOzyQu m85A== X-Gm-Message-State: AOUpUlGqFbH3tQrNw/oJGcsb+8ntrdev2mWnBgKajvQHtGriftSqsZZO +SOo9iG0Mc9RhENX+UK8pRxdIOrZ X-Google-Smtp-Source: ANB0VdZlqVrRdoYhZKP5Q1Jj1jQAc6PmyL+pFenVBGVQ6qfIwDcmLVRQ14GxUjDE+fTFJDEariDHyg== X-Received: by 2002:adf:8567:: with SMTP id 94-v6mr12157761wrh.223.1534871004956; Tue, 21 Aug 2018 10:03:24 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Tue, 21 Aug 2018 19:01:52 +0200 Message-Id: <1534870966-9287-21-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1534870966-9287-1-git-send-email-pbonzini@redhat.com> References: <1534870966-9287-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:4864:20::442 Subject: [Qemu-devel] [PULL 20/74] qsp: add qsp_reset 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: "Emilio G. Cota" Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZohoMail: RDMRC_1 RDKM_2 RSF_0 Z_629925259 SPT_0 Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" From: "Emilio G. Cota" I first implemented this by deleting all entries in the global hash table. But doing that safely slows down profiling, since we'd need to introduce rcu_read_lock/unlock in the fast path. What's implemented here avoids messing with the thread-local data in the global hash table. It achieves this by taking a snapshot of the current state, so that subsequent reports present the delta wrt to the snapshot. Signed-off-by: Emilio G. Cota Signed-off-by: Paolo Bonzini --- include/qemu/qsp.h | 1 + util/qsp.c | 94 ++++++++++++++++++++++++++++++++++++++++++++++++++= ++++ 2 files changed, 95 insertions(+) diff --git a/include/qemu/qsp.h b/include/qemu/qsp.h index 209480b..f8c6c96 100644 --- a/include/qemu/qsp.h +++ b/include/qemu/qsp.h @@ -24,5 +24,6 @@ void qsp_report(FILE *f, fprintf_function cpu_fprintf, si= ze_t max, bool qsp_is_enabled(void); void qsp_enable(void); void qsp_disable(void); +void qsp_reset(void); =20 #endif /* QEMU_QSP_H */ diff --git a/util/qsp.c b/util/qsp.c index 80dbd4c..4b1308b 100644 --- a/util/qsp.c +++ b/util/qsp.c @@ -47,6 +47,11 @@ * an intermediate hash table. This would simplify the code only slightl= y, but * would perform badly if there were many threads and objects to track. * + * - Wrap operations on qsp entries with RCU read-side critical sections, = so + * that qsp_reset() can delete entries. Unfortunately, the overhead of c= alling + * rcu_read_lock/unlock slows down atomic_add-bench -m by 24%. Having + * a snapshot that is updated on qsp_reset() avoids this overhead. + * * Related Work: * - Lennart Poettering's mutrace: http://0pointer.de/blog/projects/mutrac= e.html * - Lozi, David, Thomas, Lawall and Muller. "Remote Core Locking: Migrati= ng @@ -57,6 +62,7 @@ #include "qemu/thread.h" #include "qemu/timer.h" #include "qemu/qht.h" +#include "qemu/rcu.h" #include "exec/tb-hash-xx.h" =20 enum QSPType { @@ -88,6 +94,12 @@ struct QSPEntry { }; typedef struct QSPEntry QSPEntry; =20 +struct QSPSnapshot { + struct rcu_head rcu; + struct qht ht; +}; +typedef struct QSPSnapshot QSPSnapshot; + /* initial sizing for hash tables */ #define QSP_INITIAL_SIZE 64 =20 @@ -107,6 +119,7 @@ static __thread int qsp_thread; static struct qht qsp_callsite_ht; =20 static struct qht qsp_ht; +static QSPSnapshot *qsp_snapshot; static bool qsp_initialized, qsp_initializing; =20 static const char * const qsp_typenames[] =3D { @@ -505,15 +518,69 @@ static void qsp_aggregate(struct qht *global_ht, void= *p, uint32_t h, void *up) qsp_entry_aggregate(agg, e); } =20 +static void qsp_iter_diff(struct qht *orig, void *p, uint32_t hash, void *= htp) +{ + struct qht *ht =3D htp; + QSPEntry *old =3D p; + QSPEntry *new; + + new =3D qht_lookup(ht, old, hash); + /* entries are never deleted, so we must have this one */ + g_assert(new !=3D NULL); + /* our reading of the stats happened after the snapshot was taken */ + g_assert(new->n_acqs >=3D old->n_acqs); + g_assert(new->ns >=3D old->ns); + + new->n_acqs -=3D old->n_acqs; + new->ns -=3D old->ns; + + /* No point in reporting an empty entry */ + if (new->n_acqs =3D=3D 0 && new->ns =3D=3D 0) { + bool removed =3D qht_remove(ht, new, hash); + + g_assert(removed); + g_free(new); + } +} + +static void qsp_diff(struct qht *orig, struct qht *new) +{ + qht_iter(orig, qsp_iter_diff, new); +} + +static void qsp_ht_delete(struct qht *ht, void *p, uint32_t h, void *htp) +{ + g_free(p); +} + static void qsp_mktree(GTree *tree) { + QSPSnapshot *snap; struct qht ht; =20 + /* + * First, see if there's a prior snapshot, so that we read the global = hash + * table _after_ the snapshot has been created, which guarantees that + * the entries we'll read will be a superset of the snapshot's entries. + * + * We must remain in an RCU read-side critical section until we're done + * with the snapshot. + */ + rcu_read_lock(); + snap =3D atomic_rcu_read(&qsp_snapshot); + /* Aggregate all results from the global hash table into a local one */ qht_init(&ht, qsp_entry_no_thread_cmp, QSP_INITIAL_SIZE, QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); qht_iter(&qsp_ht, qsp_aggregate, &ht); =20 + /* compute the difference wrt the snapshot, if any */ + if (snap) { + qsp_diff(&snap->ht, &ht); + } + /* done with the snapshot; RCU can reclaim it */ + rcu_read_unlock(); + /* sort the hash table elements by using a tree */ qht_iter(&ht, qsp_sort, tree); =20 @@ -652,3 +719,30 @@ void qsp_report(FILE *f, fprintf_function cpu_fprintf,= size_t max, pr_report(&rep, f, cpu_fprintf); report_destroy(&rep); } + +static void qsp_snapshot_destroy(QSPSnapshot *snap) +{ + qht_iter(&snap->ht, qsp_ht_delete, NULL); + qht_destroy(&snap->ht); + g_free(snap); +} + +void qsp_reset(void) +{ + QSPSnapshot *new =3D g_new(QSPSnapshot, 1); + QSPSnapshot *old; + + qsp_init(); + + qht_init(&new->ht, qsp_entry_cmp, QSP_INITIAL_SIZE, + QHT_MODE_AUTO_RESIZE | QHT_MODE_RAW_MUTEXES); + + /* take a snapshot of the current state */ + qht_iter(&qsp_ht, qsp_aggregate, &new->ht); + + /* replace the previous snapshot, if any */ + old =3D atomic_xchg(&qsp_snapshot, new); + if (old) { + call_rcu(old, qsp_snapshot_destroy, rcu); + } +} --=20 1.8.3.1