From patchwork Sat Dec 13 00:41:02 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Sunil K Pandey X-Patchwork-Id: 126498 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [127.0.0.1]) by sourceware.org (Postfix) with ESMTP id EE00F4BA2E05 for ; Sat, 13 Dec 2025 00:41:38 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EE00F4BA2E05 Authentication-Results: sourceware.org; dkim=pass (2048-bit key, unprotected) header.d=intel.com header.i=@intel.com header.a=rsa-sha256 header.s=Intel header.b=MA6Ssu4x X-Original-To: libc-alpha@sourceware.org Delivered-To: libc-alpha@sourceware.org Received: from mgamail.intel.com (mgamail.intel.com [192.198.163.11]) by sourceware.org (Postfix) with ESMTPS id CB5354BA2E04 for ; Sat, 13 Dec 2025 00:41:03 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org CB5354BA2E04 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=intel.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org CB5354BA2E04 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=192.198.163.11 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765586464; cv=none; b=cqoe7/47bmEbU5RNYNhjRqGzr5pCzEh4NTjm6GBJFi7nfxNfVPe3h/ZJ0gXnyMFYe5cQiT95fXn5INNoJje3tAt36LHjFoWHvKDe9atfleSjRDW0mRIxkpEx6+2p/wd1+fS+6ojWhihLzDzdQSNA5lOEtBLmST9UuiniHdUmG/8= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1765586464; c=relaxed/simple; bh=8P50mJJCNSHTcJTc7h8OhpWyeuJJDCfntwHL2NkVUDQ=; h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version; b=O60bfVcDWaG8etm6klklRIb8SFG6x0+38vZrZuPgijckPLjjTZPO22ZlmGl0FXbMcGldWiTMssQjq+SuHzmzTSUTB5VfRIHeVrB2lvCr3OLmQXlripDZpepqWatPdAlbf7XYr+lwvgulkOj228XSJ8Ha8i+ibmjXlTc6FeeBb/w= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org CB5354BA2E04 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1765586464; x=1797122464; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=8P50mJJCNSHTcJTc7h8OhpWyeuJJDCfntwHL2NkVUDQ=; b=MA6Ssu4xqzC3RckKO0Wejs9PteYe/PucoV/xyBzOEumE2hOKSHBw+qlJ +Smb2AazNA4V/Qul0JrP6AbdzFs16UtkKs1PDKMEwEzV4QSF9aQSMR3Ly O55CQAPW/15Jj0YDvMRvx6tvJA6iDtQdEE+D1mDWk0zdzNS80hL1a9m5A 6dA37w7UPJHVFtBV3s6AKD0HggdGGgS0HN2/U30Ft4xLwEEomXl0jCKFB NcnPYpc72gxAnJUbpQKeLYvfPnYULnowpPqONPskeGTGWdh6LUnwqHfjA 5LP0Mmkyb2tsBbxeBUDVmAi7nyMK1O1nWOoAKSFo6l/I5kTJ3xPQoiDI2 Q==; X-CSE-ConnectionGUID: hYeqZGNCTBaMPZ5TL3YAGw== X-CSE-MsgGUID: JzBCeqTMRqC0R/XnnW1nLw== X-IronPort-AV: E=McAfee;i="6800,10657,11640"; a="78229653" X-IronPort-AV: E=Sophos;i="6.21,145,1763452800"; d="scan'208";a="78229653" Received: from orviesa003.jf.intel.com ([10.64.159.143]) by fmvoesa105.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 12 Dec 2025 16:41:02 -0800 X-CSE-ConnectionGUID: KR4ebSjUTAyIF2XReIvMFA== X-CSE-MsgGUID: bUENuiGNQL2y7Ap8H0WobA== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.21,145,1763452800"; d="scan'208";a="201400190" Received: from scymds03.sc.intel.com ([10.148.94.166]) by orviesa003.jf.intel.com with ESMTP; 12 Dec 2025 16:41:02 -0800 Received: from gskx-1.sc.intel.com (gskx-1.sc.intel.com [172.25.149.211]) by scymds03.sc.intel.com (Postfix) with ESMTP id 5CB331D8A; Fri, 12 Dec 2025 16:41:02 -0800 (PST) From: Sunil K Pandey To: libc-alpha@sourceware.org Cc: hjl.tools@gmail.com, fweimer@redhat.com, carlos@redhat.com, alex.m.wells@intel.com Subject: [PATCH v4] benchtests: Add pthread mutex trylock throughput test (BZ #33704) Date: Fri, 12 Dec 2025 16:41:02 -0800 Message-ID: <20251213004102.1864602-1-sunil.k.pandey@intel.com> X-Mailer: git-send-email 2.51.0 In-Reply-To: References: MIME-Version: 1.0 X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED, SPF_HELO_NONE, SPF_NONE, TXREP, URIBL_BLOCKED autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: libc-alpha@sourceware.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Libc-alpha mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: libc-alpha-bounces~patchwork=sourceware.org@sourceware.org This benchmark measures number of successful updates per second under high cache contention. Tested on x86_64. Reviewed-by: H.J. Lu --- benchtests/Makefile | 2 + .../bench-pthread-mutex-trylock-throughput.c | 177 ++++++++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 benchtests/bench-pthread-mutex-trylock-throughput.c diff --git a/benchtests/Makefile b/benchtests/Makefile index 2ecdde857e..c3368a7603 100644 --- a/benchtests/Makefile +++ b/benchtests/Makefile @@ -175,6 +175,7 @@ bench-pthread := \ pthread-locks \ pthread-mutex-lock \ pthread-mutex-trylock \ + pthread-mutex-trylock-throughput \ pthread-spin-lock \ pthread-spin-trylock \ pthread_once \ @@ -188,6 +189,7 @@ bench-resolv := \ LDLIBS-bench-pthread-mutex-lock += -lm LDLIBS-bench-pthread-mutex-trylock += -lm +LDLIBS-bench-pthread-mutex-trylock-throughput += -lm LDLIBS-bench-pthread-spin-lock += -lm LDLIBS-bench-pthread-spin-trylock += -lm diff --git a/benchtests/bench-pthread-mutex-trylock-throughput.c b/benchtests/bench-pthread-mutex-trylock-throughput.c new file mode 100644 index 0000000000..72eb90e4d9 --- /dev/null +++ b/benchtests/bench-pthread-mutex-trylock-throughput.c @@ -0,0 +1,177 @@ +/* Measure pthread trylock throughput under high cache contention. + Copyright (C) 2025 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + . */ + +#define TEST_MAIN +#define TIMEOUT (20 * 60) +#define TEST_NAME "pthread-mutex-trylock-throughput" + +#include +#include +#include +#include +#include +#include +#include +#include +#include "bench-timing.h" +#include "bench-util.h" +#include "json-lib.h" + +#define ITERS 10000000 +#define RUN_COUNT 10 + +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; + +/* Shared counter only incremented by successful threads. */ +int counter = 0; + +static void * +worker (void *v) +{ + for (int i = 0; i < ITERS; i++) + if (pthread_mutex_trylock(&mutex) == 0) + { + counter++; + pthread_mutex_unlock(&mutex); + } + return NULL; +} + +static void +do_bench_one (const char *name, int num_threads, int nprocs, json_ctx_t *js) +{ + struct timeval ts, te; + double tsd, ted, td, mean, stdev; + int i, j; + pthread_t *threads = malloc (num_threads * sizeof (pthread_t)); + + /* Array to hold throughput(#updates/second) result of each run. We do + RUN_COUNT + 2 runs so that we can discard the highest and lowest as + outliers. */ + double throughput_count[RUN_COUNT + 2]; + + for (i = 0; i < RUN_COUNT + 2; i++) + { + /* Initialize counter before each run. */ + counter = 0; + gettimeofday (&ts, NULL); + + for (j = 0; j < num_threads; j++) + pthread_create (&threads[j], NULL, worker, NULL); + + for (j = 0; j < num_threads; j++) + pthread_join (threads[j], NULL); + gettimeofday (&te, NULL); + tsd = ts.tv_sec + ts.tv_usec / 1000000.0; + ted = te.tv_sec + te.tv_usec / 1000000.0; + td = ted - tsd; + + /* Number of successful updates per second. */ + throughput_count[i] = counter / td; + } + + free (threads); + + /* Sort the results so we can discard the largest and smallest + throughput as outliers. */ + for (i = 0; i < RUN_COUNT + 1; i++) + for (j = i + 1; j < RUN_COUNT + 2; j++) + if (throughput_count[i] > throughput_count[j]) + { + double temp = throughput_count[i]; + throughput_count[i] = throughput_count[j]; + throughput_count[j] = temp; + } + + /* Calculate mean and standard deviation. */ + mean = 0; + for (i = 1; i < RUN_COUNT + 1; i++) + mean += throughput_count[i]; + mean /= RUN_COUNT; + + stdev = 0.0; + for (i = 1; i < RUN_COUNT + 1; i++) + { + double s = throughput_count[i] - mean; + stdev += s * s; + } + stdev = sqrt (stdev / (RUN_COUNT - 1)); + + char buf[256]; + snprintf (buf, sizeof buf, "%s,threads=%d,HW threads=%d", name, num_threads, + nprocs); + + json_attr_object_begin (js, buf); + + json_attr_uint (js, "mean", mean); + json_attr_uint (js, "stdev", stdev); + json_attr_uint (js, "min-outlier", throughput_count[0]); + json_attr_uint (js, "min", throughput_count[1]); + json_attr_uint (js, "max", throughput_count[RUN_COUNT]); + json_attr_uint (js, "max-outlier", throughput_count[RUN_COUNT + 1]); + + json_attr_object_end (js); +} + +int +do_bench (void) +{ + int rv = 0; + json_ctx_t json_ctx; + int th_num, th_conf, nprocs; + char name[128]; + + json_init (&json_ctx, 2, stdout); + json_attr_object_begin (&json_ctx, TEST_NAME); + + /* The thread config begins from 2, and increases by 2x until nprocs. + We also want to test nprocs and over-saturation case 2*nprocs and + 4*nprocs. */ + nprocs = get_nprocs (); + + /* Allocate [nprocs + 2] thread config array. */ + int *threads = malloc ((nprocs + 2) * sizeof (int)); + + th_num = 2; + for (th_conf = 0; th_num < nprocs; th_conf++) + { + threads[th_conf] = th_num; + th_num <<= 1; + } + threads[th_conf++] = nprocs; + threads[th_conf++] = nprocs * 2; + threads[th_conf++] = nprocs * 4; + + snprintf (name, sizeof name, "type=throughput(#updates/second)"); + + for (int i = 0; i < th_conf; i++) + { + th_num = threads[i]; + do_bench_one (name, th_num, nprocs, &json_ctx); + } + + free (threads); + + json_attr_object_end (&json_ctx); + + return rv; +} + +#define TEST_FUNCTION do_bench () + +#include "../test-skeleton.c"