numa_balancing扫描间隔调整
1. numa_next_scan2. numa_scan_period相关代码分析3. 线程迁移的周期1. numa_next_scan扫描是针对内存进行的为了保证每次只有一个线程对内存进行扫描使用mm_struct中的numa_next_scan作为控制变量。线程扫描周期的控制变量numa_scan_period要作用到numa_next_scan上来影响扫描的周期。这个过程可以参考函数task_numa_work在task_numa_work这个函数中会先比较当前时间now和numa_next_scan只有当前时间now晚于numa_next_scan才会执行后面的流程。在下一步更新numa_next_scan下一次的numa_next_scan定义为now numa_scan_period下一次的扫描时间由numa_scan_period决定存储在numa_next_scan中。| | | | --- | --- | | 1 | // cmpxchg的函数的作用它的入参是一个指向要操作的变量的指针、期望值和新值返回值是操作前的变量值。 | | 2 | // 在这里它比较numa_next_scan的当前值和migrate这个值如果相等则修改为next_scan, 否则直接return, 但是问题是numa_scan_period的取值为什么会小于1000 | | 3 | // 这里的操作可以保证对于一个mm结构体, 同一时间只有一个线程来修改 | | 4 | migrate mm-numa_next_scan; | | 5 | if (time_before(now, migrate)) | | 6 | return; | | 7 | next_scan now msecs_to_jiffies(p-numa_scan_period); | | 8 | if (cmpxchg(mm-numa_next_scan, migrate, next_scan) ! migrate) | | 9 | return; |影响task-numa_scan_period的有三个函数- task_tick_numacurr-numa_scan_period task_scan_start(curr) - update_scan_period: curr-numa_scan_period task_scan_start(curr) - update_task_scan_period: curr-numa_scan_period clamp(curr-numa_scan_period diff, task_scan_min(curr), task_scan_max(curr))task_tick_numa这个函数中的numa_scan_period只有在numa_balancing特性初次运行的时候才会生效 update_scan_period: 这个函数中的numa_scan_period要更新需要等到任务所在的node发生改变时才会产生也就是任务发生跨node的迁移时才会被调用 update_task_scan_period: 这个函数在task_numa_placement函数中被调用task_numa_placement可以认为在很频繁地被调用所以numa_scan_period很快就会增长2. numa_scan_period相关代码分析在使能numa balancing特性进行第一次扫描或者线程发生跨node迁移后会调用函数task_scan_start来设置numa_scan_period的值我们来看一下task_scan_start函数的调用流程| | | | --- | --- | | 1 | // 扫描时间由两个值中的最大值决定 max(min, period) | | 2 | // min rss / nr_scan_pages | | 3 | // period: 由min和private和share内存的比例决定 | | 4 | task_scan_start | | 5 | - task_scan_min | | 6 | // 扫描的最小时间为 rss / nr_scan_pages, 其中rss为进程总共使用的物理内存大小, nr_scan_pages为单次扫描的物理内存大小 | | 7 | - task_nr_scan_windows || | | | --- | --- | | 1 | static inline unsigned long group_faults_priv(struct numa_group *ng); | | 2 | static inline unsigned long group_faults_shared(struct numa_group *ng); | | 3 | | | 4 | // rss代表总共使用的物理内存总共使用的物理内存的大小决定了task_nr_scan_windows的大小使用的物理内存越多扫描的越快 | | 5 | static unsigned int task_nr_scan_windows(struct task_struct *p) | | 6 | { | | 7 | unsigned long rss 0; | | 8 | unsigned long nr_scan_pages; | | 9 | | | 10 | /* | | 11 | * Calculations based on RSS as non-present and empty pages are skipped | | 12 | * by the PTE scanner and NUMA hinting faults should be trapped based | | 13 | * on resident pages | | 14 | */ | | 15 | nr_scan_pages sysctl_numa_balancing_scan_size (20 - PAGE_SHIFT); | | 16 | rss get_mm_rss(p-mm); | | 17 | if (!rss) | | 18 | rss nr_scan_pages; | | 19 | | | 20 | rss round_up(rss, nr_scan_pages); | | 21 | return rss / nr_scan_pages; | | 22 | } | | 23 | | | 24 | // 由2560这个值可以推断出, 一次扫描的最短时间是100ms | | 25 | /* For sanitys sake, never scan more PTEs than MAX_SCAN_WINDOW MB/sec. */ | | 26 | #define MAX_SCAN_WINDOW 2560 | | 27 | | | 28 | static unsigned int task_scan_min(struct task_struct *p) | | 29 | { | | 30 | unsigned int scan_size READ_ONCE(sysctl_numa_balancing_scan_size); | | 31 | unsigned int scan, floor; | | 32 | unsigned int windows 1; | | 33 | | | 34 | if (scan_size MAX_SCAN_WINDOW) | | 35 | windows MAX_SCAN_WINDOW / scan_size; | | 36 | floor 1000 / windows; | | 37 | | | 38 | scan sysctl_numa_balancing_scan_period_min / task_nr_scan_windows(p); | | 39 | return max_t(unsigned int, floor, scan); | | 40 | } | | 41 | | | 42 | // 对于group shared 和private分别指的是什么 | | 43 | static unsigned int task_scan_start(struct task_struct *p) | | 44 | { | | 45 | unsigned long smin task_scan_min(p); | | 46 | unsigned long period smin; | | 47 | struct numa_group *ng; | | 48 | | | 49 | /* Scale the maximum scan period with the amount of shared memory. */ | | 50 | rcu_read_lock(); | | 51 | ng rcu_dereference(p-numa_group); | | 52 | if (ng) { | | 53 | unsigned long shared group_faults_shared(ng); | | 54 | unsigned long private group_faults_priv(ng); | | 55 | | | 56 | period * refcount_read(ng-refcount); | | 57 | period * shared 1; | | 58 | period / private shared 1; | | 59 | } | | 60 | rcu_read_unlock(); | | 61 | | | 62 | return max(smin, period); | | 63 | } | | 64 | | | 65 | static unsigned int task_scan_max(struct task_struct *p) | | 66 | { | | 67 | unsigned long smin task_scan_min(p); | | 68 | unsigned long smax; | | 69 | struct numa_group *ng; | | 70 | | | 71 | /* Watch for min being lower than max due to floor calculations */ | | 72 | smax sysctl_numa_balancing_scan_period_max / task_nr_scan_windows(p); | | 73 | | | 74 | /* Scale the maximum scan period with the amount of shared memory. */ | | 75 | ng deref_curr_numa_group(p); | | 76 | if (ng) { | | 77 | unsigned long shared group_faults_shared(ng); | | 78 | unsigned long private group_faults_priv(ng); | | 79 | unsigned long period smax; | | 80 | | | 81 | period * refcount_read(ng-refcount); | | 82 | period * shared 1; | | 83 | period / private shared 1; | | 84 | | | 85 | smax max(smax, period); | | 86 | } | | 87 | | | 88 | return max(smin, smax); | | 89 | } |numa_faults_locality[3]作为数组总共存储了3个元素第一个元素代表remote访问的pages数第二个元素代表local访问的pages数第三个元素代表迁移失败的pages数目。update_task_scan_period函数中对于numa_scan_period的更新有两种方式完全没有有效的fault访问此时任务完全处于idle状态或是所有的内存访问区域都属于不能进行numa balancing操作的的区域。或者是内存迁移失败此时要么是内存迁移太过频繁或是内存要迁去的node已经负载过重此时直接将numa_scan_period的时间设置为原来的两倍当被local/ (local remote) 70% 或是 private / (private shared) 70%此时按照比例将numa_scan_period调大最大调大的幅度为原来的30%。否则要按比例降低numa_scan_period加快扫描。| | | | --- | --- | | 1 | // 该函数在task_numa_placement函数中被调用用于更新numa_scan_period, 根据本地访存的比例, 调整扫描的周期 | | 2 | /* | | 3 | * Increase the scan period (slow down scanning) if the majority of | | 4 | * our memory is already on our local node, or if the majority of | | 5 | * the page accesses are shared with other processes. | | 6 | * Otherwise, decrease the scan period. | | 7 | */ | | 8 | static void update_task_scan_period(struct task_struct *p, | | 9 | unsigned long shared, unsigned long private) | | 10 | { | | 11 | unsigned int period_slot; | | 12 | int lr_ratio, ps_ratio; | | 13 | int diff; | | 14 | | | 15 | unsigned long remote p-numa_faults_locality[0]; | | 16 | unsigned long local p-numa_faults_locality[1]; | | 17 | | | 18 | /* | | 19 | * If there were no record hinting faults then either the task is | | 20 | * completely idle or all activity is areas that are not of interest | | 21 | * to automatic numa balancing. Related to that, if there were failed | | 22 | * migration then it implies we are migrating too quickly or the local | | 23 | * node is overloaded. In either case, scan slower | | 24 | */ | | 25 | if (local shared 0 || p-numa_faults_locality[2]) { | | 26 | p-numa_scan_period min(p-numa_scan_period_max, | | 27 | p-numa_scan_period 1); | | 28 | | | 29 | p-mm-numa_next_scan jiffies | | 30 | msecs_to_jiffies(p-numa_scan_period); | | 31 | | | 32 | return; | | 33 | } | | 34 | | | 35 | /* | | 36 | * Prepare to scale scan period relative to the current period. | | 37 | * NUMA_PERIOD_THRESHOLD scan period stays the same | | 38 | * NUMA_PERIOD_THRESHOLD scan period decreases (scan faster) | | 39 | * NUMA_PERIOD_THRESHOLD scan period increases (scan slower) | | 40 | */ | | 41 | period_slot DIV_ROUND_UP(p-numa_scan_period, NUMA_PERIOD_SLOTS); | | 42 | lr_ratio (local * NUMA_PERIOD_SLOTS) / (local remote); | | 43 | ps_ratio (private * NUMA_PERIOD_SLOTS) / (private shared); | | 44 | | | 45 | if (ps_ratio NUMA_PERIOD_THRESHOLD) { | | 46 | /* | | 47 | * Most memory accesses are local. There is no need to | | 48 | * do fast NUMA scanning, since memory is already local. | | 49 | */ | | 50 | int slot ps_ratio - NUMA_PERIOD_THRESHOLD; | | 51 | if (!slot) | | 52 | slot 1; | | 53 | diff slot * period_slot; | | 54 | } else if (lr_ratio NUMA_PERIOD_THRESHOLD) { | | 55 | /* | | 56 | * Most memory accesses are shared with other tasks. | | 57 | * There is no point in continuing fast NUMA scanning, | | 58 | * since other tasks may just move the memory elsewhere. | | 59 | */ | | 60 | int slot lr_ratio - NUMA_PERIOD_THRESHOLD; | | 61 | if (!slot) | | 62 | slot 1; | | 63 | diff slot * period_slot; | | 64 | } else { | | 65 | /* | | 66 | * Private memory faults exceed (SLOTS-THRESHOLD)/SLOTS, | | 67 | * yet they are not on the local NUMA node. Speed up | | 68 | * NUMA scanning to get the memory moved over. | | 69 | */ | | 70 | int ratio max(lr_ratio, ps_ratio); | | 71 | diff -(NUMA_PERIOD_THRESHOLD - ratio) * period_slot; | | 72 | } | | 73 | | | 74 | p-numa_scan_period clamp(p-numa_scan_period diff, | | 75 | task_scan_min(p), task_scan_max(p)); | | 76 | memset(p-numa_faults_locality, 0, sizeof(p-numa_faults_locality)); | | 77 | } |3. 线程迁移的周期线程迁移的最短时间由numa_migrate_retry决定在函数task_numa_fault函数中根据numa_migrate_retry的取值确定是否要调用task_numa_placement和函数numa_migrate_preferred来执行线程迁移。| | | | --- | --- | | 1 | /* | | 2 | * Retry to migrate task to preferred node periodically, in case it | | 3 | * previously failed, or the scheduler moved us. | | 4 | */ | | 5 | if (time_after(jiffies, p-numa_migrate_retry)) { | | 6 | task_numa_placement(p); | | 7 | numa_migrate_preferred(p); | | 8 | } |numa_migrate_retry的取值在函数中numa_migrate_preferred中被修改被定义为内存扫描周期的1/16| | | | --- | --- | | 1 | /* Periodically retry migrating the task to the preferred node */ | | 2 | interval min(interval, msecs_to_jiffies(p-numa_scan_period) / 16); | | 3 | p-numa_migrate_retry jiffies interval; |

相关新闻

32*32音频处理器常见误区:独立AEC通道数量影响会议效果

32*32音频处理器常见误区:独立AEC通道数量影响会议效果

32*32音频处理器选型指南:解析独立AEC通道与算力架构的关键作用在构建中大型会议室、多功能厅或指挥中心的音视频系统时,32*32音频处理器通常作为核心信号处理节点存在。然而,许多系统集成商和用户在设备筛选过程中,容易陷入“通道…

2026/8/11 2:01:53 阅读更多 →
C++ string优化技术:SBO与COW原理与性能对比

C++ string优化技术:SBO与COW原理与性能对比

1. 揭开C string的神秘面纱在C开发者的日常工作中,string可能是最熟悉却又最陌生的伙伴。作为标准库中最常用的容器之一,它的内部实现机制直接影响着程序性能和内存使用效率。今天我们就来深入探讨现代C string实现中的两大核心技术:SBO&…

2026/8/11 2:01:53 阅读更多 →
AS3.0项目集成Starling框架:GPU硬件加速优化2D渲染性能实战

AS3.0项目集成Starling框架:GPU硬件加速优化2D渲染性能实战

在Flash/ActionScript 3.0项目后期,尤其是涉及复杂动画、粒子效果或大型游戏时,你是否遇到过性能瓶颈?CPU占用率飙升,帧率却持续走低,复杂的显示列表让渲染线程不堪重负。这正是传统Flash Player基于CPU的矢量渲染在面…

2026/8/11 2:01:53 阅读更多 →

最新新闻

前后端Bug定位实战:从数据流分析到工具链排查

前后端Bug定位实战:从数据流分析到工具链排查

1. 项目概述:从“甩锅”到“定位”的测试进阶之路在软件测试这个行当里干了十几年,最常听到的对话场景之一就是:“这个页面显示不对,是不是前端的问题?”“不对啊,我接口返回的数据是好的,肯定是…

2026/8/11 4:00:43 阅读更多 →
AI Agent智能体架构在企业业务系统中的设计与实践

AI Agent智能体架构在企业业务系统中的设计与实践

一、项目背景与AI Agent定位1.1 业务背景与项目规模随着大语言模型能力的快速演进,企业智能化转型正从“对话引擎”走向“数字员工”的新范式。我所在团队负责设计并交付了一套企业级AI Agent智能化业务平台,目标是将大模型的推理能力与企业现有业务系统…

2026/8/11 4:00:43 阅读更多 →
SpringBoot项目中logback日志配置详解与最佳实践

SpringBoot项目中logback日志配置详解与最佳实践

1. SpringBoot项目中自定义logback日志配置的必要性在SpringBoot项目开发中,日志系统是必不可少的基础组件。虽然SpringBoot默认集成了logback作为日志框架,并且提供了开箱即用的配置,但在实际企业级应用中,默认配置往往无法满足复…

2026/8/11 4:00:43 阅读更多 →
C++实现耳切法:高效多边形三角化算法详解与实战

C++实现耳切法:高效多边形三角化算法详解与实战

1. 项目概述与核心价值最近在做一个游戏引擎的2D物理碰撞检测模块,需要处理任意凸多边形和凹多边形的碰撞形状。一个最基础的需求,就是把用户绘制的复杂多边形分解成一系列三角形,因为无论是GPU渲染还是物理引擎的碰撞计算,三角形…

2026/8/11 4:00:43 阅读更多 →
阶梯式碳交易与电制氢协同优化方案解析

阶梯式碳交易与电制氢协同优化方案解析

1. 项目背景与核心价值在能源结构转型的大背景下,如何实现高比例可再生能源消纳与深度减排目标,成为电力系统领域亟待解决的难题。我们团队提出的"阶梯式碳交易机制电制氢"协同优化方案,正是针对这一痛点的创新实践。不同于传统单一…

2026/8/11 4:00:43 阅读更多 →
核心期刊论文AI写作工具测评:5款实测打分

核心期刊论文AI写作工具测评:5款实测打分

核心期刊发表门槛逐年抬高,从选题创新性到文献引用规范,每一环都卡得人头疼。市面宣称能辅助论文写作的AI工具少说几十款,真正适配核心期刊场景的没几个。这次我以一篇经管类实证论文初稿片段为样本,统一指令和迭代轮次&#xff0…

2026/8/11 3:59:43 阅读更多 →

日新闻

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南

如何用Video2X实现专业级视频画质提升:AI视频增强完整指南 【免费下载链接】video2x A machine learning-based video super resolution and frame interpolation framework. Est. Hack the Valley II, 2018. 项目地址: https://gitcode.com/GitHub_Trending/vi/v…

2026/8/11 0:00:02 阅读更多 →
前后端分离项目中控制台与接口工具数据差异排查指南

前后端分离项目中控制台与接口工具数据差异排查指南

1. 问题现象解析:控制台与Apifox的数据差异 最近在调试一个前后端分离项目时,遇到了一个典型问题:后端服务在本地开发环境控制台能正常输出查询数据,但通过Apifox测试时却返回空结果。这种"控制台有数据,接口工具…

2026/8/11 0:00:03 阅读更多 →
AI编程实战:从Claude Code踩坑到游戏开发入门

AI编程实战:从Claude Code踩坑到游戏开发入门

1. 从“AI能帮我做游戏”到“AI让我重新学编程”最近身边不少朋友,尤其是一些非技术背景、但对游戏开发有浓厚兴趣的朋友,都在问我同一个问题:“听说现在用Claude Code这种AI编程工具,小白也能做游戏了,是真的吗&#…

2026/8/11 0:00:03 阅读更多 →

周新闻

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁

5分钟告别提取码焦虑:baidupankey如何智能破解百度网盘资源锁 【免费下载链接】baidupankey 在线查询网盘提取码(维护中 rm repo) 项目地址: https://gitcode.com/gh_mirrors/ba/baidupankey 你是否曾经在深夜寻找一份重要资料&#x…

2026/8/11 1:08:05 阅读更多 →
如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南

如何快速生成中国车牌图片:Python开源工具完整指南 【免费下载链接】chinese_license_plate_generator 中国车牌生成器 项目地址: https://gitcode.com/gh_mirrors/ch/chinese_license_plate_generator 中国车牌生成器是一个基于Python的开源项目&#xff0c…

2026/8/11 1:08:05 阅读更多 →
收藏!小白程序员轻松入门大模型,从Harness工程开始实践

收藏!小白程序员轻松入门大模型,从Harness工程开始实践

文章强调学习大模型不应只关注模型本身,而应重视模型外的系统搭建,即Harness。提出AgentModelHarness的实用公式,详细介绍Harness的四个层次:持久化层、执行层、控制层和观察与验证层。文章还探讨了上下文工程、工具设计、AGENTS.…

2026/8/11 1:08:05 阅读更多 →

月新闻

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南

免费解锁百度网盘SVIP加速:macOS用户必备的下载提速终极指南 【免费下载链接】BaiduNetdiskPlugin-macOS For macOS.百度网盘 破解SVIP、下载速度限制~ 项目地址: https://gitcode.com/gh_mirrors/ba/BaiduNetdiskPlugin-macOS 还在为百度网盘macOS版的龟速下…

2026/8/10 17:07:33 阅读更多 →
终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换

终极ncmdump指南:3分钟实现网易云NCM音乐解密与格式转换 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 还在为网易云音乐下载的NCM格式文件无法在其他播放器播放而烦恼吗?ncmdump解密工具帮你轻松解决这个困…

2026/8/11 1:08:06 阅读更多 →
HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

HarmonyOS 应用开发《掌上英语》第81篇: 智能体卡片:为英语学习 App 打造桌面级学习助手

AgentCard 智能体卡片:为英语学习 App 打造桌面级学习助手适用平台:HarmonyOS 7.0 (API 26 Beta)一、引言 HarmonyOS 7.0(API 26 Beta)新增了 AgentCard 智能体卡片能力,这是继 HMAF(鸿蒙智能体框架&#x…

2026/8/10 17:07:33 阅读更多 →