java - Java真的很慢吗?

标签 java performance

锁定。这个问题及其答案是locked因为这个问题是题外话,但具有历史意义。它目前不接受新的答案或互动。








Java 有 some degree of reputation for being slow .

  • Java真的很慢吗?
  • 如果是,为什么?瓶颈在哪里(或曾经是)?是因为 JVM 效率低下吗?垃圾收集?纯字节码库而不是 JNI 包装的 C 代码?许多其他语言具有这些功能,但它们没有这种缓慢的声誉。
  • 最佳答案

    现代 Java 是最快的语言之一,尽管它仍然是一个内存 pig 。 Java 速度慢的名声是因为它过去需要很长时间才能启动 VM。

    如果您仍然认为 Java 很慢 ,见 the benchmarks game结果。用提前编译语言(C、Fortran 等)编写的经过严格优化的代码可以击败它;但是,Java 的速度可以是 PHP、Ruby、Python 等的 10 倍以上。在某些特定领域,它可以击败常见的编译语言(如果它们使用标准库)。

    现在没有理由让 Java 应用程序“慢”了。 开发人员和遗留代码/库应该受到指责,而不仅仅是语言。此外,责怪任何“企业”。

    公平地说,对于“Java 很慢”的人群,以下是它仍然很慢的地方(2013 年更新):

  • 库通常是为了“正确性”和可读性而不是性能而编写的。 在我看来,这是 Java 仍然名声不佳的主要原因,尤其是服务器端。这使得字符串问题呈指数级恶化。一些简单的错误很常见:经常使用对象代替原语,从而降低性能并增加内存使用。许多 Java 库(包括标准库)会频繁地创建字符串,而不是重用可变或更简单的格式(char[] 或 StringBuffer)。这很慢,并且会产生大量垃圾以供稍后收集。为了解决这个问题,我建议开发人员尽可能使用原始集合,尤其是 Javalution 的库。
  • 字符串操作有点慢。 Java 使用不可变,UTF-16 - 编码的字符串对象。这意味着您需要更多内存、更多内存访问,并且某些操作比使用 ASCII(C、C++)更复杂。在当时,它是便携性的正确决定,但它带来了很小的性能成本。 UTF-8现在看起来是更好的选择。
  • 数组访问比 C 慢一点,由于边界检查。惩罚曾经很大,但现在很小(Java 7 优化了很多冗余边界检查)。
  • 缺乏任意内存访问可能会使一些 I/O 和位级处理变慢(例如压缩/解压缩)。这是现在大多数高级语言的安全特性。
  • Java 使用的内存比 C 多很多,如果您的应用程序受内存限制或内存带宽限制(缓存等),这会使其变慢。另一方面是分配/解除分配非常快(高度优化)。这是现在大多数高级语言的一个特性,并且由于对象和使用 GC而不是显式的内存分配。加上糟糕的图书馆决定。
  • 基于流的 I/O 很慢 由于(IMO,糟糕的选择)要求对每个流访问进行同步。 NIO解决了这个问题,但使用起来很痛苦。可以通过读取/写入数组而不是一次一个元素来解决此问题。
  • Java 不提供与 C 相同的低级功能,所以你不能使用脏的内联汇编技巧来使某些操作更快。这提供了可移植性,并且是现在大多数高级语言的一个特性。
  • 经常看到 Java 应用程序绑定(bind)到非常旧的 JVM 版本。 尤其是服务器端。与最新版本相比,这些旧的 JVM 效率低得令人难以置信。

  • 最后,Java 旨在以牺牲一些性能为代价提供安全性和可移植性,并且它显示了一些非常苛刻的操作。它以缓慢而著称的大部分内容已不再应得。

    但是,Java有几个地方是更快 比大多数其他语言:
  • 内存分配和解除分配
    又快又便宜。
    我看过案例
    速度提高 20%(或更多!)
    分配一个新的多 kB 数组,而不是
    重用缓存的。
  • 对象实例化和面向对象功能的使用速度非常快 (在某些情况下比 C++ 快),因为它们是从一开始就设计的。这部分来自于良好的 GC 而不是显式分配(这对大量小对象分配更友好)。可以编写 C 来击败这一点(通过滚动自定义内存管理和有效地执行 malloc),但这并不容易。
  • 方法调用基本上是免费的,并且在某些情况下比大方法代码更快。 HotSpot编译器使用执行信息来优化方法调用并具有非常高效的内联。通过使用额外的执行信息,它有时可以胜过提前编译器,甚至(在极少数情况下)手动内联。与 C/C++ 相比,如果编译器决定不内联,方法调用会带来很小的性能损失。
  • 同步和多线程既简单又高效。 Java 从一开始就被设计为线程感知,并且它显示了。现代计算机通常具有多个内核,并且由于线程内置于语言中,因此您可以非常轻松地利用它。与标准的单线程 C 代码相比,基本上是额外的 100% 到 300% 的速度提升。是的,精心编写的 C 线程和库可以解决这个问题,但这对程序员来说是很多额外的工作。
  • 字符串包括长度:某些操作更快。 这优于使用空分隔字符串(在 C 中很常见)。在 Java 7 中,Oracle 取消了 String.subString() 优化,因为人们愚蠢地使用它并导致内存泄漏。
  • 数组副本高度优化。 在最新版本中,Java 对 System.arraycopy 使用手动调整的汇编程序。结果是在 arraycopy/memcopy-heavy 操作中,我看到我的代码以合理的余量击败了 C 中的等价物。
  • JIT 编译器很聪明地使用 L1/L2缓存 .提前编译的程序无法针对它们运行的​​特定 CPU 和系统实时调整它们的代码。 JIT 以这种方式提供了一些非常有效的循环转换。

  • 其他一些历史事实促成了“Java 很慢”的声誉:
  • 在 JIT 编译之前(Java 1.2/1.3),该语言只是解释性的,而不是编译性的,因此非常慢。
  • JIT 编译需要时间才能变得高效(每个版本都有重大改进)
  • 多年来,类加载变得更加高效。它曾经在启动过程中非常低效和缓慢。
  • Swing并且 UI 代码没有很好地使用原生图形硬件。
  • 摇摆简直太可怕了。 我责怪 AWT 和 Swing 为什么 Java 从未在桌面上流行。
  • 在库类中大量使用同步;非同步版本现已可用
  • 小程序需要永远加载,因为传输完整的 JAR通过网络加载虚拟机进行引导。
  • 同步用于带来沉重的性能损失(这已针对每个 Java 版本进行了优化)。尽管如此,反射仍然是昂贵的。
  • 关于java - Java真的很慢吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2163411/

    相关文章:

    performance - Win10下VirtualBox性能不佳

    java - 在 Java 的 ThreadPoolExecutor 中重新排序队列

    java - YCSB项目安装JDBC驱动

    java - 将 Framework Assets.at Play 到 java.io.File

    Java For 循环 vs While 循环,奇怪的行为和时间性能

    excel - 提高生成随机数的嵌套循环的速度

    performance - Matlab bsxfun - 为什么 bsxfun 在这种情况下无法工作?

    java - Eclipse 的代码标准(非样式)执行器

    java - toArray() 返回对象[]

    c - 提高成交率的技巧