compiler-construction - 使编译后的二进制文件以 native 速度完美运行,而无需从另一个系统上的源代码重新编译?

标签 compiler-construction constraints virtualization native aot

我知道很多人第一眼看到这个问题,可能会立即大喊“Java”,但不,我知道 Java 的品质。请允许我先详细说明我的问题。

通常,当我们希望我们的程序在系统上以 native 速度运行时,无论是 Windows、Mac OS X 还是 Linux,我们都需要从源代码编译。如果你想在你的系统中运行另一个系统的程序,你需要使用虚拟机或者模拟器。虽然这些工具允许您在非本地操作系统上使用您需要的程序,但它们有时会出现性能和故障问题。

我们还有一个名为“JIT Compiler”的新编译器,编译器会在执行前将字节码程序解析为本地机器语言。使用 JIT Compiler 性能可能会提高到一个很好的程度,但性能仍然与在 native 系统上运行它不同。

Linux 上的另一个程序 WINE 也是在 Linux 系统上运行 Windows 程序的好工具。我曾尝试在其上运行 Team Fortress 2,并尝试尝试一些设置。我在 Windows 上以 1280 x 1024 的中高设置获得约 40 fps。在 Linux 上,我需要将所有内容都调低至 1280 x 1024 以获得约 40 fps。不过有两点值得注意:

  1. 无论我将其设置为低还是高,多边形模型设置似乎都不会影响帧速率。
  2. 当有后期处理效果或某些特殊效果需要对当前帧的绘制像素进行操作时,帧率会下降到 10-20 fps。

从这一点来看,我可以看到法线多边形渲染还不错,但是当涉及到需要显卡才能工作的较新渲染方法时,它就会变慢。

无论如何,这个问题是相当理论的。有什么我们可以做的吗?我看到WINE可以运行STEAM和军团要塞2。虽然有缺陷,但它们可以在较低的设置下运行。或者,我还应该问,“是否可以将一个系统上的整个程序翻译到另一个系统,而无需从源代码重新编译并获得 native 速度?”我看到我们也有 AOT 编译器,是可以将它用于这样的事情吗?还是有太多的限制(例如 DirectX 调用或软件架构的差异)导致无法拥有一个完美且非原生的以原生速度运行的系统程序?

最佳答案

在不重新编译的情况下以 native 速度在多个系统上运行相同的编译代码体的第一步是选择一个处理器指令集并丢弃所有其他系统。如果你选择英特尔,那么你必须抛弃 ARM、MIPS、PowerPC 等,因为一种架构的本地机器代码指令对于其他处理器来说是完全无法理解的。

好的。因此,现在的任务是以 native 速度在多个系统(都使用相同的处理器架构)上运行相同的已编译 native 代码主体,而无需重新编译。因此,基本上,您希望在同一硬件上的不同操作系统下运行相同的代码。

如果硬件相同并且唯一的区别是操作系统,那么简单的答案是肯定的,如果您可以编写代码而不需要对操作系统进行任何调用,那么您就可以做到。没有内存分配。没有控制台输出。没有文件 I/O。没有网络 I/O。没有什么好玩的。

此外,您的代码必须以不需要地址重定位修复的方式编写,因为每个操作系统都有不同的方式来表示可重定位代码。一种方法是在磁盘上完全按照它在内存中出现的方式排列代码,包括为可写数据(全局变量、堆栈和堆)保留空间。然后,运行代码所需要做的就是将文件字节复制到内存中预定义的基地址,然后跳转到起始地址。

MSDOS .com 可执行文件格式至少从 1981 年就开始这样做了,而 CP/M 早在此之前。

然而,当时的 MSDOS 并没有今天的病毒扫描程序可以与之抗衡。当主机操作系统以外的任何人将文件数据加载到内存中并尝试执行该内存时,病毒扫描程序会非常兴奋。因为,你知道,这正是病毒所做的。

由于每个操作系统都有自己的可执行文件格式,您还需要弄清楚如何在所有这些不同操作系统上将“完美”的 native 代码块放入内存中。您至少需要为每个要在其中运行 native 代码块的操作系统编译一个程序加载器。当您为每个要定位的操作系统编写程序加载器时,您还可以定义自己的文件 I/O 映射到 OS native 等效项的函数,以便您的 native 代码块可以在任何系统上执行文件 I/O。同样适用于控制台 I/O 或图形输出。

哦,等等——这正是 WINE 所做的。

这也是为什么您在 WINE 中看到的帧速率远低于主机操作系统中的相同操作的原因 - WINE 正在将 Win32 GDI 图形调用转换为由 native 主机操作系统(Linux -> XWindows)提供的东西,并且在哪里没有精确的函数匹配或存在操作语义不匹配的情况(这种情况经常发生),WINE 必须自己实现所有功能,有时成本很高。

但鉴于 IDE 驱动器、USB 设备和 BIOS 功能等标准化硬件无处不在,也许您无需费心将自己的可移植 API 映射到操作系统内置的任何东西上。只需编写一个很少的代码可以对 IDE 设备进行文件 I/O,使用 VESA BIOS 功能进行图形输出。如果您稍微抽象一下代码,您可以支持多种硬件,并根据您在运行时找到的硬件选择合适的函数指针来使用。

然后,您可以在任何系统(使用一种特定的处理器架构)上真正以 native 速度运行您的 native 代码块,而无需重新编译。

哦,等等 - 您刚刚编写了自己的操作系统。 ;>

关于compiler-construction - 使编译后的二进制文件以 native 速度完美运行,而无需从另一个系统上的源代码重新编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4638122/

相关文章:

compiler-construction - 建立一个链接器

haskell - Haskell 是用什么语言编写的?

xcode - 如何在 Swift 中以编程方式添加约束

ios - 程序化自动布局、约束和 UIView 运行时

linux - ubuntu 和虚拟 PC

.net - 如何使用 Windows 命令行上的命令行将 C++ 文件编译为单个文件

iOS 框架和重复库

c# - Entity Framework 中唯一字段的选项 - dbSet 的导航属性?

linux - vmWare Server 可以安装在 X-less 主机上吗?

windows-phone-7 - ListBox 数据虚拟化未生效