有没有人尝试过自动 Java 到 C++ 转换以提高速度?从长远来看,这是一场维护噩梦吗?只需阅读用于在 Gecko http://ejohn.org/blog/html-5-parsing/中生成 HTML5 解析引擎的内容
7 回答
一般来说,从一种语言到另一种语言的自动转换不会是一种改进。不同的语言有不同的习语会影响性能。
最简单的例子是循环和变量创建。在 Java GC 世界中,使用 new 创建对象几乎是免费的,而且它们也很容易被遗忘。在 C++ 中,内存分配(一般来说)很昂贵:
// Sample java code
for ( int i = 0; i < 10000000; ++i )
{
String str = new String( "hi" ); // new is free, GC is almost free for young objects
}
直接转换为 C++ 会导致性能不佳(使用 TR1 shared_ptr 作为内存处理程序而不是 GC):
for ( int i = 0; i < 10000000; ++i )
{
std::shared_ptr< std::string > str( new std::string( "hi" ) );
}
用 C++ 编写的等效循环是:
for ( int i = 0; i < 10000000; ++i )
{
std::string str( "hi" );
}
从一种语言到另一种语言的直接翻译通常以两全其美和难以维护的代码告终。
这种转换的积极点是,您需要适当的面向对象设计才能从 java 切换到 C++(范式交集)。
但是有人说,与 java 代码相比,编写 C++ 并没有带来速度上的提升。
即使这有效,我也不确定您是否会看到速度有很大提高。Java 的 Hotspot JIT 编译器已经变得相当不错了。
这种类型的转换外壳几乎不可能带来更好的性能。通常当 JVM 工作时,它会将大部分代码转换为本机机器码。您的建议是将 Jave 代码转换为 C++ 并从那里转换为本机机器代码,即添加一个额外的阶段。然而,在一些微不足道的情况下,由于以下事实,可能会获得一些收益:
1) 从头开始加载 JVM 需要一些时间。
2)做Jit需要一些时间,当运行一个很短的程序时,很多时候,你可能宁愿在运行前浪费这段时间。
3) 如果您不在服务器模式下运行,您可能无法在 Java 上获得相同级别的机器代码。(在服务器模式下,您将获得一流的机器代码,以及在运行时检测到的最适合您自己的 CPU 的机器代码,这通常是大多数 C/C++ 程序植入所缺乏的,此外还有机器代码在运行时优化)
几乎不可能通过程序用手动内存管理取代 Java 的自动内存管理。所以你很可能最终会得到一个程序,它有内存泄漏或使用垃圾收集器的 C++ 代码。但是 Java 中的垃圾收集器要依赖的东西要多得多(例如,没有指针算术、数学),所以为了安全起见,C++ 中的垃圾收集器会降低性能。因此,您的自动转换很可能会降低性能。
而是尝试手动将其移植到 C++ 或优化 Java 代码。
这些语言的使用风格如此不同,以至于盲目的转换几乎没有用处。由于使用的样式不同,智能转换器几乎无法编写。
一些问题领域:
- 资源分配由 Java 中的“try{} finally{}”块控制,而 C++ 使用 RAII。
- Java 在编译时进行异常检查 C++ 运行时。
- 异常的处理方式不同。两个例外:
- 在 Java 中(最后一次抛出被传播)
- 在 C++ 应用程序中终止。
- Java 有一个庞大的标准库
C++ 具有所有相同的功能,你只需要在网络上找到它[这很痛苦]。 - Java 对所有事物都使用指针。
- 一个直接不假思索的转换会给你留下一个只包含 shared_ptr 对象的程序。
无论如何,使用 JIT 编译 Java 在速度上可与 C++ 相媲美。
一般来说,说到这种转换器,不能指望它们生成可维护或高性能的代码,因为这些通常需要一个真正了解编写代码的语言的人。它们非常有用的是使移植语言变得容易。例如,任何带有 C 转换器的语言都可以在多种语言上快速实现。我在 90 年代中期使用 f2c 在 Macintosh 上运行 Fortran 例程。
如果你用 C++ 重写代码,你可能会也可能不会提高性能。如果您使用自动转换器,您可能会减速。