Mono虚拟机可以跨进程共享吗?
Can the Mono Virtual Machine Be Shared Accross Processes?
如果我想 运行 在 Linux 上的单声道下运行两个或更多控制台应用程序,我是否会为每个进程承担 Mono 虚拟机的开销,或者虚拟机的某些部分是否会被重用跨进程?如果不是这种情况,是否有办法共享单声道虚拟机使用的部分内存?
我想实现以下目标:假设当应用程序加载标准库的许多程序集时,mono 虚拟机需要 100MB。应用程序 A 的细节使其使用额外的 50Mb RAM(因此进程 A 使用的总 RAM 为 150Mb),应用程序 B 的细节使其我们额外使用 120Mb 的 RAM(因此进程 B 使用的总 RAM 为 220Mb ).
如果 Mono 的工作方式,将生成两个独立的 Mono 虚拟机,那么我将使用 370Mb 的 RAM。但是,如果在虚拟机之间共享诸如基础库之类的内存,那么我只会使用 100 + 50 + 120 = 270Mb 的 RAM。
问题是,我可能处于 运行 数十或数百个相对较小的应用程序的情况,我担心每个单声道虚拟机保留的内存会大大降低内存占用的部署,而每个单独的应用程序的 RAM 要求实际上不会那么大。我说的是控制台应用程序(Web 服务)。
谢谢
一如既往,视情况而定。 ;-)
Linux 将始终多次共享同一个可执行文件 运行 的只读段 。 IE。 VM的可执行代码和常量数据在内存中只存在一次,而可变数据不共享。
但是要知道一件事。由于 Mono 是一个即时编译器,它将 IL 语言翻译成您平台的本机代码。你的问题从这里开始。 翻译后的代码在 运行 时生成并驻留在非只读内存段中。 内核不再知道这种冗余,因此单声道占用的内存 class 库将不会在同一主机上的 Mono VM 之间共享 运行。
(事实上,内存页面无论如何都不会完全匹配,因为不同的 VM 可能 运行 代码路径略有不同,例如以不同的顺序加载 运行time 的 classes 或类似那个。)
如果故事就此结束,事情会很容易,但事实并非如此。还有另一个 Mono 特性:AOT(提前编译).
在这种情况下,JIT 在 运行 时间未将 ode 编译为机器语言。取而代之的是更早的预编译。在这种情况下,从 VM 实例的角度来看,预编译代码是 只读的。现在内核将再次共享预编译代码作为常量数据。
参见 AOT: Increased Memory Sharing
但这还不是故事的结局。 AOT 编译器 确实支持 Mono 的所有功能,它有限制。它无法处理所有程序模式。所以一些运行时间class不共享。详细信息取决于 Mono 版本以及您的平台。
有关详细信息,请参阅 Ahead of Time Compilation (AOT)。
所以答案并不那么容易。根据 Mono 版本以及您引用的库是否包含您平台的预编译代码,或多或少的内存在并发 运行 宁虚拟机之间共享。
实际上,它介于您的悲观假设和乐观假设之间。您可以非常确定,即使 AOT 做得非常好,VM 的某些数据段也无法共享。例如。内部变量和 class 反射实例 classes 将 不 共享。
AOT 仅涵盖 IL 代码,但不涵盖仅依赖于设计时常量的表达式和对象,例如 C++ constexpr
。
我不知道它如何在您的 特定用例中扩展。但是您谈论的是数百个 相对较小的 应用程序。小型应用程序很可能不会有 100 MB 的 运行 时间开销。至少我不会再叫这个"small application"了。
但还有一个建议:不要启动数百个并行进程。即使 Mono VM 在内存共享方面做得很好,它也是对系统资源的过度使用.使用队列代替将任务委托给 有限 个进程,或者以其他方式重新考虑您的概念。很可能 运行 进入非线性可扩展性和最差情况下的性能。
如果我想 运行 在 Linux 上的单声道下运行两个或更多控制台应用程序,我是否会为每个进程承担 Mono 虚拟机的开销,或者虚拟机的某些部分是否会被重用跨进程?如果不是这种情况,是否有办法共享单声道虚拟机使用的部分内存?
我想实现以下目标:假设当应用程序加载标准库的许多程序集时,mono 虚拟机需要 100MB。应用程序 A 的细节使其使用额外的 50Mb RAM(因此进程 A 使用的总 RAM 为 150Mb),应用程序 B 的细节使其我们额外使用 120Mb 的 RAM(因此进程 B 使用的总 RAM 为 220Mb ).
如果 Mono 的工作方式,将生成两个独立的 Mono 虚拟机,那么我将使用 370Mb 的 RAM。但是,如果在虚拟机之间共享诸如基础库之类的内存,那么我只会使用 100 + 50 + 120 = 270Mb 的 RAM。
问题是,我可能处于 运行 数十或数百个相对较小的应用程序的情况,我担心每个单声道虚拟机保留的内存会大大降低内存占用的部署,而每个单独的应用程序的 RAM 要求实际上不会那么大。我说的是控制台应用程序(Web 服务)。
谢谢
一如既往,视情况而定。 ;-)
Linux 将始终多次共享同一个可执行文件 运行 的只读段 。 IE。 VM的可执行代码和常量数据在内存中只存在一次,而可变数据不共享。
但是要知道一件事。由于 Mono 是一个即时编译器,它将 IL 语言翻译成您平台的本机代码。你的问题从这里开始。 翻译后的代码在 运行 时生成并驻留在非只读内存段中。 内核不再知道这种冗余,因此单声道占用的内存 class 库将不会在同一主机上的 Mono VM 之间共享 运行。
(事实上,内存页面无论如何都不会完全匹配,因为不同的 VM 可能 运行 代码路径略有不同,例如以不同的顺序加载 运行time 的 classes 或类似那个。)如果故事就此结束,事情会很容易,但事实并非如此。还有另一个 Mono 特性:AOT(提前编译).
在这种情况下,JIT 在 运行 时间未将 ode 编译为机器语言。取而代之的是更早的预编译。在这种情况下,从 VM 实例的角度来看,预编译代码是 只读的。现在内核将再次共享预编译代码作为常量数据。
参见 AOT: Increased Memory Sharing但这还不是故事的结局。 AOT 编译器 确实支持 Mono 的所有功能,它有限制。它无法处理所有程序模式。所以一些运行时间class不共享。详细信息取决于 Mono 版本以及您的平台。
有关详细信息,请参阅 Ahead of Time Compilation (AOT)。
所以答案并不那么容易。根据 Mono 版本以及您引用的库是否包含您平台的预编译代码,或多或少的内存在并发 运行 宁虚拟机之间共享。
实际上,它介于您的悲观假设和乐观假设之间。您可以非常确定,即使 AOT 做得非常好,VM 的某些数据段也无法共享。例如。内部变量和 class 反射实例 classes 将 不 共享。
AOT 仅涵盖 IL 代码,但不涵盖仅依赖于设计时常量的表达式和对象,例如 C++ constexpr
。
我不知道它如何在您的 特定用例中扩展。但是您谈论的是数百个 相对较小的 应用程序。小型应用程序很可能不会有 100 MB 的 运行 时间开销。至少我不会再叫这个"small application"了。
但还有一个建议:不要启动数百个并行进程。即使 Mono VM 在内存共享方面做得很好,它也是对系统资源的过度使用.使用队列代替将任务委托给 有限 个进程,或者以其他方式重新考虑您的概念。很可能 运行 进入非线性可扩展性和最差情况下的性能。