【趣话编程】内存疯狂换页!CPU怒批OS

简介: 本文主要为大家讲解CPU与操作系统之间的故事。

原文链接

内存访问瓶颈

我是CPU一号车间的阿Q,前一阵子我们厂里发生了一件大喜事,老板拉到了一笔投资,准备扩大生产规模。
不过老板挺抠门的,拉到了投资也不给我们涨点工资,就知道让我们拼命干活,压榨我们的劳动力。
老板说了,投资的钱要用来添置设备,招聘新员工,咱们原来就有八个车间了,这一下直接double,变成了十六个!我们的工资要是也能double就好了···
image.png
现在我们变成了一个16核的CPU啦!
原以为我们生产效率也能double,没想到却遇到了新的问题。
我们CPU里面各个车间访问内存都要通过内存控制器和总线系统,有时候碰到几个车间都要访问内存,就得要竞争。
image.png
以前我们八个车间的时候竞争情况还不是很激烈,大家互相谦让一下也就罢了。现在变成了十六个车间都要过独木桥,这竞争一下就激烈了,尤其是我们这帮老员工基本不会让着新来的,为了此事经常发生不愉快。
内存访问出现了瓶颈,这性能自然是折损严重。

NUMA架构

老板把这一切都看在眼里,私下里找了我、二号车间的虎子还有总线主任开了个小会。
image.png
“你们几个都是厂里的核心员工,对厂里目前的问题你们怎么看?”,老板问我们几个。
我和虎子互相瞅了瞅,都没说话。
这时总线主任开口了:“老板,现在的问题是访问内存的路只有一条,大家都要来挤,难免会发生摩擦,影响工作性能。要想从根本解决问题,最好再建一条路”
“再建一条路,什么意思?”
“我建议把新扩建的那8个车间独立出去,建一个分厂。然后再把内存分一下,让两个厂各管理一部分。一来可以减少新老员工之间的矛盾,二来可以减少大家访问内存拥挤造成的资源浪费。再说了,万一以后继续扩大规模还可以继续用这个办法”,总线主任继续说到。
image.png
领导正低头思索,我倒是想到了一个问题:“主任,要是我们一号核执行的线程要访问的内存页面不在我们厂管理的内存上,在他们分厂怎么办呢?”
“嗯,这样的话,两个厂之间需要通信,如果访问的内存不在自己管辖的范围,就要互相帮忙传递一下”
老板拍了下桌子:“好主意!就这么办!”
第二天,老板召集16个车间的代表,总线主任,还有操作系统那边负责内存管理的代表小李,一起开了一个大会,会上正式通过了新的技术方案。
image.png
还给这项技术取了一个名字:NUMA(Non Uniform Memory Access),非一致性内存访问。
image.png
现有的16个车间拆分成两个CPU工厂,叫做两个NUMA节点(Node),每个节点直接连接一部分内存,两个节点之间有专门的的inter-connect通道。各节点直接访问自己管理的内存叫Local Access,通过inter-connect通道访问其他分厂管理的内存叫做Remote Access。很显然,前者的访问速度要比后者快得多,所以这也是这项技术名字的由来:非一致性内存访问。
新的组织架构调整过后,厂里的工作效率提升不少,矛盾摩擦也少了很多,又可以愉快的干活了。

操作系统支持

我们的组织架构调整了,操作系统那边可忙坏了。为了支持我们新的架构,操作系统不得不配合着做一些调整。
首先是缓存的问题,操作系统的进程&线程调度管理部门需要注意尽量不要跨NUMA节点进行调度线程,不能让一个线程一会儿在隔壁分厂运行,一会儿又在我们厂运行,这样建立的缓存就失效了。
image.png
还有就是内存亲和性的问题了,为了能得到更快的内存访问速度,操作系统的内存管理部门制定了一个内存分配策略,线程在哪个NUMA节点内执行,那就把内存分配到那个节点直接连接的内存中,避免跨节点的内存访问。
还别说,操作系统这么一优化调整,工作效率真是提升了不少呢。
然而好景不长,就因为这个调整,新的问题又双叒叕出现了~~~

MySQL的问题

最近一段时间,发生了一件怪事,不知道怎么回事,我们分厂管辖的内存很快耗光了,但隔壁分厂管理的内存还有很多空间。
操作系统不去分配那边的内存页面,却让我们一个劲的把内存页面swap到硬盘上去,腾挪空间。我们花了大量时间在这上边,搞得我们业绩下滑,还比不上隔壁分厂那帮新人。
image.png
终于有一天,忍不了了,我伙同厂里几个老家伙,把操作系统内存管理部门的小李又叫来了。
“你们怎么回事,就不能分配隔壁二号节点分厂管辖的内存吗,明明还有那么多空间,却让我们忙个不停”,我有点生气。
小李满脸无辜的说到:“不瞒你们各位,前几天有人来我们Linux帝国开设了一家新公司,叫MySQL,这家伙是个吃内存大户啊,一上来就要吃掉几十G,你们厂管辖的内存大半都被它给吃掉了”
image.png
虎子问到:“这跟我们有什么关系,你别推卸责任啊”
“上次我来开会,你们不是搞了个什么NUMA架构吗,访问本地连接的内存要比访问远程内存快一些嘛,所以我们制定了内存亲和性策略嘛,线程在哪个NUMA节点执行,就把内存分配到哪个节点直接连接的内存,想着这样能提升性能嘛”,小李继续委屈的说到。
“那也不能死脑筋啊,访问远程内存虽然比不上访问本地内存快,那也比一个劲的把页面从内存和硬盘上换来换去的强啊,你真是好心办坏事!”
被我们这样一说,小李也意识到了这样做的问题,“我回去反馈一下大家的意见,调整一下我们的策略”
过了几天,操作系统那边上了新的内存分配策略,将内存均匀的分配到各个NUMA节点,我们再也不用坑次坑次的把数据从内存和硬盘之间搬来搬去了。
NUMA虽好,可要是用得不好,只会徒增烦恼啊~

彩蛋

Linux帝国最近又来了一家公司,发布了一项工程招标。
“听说了吗,我们厂居然没中标”
“怎么可能,除了我们还有谁干这活”
“听说是一家叫GPU的工厂”
预知后事如何,请关注后续精彩······

来源 | 编程技术宇宙
作者 | 轩辕之风

相关文章
|
15天前
|
弹性计算 Kubernetes Perl
k8s 设置pod 的cpu 和内存
在 Kubernetes (k8s) 中,设置 Pod 的 CPU 和内存资源限制和请求是非常重要的,因为这有助于确保集群资源的合理分配和有效利用。你可以通过定义 Pod 的 `resources` 字段来设置这些限制。 以下是一个示例 YAML 文件,展示了如何为一个 Pod 设置 CPU 和内存资源请求(requests)和限制(limits): ```yaml apiVersion: v1 kind: Pod metadata: name: example-pod spec: containers: - name: example-container image:
100 1
|
24天前
|
存储 关系型数据库 MySQL
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
查询服务器CPU、内存、磁盘、网络IO、队列、数据库占用空间等等信息
203 2
|
1月前
|
分布式计算 算法 大数据
探索操作系统的核心:调度与内存管理机制
【10月更文挑战第11天】 本文深入探讨了操作系统中两大核心功能——调度与内存管理机制。通过分析调度算法、进程状态转换及内存分配策略等关键方面,揭示了它们如何共同维护系统性能和稳定性。旨在为读者提供对操作系统内部运作的深刻理解,同时引起对优化策略的思考。
64 5
|
1月前
|
算法
深入理解操作系统:内存管理机制的探索之旅
【10月更文挑战第2天】在数字世界的浩瀚海洋中,操作系统犹如一艘精密的航船,承载着软件与硬件的和谐共舞。本文将揭开内存管理的神秘面纱,从基础概念到高级策略,引领读者领略操作系统内存分配的智慧。通过深入浅出的解释和生动的比喻,我们一同遨游在内存的江河之中,感受操作系统如何巧妙地协调资源,确保数据的有序流动。让我们跟随内存的脚步,探索那些隐藏在每次点击、每次命令背后的奥秘。
|
1月前
|
监控 开发者
深入理解操作系统:内存管理的艺术
【10月更文挑战第2天】在数字世界的幕后,操作系统扮演着至关重要的角色。本文将深入探索操作系统的心脏——内存管理,揭示它是如何协调和管理计算机的宝贵资源。通过浅显易懂的语言和生活化的比喻,我们将一起走进内存管理的奥秘世界,了解它的原理、机制以及为何对整个系统的性能和稳定性有着不可替代的影响。无论你是技术新手还是资深开发者,这篇文章都将为你打开新的视角,让你对日常使用的设备有更深层次的认识和尊重。
|
1月前
|
缓存 算法 调度
深入浅出操作系统:从进程管理到内存优化
本文旨在为读者提供一次深入浅出的操作系统之旅。我们将从进程管理的基本概念出发,逐步深入到内存管理的复杂世界,最终探索如何通过实践技巧来优化系统性能。文章将结合理论与实践,通过代码示例,帮助读者更好地理解操作系统的核心机制及其在日常技术工作中的重要性。无论你是初学者还是有一定经验的开发者,这篇文章都将为你打开一扇通往操作系统深层次理解的大门。
|
1月前
|
IDE 开发工具 Android开发
探索移动应用开发之旅:理解移动操作系统与编程实践
【9月更文挑战第36天】在数字化时代的浪潮中,移动应用成为连接用户与数字世界的桥梁。本文将深入探讨移动应用开发的精髓,从移动操作系统的工作原理到实际编程实践,旨在为读者提供一条清晰的道路,以理解和掌握移动应用的开发过程。我们将通过具体示例,揭示如何在不断变化的技术环境中保持应用的性能、安全性和用户体验。无论你是初学者还是有经验的开发者,本文都将为你打开一扇窗,让你一窥移动应用开发的精彩世界。
|
1月前
|
安全 测试技术 数据库
Python编程--sys模块及OS模块简单用例
Python编程--sys模块及OS模块简单用例
|
1月前
|
运维 JavaScript Linux
容器内的Nodejs应用如何获取宿主机的基础信息-系统、内存、cpu、启动时间,以及一个df -h的坑
本文介绍了如何在Docker容器内的Node.js应用中获取宿主机的基础信息,包括系统信息、内存使用情况、磁盘空间和启动时间等。核心思路是将宿主机的根目录挂载到容器,但需注意权限和安全问题。文章还提到了使用`df -P`替代`df -h`以获得一致性输出,避免解析错误。
|
1月前
|
算法 调度 UED
探索操作系统中的多线程编程
【8月更文挑战第78天】在数字世界的复杂迷宫中,操作系统扮演着至关重要的角色。本文旨在揭开操作系统中多线程编程的神秘面纱,引导读者理解其概念、实现及应用。通过深入浅出的方式,我们将探讨如何在程序设计中运用多线程,以及这一技术如何优化软件性能和提升用户体验。文章将结合具体代码示例,展示多线程在实际应用中的魔力。无论你是编程新手还是资深开发者,这篇文章都将为你提供新的视角和思考路径。
下一篇
无影云桌面