为什么在 Windows 上创建新进程比在 Linux 上更昂贵?
- 2024-10-22 08:29:00
- admin 原创
- 69
问题描述:
我听说在 Windows 机器上创建新进程的成本比在 Linux 上更高。这是真的吗?有人能解释一下为什么成本更高,以及提供这些原因背后的设计决策的历史原因吗?
解决方案 1:
mweerden:NT 从第一天起就被设计为多用户,所以这不是真正的原因。但是,您说得对,进程创建在 NT 上的作用不如在 Unix 上重要,因为与 Unix 相比,NT 更倾向于多线程而不是多处理。
Rob,确实,使用 COW 时 fork 相对便宜,但事实上,fork 之后大多会执行 exec。而且 exec 还必须加载所有图像。因此,讨论 fork 的性能只是事实的一部分。
在讨论进程创建速度时,区分 NT 和 Windows/Win32 可能是一个好主意。就 NT(即内核本身)而言,我认为进程创建(NtCreateProcess)和线程创建(NtCreateThread)的速度不会比普通 Unix 慢很多。可能还存在一些其他问题,但我看不出这里性能差异的主要原因。
但是,如果您查看 Win32,就会发现它为进程创建增加了相当多的开销。首先,它要求将进程创建通知给 CSRSS,这涉及 LPC。它至少需要额外加载 kernel32,并且必须执行许多额外的簿记工作项目,然后才能将进程视为成熟的 Win32 进程。我们不要忘记解析清单、检查映像是否需要兼容性垫片、检查软件限制策略是否适用等所有额外开销。
话虽如此,我看到除了创建进程、VA 空间和初始线程之外,所有这些小事情的总和都会导致整体速度减慢。但正如开头所说——由于人们更倾向于多线程而不是多任务,唯一受到这种额外开销严重影响的软件是移植不良的 Unix 软件。尽管当 Chrome 和 IE8 等软件突然重新发现多处理的好处并开始频繁启动和拆除进程时,这种情况发生了变化……
解决方案 2:
补充一下 JP 所说的:大部分开销属于该过程的 Win32 启动。
Windows NT 内核实际上支持 COW fork。SFU ( Microsoft 的 Windows UNIX 环境)使用它们。但是,Win32 不支持 fork。SFU 进程不是 Win32 进程。SFU 与 Win32 正交:它们都是基于同一内核构建的环境子系统。
除了对 的进程外 LPC 调用之外CSRSS
,在 XP 及更高版本中,还会对应用程序兼容性引擎进行进程外调用,以在应用程序兼容性数据库中查找程序。此步骤会造成足够的开销,因此 Microsoft 提供了一个组策略选项来禁用 WS2003 上的兼容性引擎,以达到性能目的。
Win32 运行时库(kernel32.dll 等)在启动时也会执行大量注册表读取和初始化操作,这些操作不适用于 UNIX、SFU 或本机进程。
本机进程(没有环境子系统)创建速度非常快。SFU 在进程创建方面所做的工作比 Win32 少很多,因此其进程创建速度也很快。
2019 年更新:添加 LXSS:适用于 Linux 的 Windows 子系统
取代 Windows 10 的 SFU 的是 LXSS 环境子系统。它是 100% 内核模式,不需要 Win32 继续拥有的任何 IPC。这些进程的系统调用直接指向 lxss.sys/lxcore.sys,因此 fork() 或其他进程创建调用总共只需要创建者进行 1 次系统调用。[称为实例的数据区域] 跟踪所有 LX 进程、线程和运行时状态。
LXSS 进程基于本机进程,而不是 Win32 进程。所有 Win32 特有的东西(例如兼容引擎)都完全没有参与。
解决方案 3:
Unix 有一个“fork”系统调用,它将当前进程“拆分”为两个,并为您提供与第一个进程相同的第二个进程(对 fork 调用的返回值取模)。由于新进程的地址空间已经启动并运行,因此这应该比在 Windows 中调用“CreateProcess”并让其加载 exe 映像、相关 dll 等更便宜。
在 fork 情况下,操作系统可以对与两个新进程相关的内存页面使用“写时复制”语义,以确保每个进程都获得随后修改的页面的副本。
解决方案 4:
除了 Rob Walker 的回答之外:现在,如果您愿意,您可以使用 Native POSIX 线程库之类的东西。但长期以来,在 unix 世界中“委托”工作的唯一方法是使用 fork()(在很多情况下,它仍然是首选)。例如某种套接字服务器
socket_accept()
叉()
如果(子项)
处理请求()
别的
转到父类()
因此,fork 的实现必须快速,并且随着时间的推移,已经实现了许多优化。Microsoft 认可 CreateThread 甚至纤程,而不是创建新进程和使用进程间通信。我认为将 CreateProcess 与 fork 进行比较并不“公平”,因为它们不可互换。将 fork/exec 与 CreateProcess 进行比较可能更合适。
解决方案 5:
我认为,这个问题的关键在于这两个系统的历史用法。Windows(以及之前的 DOS)最初是个人电脑的单用户系统。因此,这些系统通常不必一直创建大量进程;(非常)简单地说,只有当这个孤独的用户请求时才会创建一个进程(相对而言,我们人类的操作速度不是很快)。
基于 Unix 的系统最初是多用户系统和服务器。特别是对于后者,将进程(例如邮件或 http 守护进程)拆分成处理特定任务(例如处理一个传入连接)的情况并不少见。这样做的一个重要因素是廉价的方法(如 Rob Walker ( 47865fork
)所述,该方法最初为新创建的进程使用相同的内存),这非常有用,因为新进程可以立即获得所需的所有信息。
显然,至少从历史上看,基于 Unix 的系统对快速进程创建的需求远高于 Windows 系统。我认为现在情况仍然如此,因为基于 Unix 的系统仍然非常面向进程,而 Windows 则由于其历史原因可能更加面向线程(线程对于制作响应式应用程序非常有用)。
免责声明:我绝不是这个问题的专家,所以如果我错了,请原谅我。
解决方案 6:
简短的回答是“软件层和组件”。
Windows SW 架构有几个额外的层和组件,这些层和组件在 Unix 上不存在,或者在 Unix 的内核中被简化和处理。
在 Unix 上,fork 和 exec 是直接调用内核。
在 Windows 上,内核 API 并不直接使用,而是在它之上有 win32 和某些其他组件,因此进程创建必须经过额外的层,然后新进程必须启动或连接到这些层和组件。
很长一段时间以来,研究人员和公司都试图以类似的方式拆分 Unix,通常以Mach 内核为基础进行实验;一个著名的例子就是OS X。然而,每次他们尝试时,速度都非常慢,最终他们不得不至少部分地将各个部分永久合并回内核或用于生产发布。
解决方案 7:
呃,似乎有很多“这样更好”之类的理由。
我认为阅读《Showstopper》这本关于 Windows NT 开发的书会对人们有益。
在 Windows NT 上,服务作为 DLL 在同一个进程中运行的原因是,作为单独的进程运行它们太慢了。
如果你认真研究一下,你就会发现库加载策略是一个问题。
在 Unices 上(一般来说),共享库(DLL)代码段实际上是共享的。
Windows NT 每个进程都加载 DLL 的一个副本,因为它在加载后会操作库代码段(和可执行代码段)。(告诉它你的数据在哪里?)
这会导致库中的代码段不可重用。
因此,NT 进程创建实际上非常昂贵。而不利的一面是,它不会显著节省 DLL 的内存,反而有可能引发应用程序间依赖性问题。
在工程设计中,有时我们需要退后一步,然后思考:“现在,如果我们要设计一个非常糟糕的产品,它会是什么样子?”
我曾经使用过一个嵌入式系统,它曾经非常不稳定,有一天我查看它时意识到它是一个腔体磁控管,电子元件位于微波腔体中。之后我们让它变得更加稳定(不再像微波炉)。
解决方案 8:
因为有些答案似乎对 MS-Windows 有所解释,例如
“NT 内核和 Win32 不是一回事。如果你针对 NT 内核编程,那就没那么糟糕了”——没错,但除非你正在编写 Posix 子系统,否则谁会在乎呢。你将针对 win32 进行编写。
“将 fork 与 ProcessCreate 进行比较是不公平的,因为它们的作用不同,而且 Windows 没有 fork” — 是的,所以我会比较同类事物。但是我也会比较 fork,因为它有很多用例,例如进程隔离(例如,Web 浏览器的每个选项卡都在不同的进程中运行)。
现在我们来看看事实,性能上有什么区别?
数据摘自http://www.bitsnbites.eu/benchmarking-os-primitives/。
由于偏见不可避免,总结时,我倾向于
在大多数测试中使用 MS-Windows 硬件 i7 8 核 3.2GHz。运行 Gnu/Linux 的 Raspberry-Pi 除外
注意:在 Linux 上,fork
比 MS-Window 的首选方法更快CreateThread
。
进程创建类型操作的数字(因为在图表中很难看到 Linux 的值)。
按速度排序,从最快到最慢(数字是时间,越小越好)。
Linux 创建线程 12
Mac CreateThread 15
Linux Fork 19
Windows 创建线程 25
Linux CreateProcess(fork+exec) 45
麦克福克 105
Mac CreateProcess(fork+exec) 453
Raspberry-Pi CreateProcess(fork + exec)501
Windows 创建进程 787
Windows CreateProcess 带有病毒扫描程序 2850
Windows Fork(使用 CreateProcess + fixup 模拟)大于 2850
其他测量值的数字
创建文件。
Linux 13
Mac 113
窗户 225
Raspberry-Pi(带慢速 SD 卡) 241
带有防御程序和病毒扫描程序等的 Windows 12950
分配内存
Linux 79
Windows 93
Mac 152
解决方案 9:
所有这些再加上一个事实,即在 Win 机器上,防病毒软件很可能会在 CreateProcess 期间启动……这通常是最严重的减速。
解决方案 10:
还值得注意的是,Windows 中的安全模型比基于 Unix 的操作系统复杂得多,这在进程创建期间增加了大量开销。这也是 Windows 中多线程优于多处理的另一个原因。
- 2024年20款好用的项目管理软件推荐,项目管理提效的20个工具和技巧
- 2024年开源项目管理软件有哪些?推荐5款好用的项目管理工具
- 项目管理软件有哪些?推荐7款超好用的项目管理工具
- 项目管理软件哪个最好用?盘点推荐5款好用的项目管理工具
- 项目管理软件有哪些最好用?推荐6款好用的项目管理工具
- 项目管理软件有哪些,盘点推荐国内外超好用的7款项目管理工具
- 2024项目管理软件排行榜(10类常用的项目管理工具全推荐)
- 项目管理软件排行榜:2024年项目经理必备5款开源项目管理软件汇总
- 2024年常用的项目管理软件有哪些?推荐这10款国内外好用的项目管理工具
- 项目管理必备:盘点2024年13款好用的项目管理软件