From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from sg-1-104.ptr.blmpb.com (sg-1-104.ptr.blmpb.com [118.26.132.104]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6525428CF5F for ; Thu, 5 Mar 2026 07:01:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=118.26.132.104 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772694107; cv=none; b=Ft4B0pF83817coHUukib/TiZG3kuPCBJItVX27GoXUNLI1i58JWYXuNOW4ZaYHUAQM3NguEwUhwhQ2rjN3WNhVLiz6IfhbE5G/+QealFW4Ojeq1r/JISZ0cpS2LELwORR0IuVKPUjsf4UdIEA3h1lg1l2ZKx+PSLDjqgnhmhAs4= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1772694107; c=relaxed/simple; bh=WdFVX4dDIMosdUX3Pd26zpTFSsQd3++5G6XBU/pJj3U=; h=Cc:From:Date:Subject:Mime-Version:References:To:Message-Id: In-Reply-To:Content-Type; b=DxwA2wQkN7xzTRMX/mcv7HBqEHD0crefs0GYg110h1kWC9nOyGLm0IAPGpI7PRM5LO4PN7UiQE8LoixEExQwPqKFXEKC02UDxqmfDO/sFJE+3sf3isSEdDzQZXZEyuNtGkQi7+loPaCMWdNOCkuSFIvO62ap4o/xBEWzKhb3vLw= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com; spf=pass smtp.mailfrom=bytedance.com; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b=V+0Zjkfw; arc=none smtp.client-ip=118.26.132.104 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=bytedance.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bytedance.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bytedance.com header.i=@bytedance.com header.b="V+0Zjkfw" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; s=2212171451; d=bytedance.com; t=1772694098; h=from:subject: mime-version:from:date:message-id:subject:to:cc:reply-to:content-type: mime-version:in-reply-to:message-id; bh=sCyyfZ528KylDpj4ms+Cx9pXPX0Qm9zfD6qNv5bZ9cQ=; b=V+0ZjkfwvHS0nJIzCQ1gnMr82x23kMCjbZ2WVo49wKemMjZ86TTn29YSGmVdOTGp7AYmJO MHAEICRG+l8ZW1iMTIaterhVBusMaSge2g25Y7An9CoUZ1059tIBSSx1MXF9tWz+3mFH+y K/iemcjpr8GMt0xdofuCJ/Yj1kBtbJLV5dIlHcOLymo5L2SBlxwicHqUm/cMRJvrBebQo0 AFEkICV+I/yqNS3CxyNjeXcadao2oeLojeFFnPt2OqNIOIF3jzv+bVQ7AxoqvpC9n9kaGK 3K3wuE2OpSV/c2vlaLtzZoanxkYP7QjYeGMr4Hvnh7mp5sbBmF/NZbaaZvtP5g== X-Lms-Return-Path: Cc: , , , , , , , , , , , From: "Chuyi Zhou" Date: Thu, 5 Mar 2026 15:01:19 +0800 X-Original-From: Chuyi Zhou Subject: Re: [PATCH v2 10/12] x86/mm: Move flush_tlb_info back to the stack Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20260302075216.2170675-1-zhouchuyi@bytedance.com> <20260302075216.2170675-11-zhouchuyi@bytedance.com> <20260302145848.GI1395266@noisy.programming.kicks-ass.net> To: "Peter Zijlstra" Message-Id: <1aeb64e0-97bb-4b25-a0b7-435240dfbbd3@bytedance.com> Content-Transfer-Encoding: quoted-printable In-Reply-To: <20260302145848.GI1395266@noisy.programming.kicks-ass.net> Content-Type: text/plain; charset=UTF-8 User-Agent: Mozilla Thunderbird Hi Peter, =E5=9C=A8 2026/3/2 22:58, Peter Zijlstra =E5=86=99=E9=81=93: > On Mon, Mar 02, 2026 at 03:52:14PM +0800, Chuyi Zhou wrote: >> Commit 3db6d5a5ecaf ("x86/mm/tlb: Remove 'struct flush_tlb_info' from th= e >> stack") converted flush_tlb_info from stack variable to per-CPU variable= . >> This brought about a performance improvement of around 3% in extreme tes= t. >> However, it also required that all flush_tlb* operations keep preemption >> disabled entirely to prevent concurrent modifications of flush_tlb_info. >> flush_tlb* needs to send IPIs to remote CPUs and synchronously wait for >> all remote CPUs to complete their local TLB flushes. The process could >> take tens of milliseconds when interrupts are disabled or with a large >> number of remote CPUs. >> >> From the perspective of improving kernel real-time performance, this pa= tch >> reverts flush_tlb_info back to stack variables. This is a preparation fo= r >> enabling preemption during TLB flush in next patch. >=20 > This isn't properly justified. You've got to show that 'most' workloads > are not adversely affected by this. >=20 > Most people still swing towards performance most of the time. I attempted to reproduce the microbenchmark mentioned in Commit=20 3db6d5a5ecaf ("x86/mm/tlb: Remove 'struct flush_tlb_info' from the=20 stack") using the script below. The baseline was tip/sched/core: f74d204baf9f (sched/hrtick: Mark hrtick_clear() as always used). The test environment was an Ice Lake system (Intel(R) Xeon(R) Platinum 8336C) with 128 CPUs and 2 NUMA nodes. Using the per-CPU flush_tlb_info showed only a very marginal performance advantage, approximately 1%. base on-stack ---- --------- avg (usec/op) 5.9362 5.9956 (+1%) stddev 0.0240 0.0096 I also tested with mmtest/stress-ng-madvise, which randomly calls=20 madvise on pages within a mmap range and triggers a large number of=20 high-frequency TLB flushes. However, I did not observe any significant=20 difference. baseline on-stack Amean bops-madvise-1 13.64 ( 0.00%) 13.56 ( 0.59%) Amean bops-madvise-2 27.32 ( 0.00%) 27.26 ( 0.24%) Amean bops-madvise-4 53.35 ( 0.00%) 53.54 ( -0.35%) Amean bops-madvise-8 103.09 ( 0.00%) 103.30 ( -0.20%) Amean bops-madvise-16 191.88 ( 0.00%) 191.75 ( 0.07%) Amean bops-madvise-32 287.98 ( 0.00%) 291.01 * -1.05%* Amean bops-madvise-64 365.84 ( 0.00%) 368.09 * -0.61%* Amean bops-madvise-128 422.72 ( 0.00%) 423.47 ( -0.18%) Amean bops-madvise-256 435.61 ( 0.00%) 435.63 ( -0.01%) Thanks. #define _GNU_SOURCE #include #include #include #include #include #include #define NUM_OPS 1000000 #define NUM_THREADS 3 #define NUM_RUNS 5 #define PAGE_SIZE 4096 volatile int stop_threads =3D 0; void *busy_wait_thread(void *arg) { while (!stop_threads) { __asm__ volatile ("nop"); } return NULL; } long long get_usec() { struct timeval tv; gettimeofday(&tv, NULL); return tv.tv_sec * 1000000LL + tv.tv_usec; } int main() { pthread_t threads[NUM_THREADS]; char *addr; int i, r; addr =3D mmap(NULL, PAGE_SIZE, PROT_READ | PROT_WRITE, MAP_PRIVATE |= =20 MAP_ANONYMOUS, -1, 0); if (addr =3D=3D MAP_FAILED) { perror("mmap"); exit(1); } for (i =3D 0; i < NUM_THREADS; i++) { if (pthread_create(&threads[i], NULL, busy_wait_thread, NULL)=20 !=3D 0) { perror("pthread_create"); exit(1); } } printf("Running benchmark: %d runs, %d ops each, %d background=20 threads\n", NUM_RUNS, NUM_OPS, NUM_THREADS); for (r =3D 0; r < NUM_RUNS; r++) { long long start, end; start =3D get_usec(); for (i =3D 0; i < NUM_OPS; i++) { addr[0] =3D 1; if (madvise(addr, PAGE_SIZE, MADV_DONTNEED) !=3D 0) { perror("madvise"); exit(1); } } end =3D get_usec(); double duration =3D (double)(end - start); double avg_lat =3D duration / NUM_OPS; printf("Run %d: Total time %.2f us, Avg latency %.4f us/op\n",=20 r + 1, duration, avg_lat); } stop_threads =3D 1; for (i =3D 0; i < NUM_THREADS; i++) { pthread_join(threads[i], NULL); } munmap(addr, PAGE_SIZE); return 0; }