Locked 。这个问题及其答案是locked 因为这个问题是题外话,但却具有历史意义。目前不接受新的答案或互动。
Java有在某种程度上因缓慢而闻名 .
Java真的很慢吗?
如果是,为什么?瓶颈在(或曾经)在哪里?是因为 JVM 效率低下吗?垃圾收集?纯字节码库而不是 JNI 包装的 C 代码?许多其他语言都具有这些功能,但它们没有缓慢的声誉。
现代 Java 是最快的语言之一,尽管它仍然占用内存。爪哇had 因其速度慢而闻名,因为过去虚拟机启动需要很长时间。
如果你仍然认为 Java 很慢 , see 基准游戏 结果。用提前编译语言(C、Fortran 等)编写的经过严格优化的代码可以击败它;然而,Java 的速度可以比 PHP、Ruby、Python 等快 10 倍以上。在某些特定领域,Java 可以击败常见的编译语言(如果它们使用标准库)。
现在,Java 应用程序“慢”是没有任何借口的。 开发人员和遗留代码/库应该受到指责,而不仅仅是语言。另外,归咎于任何“企业”。
公平地说,对于那些“Java 很慢”的人来说,以下是它仍然很慢的领域(2013 年更新):
库通常是为了“正确性”和可读性而编写的,而不是为了性能。 在我看来,这是Java仍然名声不佳的主要原因,尤其是服务器端。这使得字符串问题呈指数级恶化。一些简单的错误很常见:经常使用对象代替基元,从而降低性能并增加内存使用。许多 Java 库(包括标准库)会频繁创建字符串,而不是重用可变或更简单的格式(char[] 或 StringBuffer)。这很慢并且会产生大量垃圾供以后收集。为了解决这个问题,我建议开发人员尽可能使用原始集合,尤其是 Javalution 的库。
字符串操作有点慢。 Java使用不可变,UTF-16 - 编码的字符串对象。这意味着您需要更多内存、更多内存访问,并且某些操作比 ASCII(C、C++)更复杂。当时,正是right 决定可移植性,但它会带来很小的性能成本。UTF-8 现在看起来是一个更好的选择。
与 C 相比,数组访问要慢一些, 由于边界检查。惩罚曾经很大,但现在很小(Java 7 优化掉了很多冗余的边界检查)。
缺乏任意内存访问可能会使某些 I/O 和位级处理变慢(例如压缩/解压缩)。这是现在大多数高级语言的安全特性。
Java 使用的内存比 C 多得多, 如果您的应用程序受内存限制或内存带宽限制(缓存等),这会使其速度变慢。另一方面是分配/释放速度非常快(高度优化)。这是现在大多数高级语言的一个特性,并且由于对象和使用GC 而不是显式的内存分配。 再加上图书馆的糟糕决定。
基于流的 I/O 速度很慢 由于(IMO,糟糕的选择)要求每个流访问同步。NIO 修复了这个问题,但是使用起来很痛苦。人们可以通过对数组而不是一次对一个元素进行读/写来解决这个问题。
Java 不提供与 C 相同的低级功能, 所以你不能使用脏的内联汇编技巧来使某些操作更快。这提供了可移植性,并且是现在大多数高级语言的一个特性。
Java 应用程序与非常旧的 JVM 版本相关的情况很常见。 尤其是服务器端。与最新版本相比,这些旧 JVM 的效率可能极其低下。
最后,Java 的设计目的是为了提供安全性和可移植性,但牺牲了一些性能,并且对于它所显示的一些真正要求很高的操作来说。它大部分缓慢的声誉已不再名副其实。
然而,有几个地方需要Javafaster 与大多数其他语言相比:
内存分配和解除分配
又快又便宜。 我见过案例
速度快 20%(或更多!)
分配一个新的多kB数组
重用缓存的一个。
对象实例化和面向对象的功能使用起来非常快 (在某些情况下比 C++ 更快),因为它们是从一开始就设计的。这部分来自于良好的 GC,而不是显式分配(这对大量小对象分配更友好)。人们可以编写 C 代码来击败这一点(通过滚动自定义内存管理并有效地执行 malloc),但这并不容易。
方法调用基本上是免费的,并且在某些情况下比大型方法代码更快。 The HotSpot 编译器使用执行信息来优化方法调用,并具有非常高效的内联。通过使用额外的执行信息,它有时可以胜过提前编译器,甚至(在极少数情况下)手动内联。与 C/C++ 相比,如果编译器决定不内联,方法调用会带来较小的性能损失。
同步和多线程既简单又高效。 Java 从一开始就被设计为具有线程感知能力,这一点也得到了证明。现代计算机通常具有多个核心,并且由于线程内置于该语言中,因此您可以很容易地利用它。与标准单线程 C 代码相比,速度基本上提高了 100% 到 300%。是的,精心编写的 C 线程和库可以克服这个问题,但这对程序员来说是很多额外的工作。
字符串包括长度:某些操作速度更快。 这优于使用空分隔字符串(C 中常见)。在 Java 7 中,Oracle 取消了 String.subString() 优化,因为人们愚蠢地使用它并导致内存泄漏。
数组复制经过高度优化。 在最新版本中,Java 对 System.arraycopy 使用手动调整的汇编程序。结果是,在 arraycopy/memcopy 密集型操作中,我发现我的代码以合理的幅度击败了 C 中的等效代码。
JIT 编译器很聪明地使用L1/L2 cache 。提前编译的程序无法根据其运行的特定 CPU 和系统实时调整其代码。 JIT 通过这种方式提供了一些非常有效的循环转换。
其他一些历史事实也导致了“Java 很慢”的声誉:
在 JIT 编译(Java 1.2/1.3)之前,该语言仅被解释,而不被编译,因此非常慢。
JIT 编译需要时间才能变得高效(每个版本都有重大改进)
多年来,类加载已经变得更加高效。过去它在启动过程中效率很低且缓慢。
Swing 并且 UI 代码没有很好地使用本机图形硬件。
摇摆实在是太糟糕了。 我将 Java 从未在桌面上流行起来的原因归咎于 AWT 和 Swing。
在库类中大量使用同步;现已提供非同步版本
小程序需要很长时间才能加载,因为要传输完整的内容JAR 通过网络并加载虚拟机进行启动。
同步过去会带来严重的性能损失(每个 Java 版本都对此进行了优化)。不过,反思的代价仍然很高。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)