From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id A4B8B45BD4; Fri, 25 Oct 2024 10:50:58 +0200 (CEST) Received: from mails.dpdk.org (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 42237402BB; Fri, 25 Oct 2024 10:50:55 +0200 (CEST) Received: from EUR03-DBA-obe.outbound.protection.outlook.com (mail-dbaeur03on2080.outbound.protection.outlook.com [40.107.104.80]) by mails.dpdk.org (Postfix) with ESMTP id B9CA14003C for ; Fri, 25 Oct 2024 10:50:52 +0200 (CEST) ARC-Seal: i=1; a=rsa-sha256; s=arcselector10001; d=microsoft.com; cv=none; b=MNw+REV7AAlucAdMTiXkWlTAGFgD8p1HZUnJcFy4X+05Rmt1DVPe70ljDVwmPBLxxD4/Bk35BRIh2O7grYXwGyh2/jYChNvNXwkW0OrOF+qKRP1muWkF8Y1I3V9Tz00tnabEfvXGG8dLjA9lrOb/uIDw/1nIOJO0ArfDn3yx4QqrgbwUsACdMnjZEwXS+/I9h/aK33BJPZmykOl5SISZYiuMsmYZ4jOzS0+z1qZ8B+C5Mr7KWSpvhZAn/QW26De6LWG2ku6JVutf/MIjmB00lhu3IK/RxgkMuxjtEFp1tIJUIMIgVlxkLBE3VDENd/9K8M0DLlJLR8GB0XpQOkPY+w== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector10001; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-AntiSpam-MessageData-ChunkCount:X-MS-Exchange-AntiSpam-MessageData-0:X-MS-Exchange-AntiSpam-MessageData-1; bh=o6b1HEcpM0KUhEWZJInRKcoUJDY2fcG+jTKaAEbm0uw=; b=I3Nro0BRLs+2EJszrFcODni7+rfxfrhATIlTTKrSOPwPI4jVMfqlnKArlU8m3jVHDLWV6jAQ7rq82sM0HWKySzVpogEkY7/7u/CIabZ1TQGJT0KZgaO7GWeRy44Glj5hjqCSAxK2CBP4sESbrV9YctfUqmTAjpJVS0zA5MQ4SB/NRZI8EHt8zo5QaQOMe77RiP55mr0Vng+TJ4DouUHDuxH/5js3MYHfYfmrsKgN/f7YuP5BBa5wvr6D84yaGK/Gf+zoGPU8WouKhJsKqaILdD+EvZc5m9Y6fRuVMCxKGsbo9AcMrcNYsePbvFEvCrY0dsj457WghziHUdHSiSVyug== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=pass (sender ip is 192.176.1.74) smtp.rcpttodomain=dpdk.org smtp.mailfrom=ericsson.com; dmarc=pass (p=reject sp=reject pct=100) action=none header.from=ericsson.com; dkim=none (message not signed); arc=none (0) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=ericsson.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=o6b1HEcpM0KUhEWZJInRKcoUJDY2fcG+jTKaAEbm0uw=; b=g3cJErUO0mucsaBk7UWOR7k5SWBeBm5WuppLzosXWShC1icvO5kvQEuX3nW+rBY/H9iBVC0DGAlUzfaVMUzqci4l5ifABCaZu94LAI2Gbs9uf58OjtlQDz0Y0f6n8nSlUCQ+UaytvLR5YlNEeZ/0gWV5wshZTRKgoh/uRzDY7aSgDVfkqj5j4nhTObvtHEpWkGg04MZTiiMeMhrqTkYxRO/hEp7bZ+Ocv2k48U99CN4lb0FXMeVNY/BuSufsuINXEE1jrb/dbt7SwmF3LbfAhD9asG/hWZ1klGpGW6Uw7PcU/9rrHEOxgljhocJJ3lKWMvKupyC7QHtSdesIvVhsSw== Received: from DUZPR01CA0271.eurprd01.prod.exchangelabs.com (2603:10a6:10:4b9::27) by AS8PR07MB7448.eurprd07.prod.outlook.com (2603:10a6:20b:28b::23) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8093.20; Fri, 25 Oct 2024 08:50:50 +0000 Received: from DB5PEPF00014B97.eurprd02.prod.outlook.com (2603:10a6:10:4b9:cafe::34) by DUZPR01CA0271.outlook.office365.com (2603:10a6:10:4b9::27) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8093.20 via Frontend Transport; Fri, 25 Oct 2024 08:50:50 +0000 X-MS-Exchange-Authentication-Results: spf=pass (sender IP is 192.176.1.74) smtp.mailfrom=ericsson.com; dkim=none (message not signed) header.d=none;dmarc=pass action=none header.from=ericsson.com; Received-SPF: Pass (protection.outlook.com: domain of ericsson.com designates 192.176.1.74 as permitted sender) receiver=protection.outlook.com; client-ip=192.176.1.74; helo=oa.msg.ericsson.com; pr=C Received: from oa.msg.ericsson.com (192.176.1.74) by DB5PEPF00014B97.mail.protection.outlook.com (10.167.8.235) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.8093.14 via Frontend Transport; Fri, 25 Oct 2024 08:50:50 +0000 Received: from seliicinfr00050.seli.gic.ericsson.se (153.88.142.248) by smtp-central.internal.ericsson.com (100.87.178.69) with Microsoft SMTP Server id 15.2.1544.11; Fri, 25 Oct 2024 10:50:49 +0200 Received: from breslau.. (seliicwb00002.seli.gic.ericsson.se [10.156.25.100]) by seliicinfr00050.seli.gic.ericsson.se (Postfix) with ESMTP id E55A31C009D; Fri, 25 Oct 2024 10:50:49 +0200 (CEST) From: =?UTF-8?q?Mattias=20R=C3=B6nnblom?= To: CC: , =?UTF-8?q?Morten=20Br=C3=B8rup?= , Stephen Hemminger , Konstantin Ananyev , David Marchand , Jerin Jacob , Luka Jankovic , Thomas Monjalon , =?UTF-8?q?Mattias=20R=C3=B6nnblom?= , "Chengwen Feng" Subject: [PATCH v17 3/8] eal: add lcore variable performance test Date: Fri, 25 Oct 2024 10:41:44 +0200 Message-ID: <20241025084149.873037-4-mattias.ronnblom@ericsson.com> X-Mailer: git-send-email 2.34.1 In-Reply-To: <20241025084149.873037-1-mattias.ronnblom@ericsson.com> References: <20241023075302.869008-1-mattias.ronnblom@ericsson.com> <20241025084149.873037-1-mattias.ronnblom@ericsson.com> MIME-Version: 1.0 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 8bit X-EOPAttributedMessage: 0 X-MS-PublicTrafficType: Email X-MS-TrafficTypeDiagnostic: DB5PEPF00014B97:EE_|AS8PR07MB7448:EE_ X-MS-Office365-Filtering-Correlation-Id: 68e33677-bc09-4dca-a295-08dcf4d22080 X-MS-Exchange-SenderADCheck: 1 X-MS-Exchange-AntiSpam-Relay: 0 X-Microsoft-Antispam: BCL:0; ARA:13230040|1800799024|82310400026|36860700013|376014; X-Microsoft-Antispam-Message-Info: =?utf-8?B?bkM4Zlg3OG5GZ04wRjFPWGx2ZmsvTnJKZG5UQUU2UXZ6QjgxVmlnKzVGUm85?= =?utf-8?B?YWpQYWtIUTRuOHY2N04yY1docFk5SjVyTE9ORHpvTVRyS2NaMWxhSjUrT2or?= =?utf-8?B?blp5dktxZlptVm5XQmZiNGtEUkV0clUzSE84NE9qSkFGY3M3Ny9BZGpjV1Jv?= =?utf-8?B?N09FTlZuYklzeWtJWE00bU8rdUNPaWRIVVZUVWtub1J2VnlXWmJVUTVxcjlD?= =?utf-8?B?M0VCcXZFUG11NTk0eVA4cWNRcmROYkZuRHRmZnZ3U0Y2UVVVMnErV045L3NB?= =?utf-8?B?bjdPSWQ1Nmwrck5HL3hvNGxpRXBKWVowU3ZKdEJmQzRkWkFhRmQ0ZXhReWxv?= =?utf-8?B?U3Z2c0p4b1FYK1lNZzdyNThqbVpwWmRWMlo2MmNXeEZ0OEIrdWYxcEdWQXc5?= =?utf-8?B?aVNucmxyRkhJeldHaGlVMWRDWWhqbEVEQUdNS2cvRkN0V2JXTWNMZFZvcWs5?= =?utf-8?B?ZzBZTFlOK0VqTGRFa1hWUlMxMForWGlJTjloSlFXU1FkWUU3ZGticElWOXls?= =?utf-8?B?K3pNQjZOS000QUYvT2FlU1ZiUmZvRzJoWVovZ0NtRDBEOFpCaS9ORDUzbUZT?= =?utf-8?B?UWlMY3FoajF2S2RqdE80ZW95VXlpY1E1emxLYmhERnFuOVg1OGZBSythOXJt?= =?utf-8?B?ZS93ZzMxemZ4a0pod1B3elZKZVQrb1lWcCt5V3NtV2htWHBEN2NpSFdsRG93?= =?utf-8?B?NklyR1ViZ3pYRTZmaVVPU2NHcm5XSHNxZTBXaVF1WWszZnZrblVNQ0k5cFhq?= =?utf-8?B?VnJDK0pkQ0c2YXgvL1dSZlY1d2d4QzNTUFZlRlVGaEQwVnpncXc5cHdERzZ5?= =?utf-8?B?aitENnlFcS9qeDFmdElIbkQvVCt6TzR3anhTS00wNGtUVzlqS0dTZ0FUODZi?= =?utf-8?B?dUwreW8yQVY5QVd0L29zaG5rUnA4SlhSczk4ZHllbGtoejVrWkR2SzhaREsy?= =?utf-8?B?Kys1MTBoK0xXWDdBYk9XL3JRUlZSOWxjRzFYc2huemwyWWN0eXNIMGVnMjFN?= =?utf-8?B?VkdzZ1I2RFpLUmZkRmlPQVA0K0FDTC9aTHBOL0xiT01iYVVuTmVJUjhjWk5W?= =?utf-8?B?aDdiMnpleFNoWnRQNzJnSytlTzIzc0FYMmUxVkE4bitNMmwzd2JVNEJBaHZM?= =?utf-8?B?WUVoclMxVkhPVHk4cStmaThjQ1duYUlBM0ZrMDJnQVVVQUR5NUc5NnNVeUZ4?= =?utf-8?B?ZDN3dW1qbTF6MW5KY2FUUjNSZWxHV1ZIVDRXN3dmZ1VzQjdFbDdBSDVjckxW?= =?utf-8?B?TlVEeDUrY0k5T3IwbkF5d2lwWk9EUGJUUUhwdzRCU1VHc0VxMHBkU3BHL1cx?= =?utf-8?B?UXZ6OVBJMDdodlVMZTFCNkQ3S3g5L1EzNWpOd1RXc0krbitTejJrQzZLZndO?= =?utf-8?B?OE1KWVRwd3FxUWtrOHgyY3N4MWlhVHFTV2pzZjBHb0NjQjBaV3hOR1MxQ2xn?= =?utf-8?B?aXZhcUtRNzY4ZXlEcjVaVStwNkVnTWsyVGoxS0NIekR0N2UzbTBLQ0hFSnM4?= =?utf-8?B?dVBPUFJPWmU2N0xzTGd6dUJjZm52Uk83RWVsYW41SDJUR1JMRXByUGx0VWhX?= =?utf-8?B?K3VxY0pSSHl4bXJvSVZmSlpHem1aVkk4VXExNFA2QTI2YmRVeTE5NXBGUFhB?= =?utf-8?B?a2dwSllFZUNYT1dKb1VGRUd0cG1DR0FxWFh4NFpKbWI1aHFKZVcxc2Z5Z1d0?= =?utf-8?B?M1M4bUVCSTFOOC9DWm9xZlVINEtKZVRvanBVSUVxOWdQcVBYN3I5RlFBZW1v?= =?utf-8?B?K0FvZWlTMDVFZ2wrajh3NExMdGpMRTRFNlNaaTNIUytFV1BZVi81Nnh6ZzdM?= =?utf-8?B?VXFXUzY0OVozaW9McWhSM2RQMDhXdUFUMVZYcWZIKzFZRnR6cVR2MVIrekZM?= =?utf-8?B?dEYzSGRHSVlTWHpibGV6ZmRwZnMraFJYaTlrL01YeFJCTnc9PQ==?= X-Forefront-Antispam-Report: CIP:192.176.1.74; CTRY:SE; LANG:en; SCL:1; SRV:; IPV:NLI; SFV:NSPM; H:oa.msg.ericsson.com; PTR:office365.se.ericsson.net; CAT:NONE; SFS:(13230040)(1800799024)(82310400026)(36860700013)(376014); DIR:OUT; SFP:1101; X-OriginatorOrg: ericsson.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Oct 2024 08:50:50.4753 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 68e33677-bc09-4dca-a295-08dcf4d22080 X-MS-Exchange-CrossTenant-Id: 92e84ceb-fbfd-47ab-be52-080c6b87953f X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=92e84ceb-fbfd-47ab-be52-080c6b87953f; Ip=[192.176.1.74]; Helo=[oa.msg.ericsson.com] X-MS-Exchange-CrossTenant-AuthSource: DB5PEPF00014B97.eurprd02.prod.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: AS8PR07MB7448 X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Add basic micro benchmark for lcore variables, in an attempt to assure that the overhead isn't significantly greater than alternative approaches, in scenarios where the benefits aren't expected to show up (i.e., when plenty of cache is available compared to the working set size of the per-lcore data). Signed-off-by: Mattias Rönnblom Acked-by: Chengwen Feng Acked-by: Stephen Hemminger Acked-by: Morten Brørup -- PATCH v8: * Fix spelling. (Morten Brørup) PATCH v6: * Use floating point math when calculating per-update latency. (Morten Brørup) PATCH v5: * Add variant of thread-local storage with initialization performed at the time of thread creation to the benchmark scenarios. (Morten Brørup) PATCH v4: * Rework the tests to be a little less unrealistic. Instead of a single dummy module using a single variable, use a number of variables/modules. In this way, differences in cache effects may show up. * Add RTE_CACHE_GUARD to better mimic that static array pattern. (Morten Brørup) * Show latencies as TSC cycles. (Morten Brørup) --- app/test/meson.build | 1 + app/test/test_lcore_var_perf.c | 256 +++++++++++++++++++++++++++++++++ 2 files changed, 257 insertions(+) create mode 100644 app/test/test_lcore_var_perf.c diff --git a/app/test/meson.build b/app/test/meson.build index 7dccd197ac..40f22a54d5 100644 --- a/app/test/meson.build +++ b/app/test/meson.build @@ -105,6 +105,7 @@ source_file_deps = { 'test_kvargs.c': ['kvargs'], 'test_latencystats.c': ['ethdev', 'latencystats', 'metrics'] + sample_packet_forward_deps, 'test_lcore_var.c': [], + 'test_lcore_var_perf.c': [], 'test_lcores.c': [], 'test_link_bonding.c': ['ethdev', 'net_bond', 'net'] + packet_burst_generator_deps + virtual_pmd_deps, diff --git a/app/test/test_lcore_var_perf.c b/app/test/test_lcore_var_perf.c new file mode 100644 index 0000000000..6d9869f873 --- /dev/null +++ b/app/test/test_lcore_var_perf.c @@ -0,0 +1,256 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2024 Ericsson AB + */ + +#define MAX_MODS 1024 + +#include + +#include +#include +#include +#include +#include + +#include "test.h" + +struct mod_lcore_state { + uint64_t a; + uint64_t b; + uint64_t sum; +}; + +static void +mod_init(struct mod_lcore_state *state) +{ + state->a = rte_rand(); + state->b = rte_rand(); + state->sum = 0; +} + +static __rte_always_inline void +mod_update(volatile struct mod_lcore_state *state) +{ + state->sum += state->a * state->b; +} + +struct __rte_cache_aligned mod_lcore_state_aligned { + struct mod_lcore_state mod_state; + + RTE_CACHE_GUARD; +}; + +static struct mod_lcore_state_aligned +sarray_lcore_state[MAX_MODS][RTE_MAX_LCORE]; + +static void +sarray_init(void) +{ + unsigned int lcore_id = rte_lcore_id(); + int mod; + + for (mod = 0; mod < MAX_MODS; mod++) { + struct mod_lcore_state *mod_state = + &sarray_lcore_state[mod][lcore_id].mod_state; + + mod_init(mod_state); + } +} + +static __rte_noinline void +sarray_update(unsigned int mod) +{ + unsigned int lcore_id = rte_lcore_id(); + struct mod_lcore_state *mod_state = + &sarray_lcore_state[mod][lcore_id].mod_state; + + mod_update(mod_state); +} + +struct mod_lcore_state_lazy { + struct mod_lcore_state mod_state; + bool initialized; +}; + +/* + * Note: it's usually a bad idea have this much thread-local storage + * allocated in a real application, since it will incur a cost on + * thread creation and non-lcore thread memory usage. + */ +static RTE_DEFINE_PER_LCORE(struct mod_lcore_state_lazy, + tls_lcore_state)[MAX_MODS]; + +static inline void +tls_init(struct mod_lcore_state_lazy *state) +{ + mod_init(&state->mod_state); + + state->initialized = true; +} + +static __rte_noinline void +tls_lazy_update(unsigned int mod) +{ + struct mod_lcore_state_lazy *state = + &RTE_PER_LCORE(tls_lcore_state[mod]); + + /* With thread-local storage, initialization must usually be lazy */ + if (!state->initialized) + tls_init(state); + + mod_update(&state->mod_state); +} + +static __rte_noinline void +tls_update(unsigned int mod) +{ + struct mod_lcore_state_lazy *state = + &RTE_PER_LCORE(tls_lcore_state[mod]); + + mod_update(&state->mod_state); +} + +RTE_LCORE_VAR_HANDLE(struct mod_lcore_state, lvar_lcore_state)[MAX_MODS]; + +static void +lvar_init(void) +{ + unsigned int mod; + + for (mod = 0; mod < MAX_MODS; mod++) { + RTE_LCORE_VAR_ALLOC(lvar_lcore_state[mod]); + + struct mod_lcore_state *state = + RTE_LCORE_VAR(lvar_lcore_state[mod]); + + mod_init(state); + } +} + +static __rte_noinline void +lvar_update(unsigned int mod) +{ + struct mod_lcore_state *state = RTE_LCORE_VAR(lvar_lcore_state[mod]); + + mod_update(state); +} + +static void +shuffle(unsigned int *elems, size_t len) +{ + size_t i; + + for (i = len - 1; i > 0; i--) { + unsigned int other = rte_rand_max(i + 1); + + unsigned int tmp = elems[other]; + elems[other] = elems[i]; + elems[i] = tmp; + } +} + +#define ITERATIONS UINT64_C(10000000) + +static inline double +benchmark_access(const unsigned int *mods, unsigned int num_mods, + void (*init_fun)(void), void (*update_fun)(unsigned int)) +{ + unsigned int i; + double start; + double end; + double latency; + unsigned int num_mods_mask = num_mods - 1; + + RTE_VERIFY(rte_is_power_of_2(num_mods)); + + if (init_fun != NULL) + init_fun(); + + /* Warm up cache and make sure TLS variables are initialized */ + for (i = 0; i < num_mods; i++) + update_fun(i); + + start = rte_rdtsc(); + + for (i = 0; i < ITERATIONS; i++) + update_fun(mods[i & num_mods_mask]); + + end = rte_rdtsc(); + + latency = (end - start) / (double)ITERATIONS; + + return latency; +} + +static void +test_lcore_var_access_n(unsigned int num_mods) +{ + double sarray_latency; + double tls_latency; + double lazy_tls_latency; + double lvar_latency; + unsigned int mods[num_mods]; + unsigned int i; + + for (i = 0; i < num_mods; i++) + mods[i] = i; + + shuffle(mods, num_mods); + + sarray_latency = + benchmark_access(mods, num_mods, sarray_init, sarray_update); + + tls_latency = + benchmark_access(mods, num_mods, NULL, tls_update); + + lazy_tls_latency = + benchmark_access(mods, num_mods, NULL, tls_lazy_update); + + lvar_latency = + benchmark_access(mods, num_mods, lvar_init, lvar_update); + + printf("%17u %8.1f %14.1f %15.1f %10.1f\n", num_mods, sarray_latency, + tls_latency, lazy_tls_latency, lvar_latency); +} + +/* + * The potential performance benefit of lcore variables compared to + * the use of statically sized, lcore id-indexed arrays is not + * shorter latencies in a scenario with low cache pressure, but rather + * fewer cache misses in a real-world scenario, with extensive cache + * usage. These tests are a crude simulation of such, using dummy + * modules, each with a small, per-lcore state. Note however that + * these tests have very little non-lcore/thread local state, which is + * unrealistic. + */ + +static int +test_lcore_var_access(void) +{ + unsigned int num_mods = 1; + + printf("- Latencies [TSC cycles/update] -\n"); + printf("Number of Static Thread-local Thread-local Lcore\n"); + printf("Modules/Variables Array Storage Storage (Lazy) Variables\n"); + + for (num_mods = 1; num_mods <= MAX_MODS; num_mods *= 2) + test_lcore_var_access_n(num_mods); + + return TEST_SUCCESS; +} + +static struct unit_test_suite lcore_var_testsuite = { + .suite_name = "lcore variable perf autotest", + .unit_test_cases = { + TEST_CASE(test_lcore_var_access), + TEST_CASES_END() + }, +}; + +static int +test_lcore_var_perf(void) +{ + return unit_test_suite_runner(&lcore_var_testsuite); +} + +REGISTER_PERF_TEST(lcore_var_perf_autotest, test_lcore_var_perf); -- 2.43.0