Maison Java javaDidacticiel 在什么情况下,Java比C++慢很多?

在什么情况下,Java比C++慢很多?

Nov 30, 2016 am 09:58 AM
c++ java

 问:在什么情况下,Java 比 C++ 慢很多?

  答:Ben Maurer:

  为了回答这个问题,需要先将该问题分成几个可能引起慢的原因:

  垃圾回收器。这是一把“双刃剑”。如果你的程序遵循“大部分对象都在年青代中消亡”模型,垃圾回收器是非常有利的(很少的碎片,更好的缓存局部性)。但是,如果程序不遵循该模型,JVM将花费很多资源来回收堆内存。

  大对象。在Java中,所有的对象都有一个vtable指针,而C++中使用POD结构没有额外开销。此外,所有的Java对象是可以被锁定的。其实现依赖于JVM,这可能需要在对象中增加额外的字段。大对象 == 缓存更少的对象 == 更慢。(另一方面,Java 7 用64位记录压缩后的指针,这也是造成该问题的一部分原因。

  缺乏内联对象。在Java中,所有的类都是指针。在C++中,对象可以和其它对象一起分配,或者在栈上分配。这样可以提高缓存的局部性,从而减少动态内存分配的开销。

  平台函数调用。在Java中,JNI的调用或者将对象编译成本地代码都会带来不小的开销。如果你需要频繁调用客户端的C++代码,会增加很大的开销。

  低效的强制抽象。例如,在Java中字符串是不可变的。如果你想写一个XML分析器,你只使用String对象(没有char[]),它将会很慢,因为需要分配额外的空间。

  虚函数调用增加。JVM中,几乎所有的函数调用都是虚函数调用。有许多代码尝试避免虚函数调用,但是很多场景下,JVM无法解决这个问题。这阻碍了代码的内联,使代码变慢。

  缺乏高级的编译特征及转为汇编的能力。 如果你写了一段能从汇编得益的代码Java可能表现不佳。

  在我看来,最大的问题是垃圾回收。在程序中,强制在大的内存中进行多次完全GC,是最容易导致Java和C++之间产生鸿沟的原因之一。除此之外,如果将程序的工作集放在L2缓存之外,像大对象、缺乏内联对象等问题,也会导致两者之间的巨大差别。

  低效的强制抽象和平台函数也会导致速度下降,但是这通常只会因为低级的代码才会产生。如果你使用写得很好的Java代码库,这通常不是什么大问题。

  答:Todd Lipcon

  我基本同意Ben Maurer(hey Ben!)的回答。有几个小点不同:

  在最新的JVM中,当这种分配永远不会从(a)局部函数或(b)局部线程逃逸出去的时候,逃逸分析能有效地决定一种固定分配。也就是说当分配不需要加锁,通常是在自身的栈空间上进行的。这两种情况下都是一种简单的“指针碰撞(bump the pointer)”分配,这等同于C中的栈分配。

  译者注:

逃逸分析 Escape Analysis,是一种编译优化技术,指分析指针动态范围的方法。通俗地说,当一个对象的指针被多个方法或线程引用时,我们称这个指针发生了逃逸。

指针碰撞(bump the point)。假设Java堆中内存是绝对规整的,所有用过的内存都被放在一边,空闲的内存被放在另一边,中间放着一个指针作为分界点的指示器,那所分配内存就仅仅是把那个指针向空闲空间那边挪动一段与对象大小相等的距离,这种分配方式称为“指针碰撞”。

  即使没有逃逸分析,年青代的分配也是通过指针碰撞方式,在线程本地分配缓冲区(TLAB)中完成的,不需要进行同步。所以Java中小对象的分配有的时候比C语言实现的 malloc() 方式更快。更好的 malloc 方法像Google的 tcmalloc,采用了类似的方式。但是由于C语言无法在内存中对分配后的对象重新分配,所以某些方面会受到限制。

  虽然存在内联和虚函数问题,但是实际上,Java在某些情况下甚至可以做的比C更好。特别是,C不能通过动态链接功能来实现内联,因为内联是在编译时期进行的,而不是运行时期。而Java可越过不同的类或库的边界来动态内联一个函数,即使该类的真正实现在编译期间还不可用。许多工作中,这种方式比C++的虚函数调用更有效,C++虚函数调用总是需要调用虚表。而JIT编译器,如果之前动态属性已经丢失(如新的类已经被加载),能够聪明地取消内联优化。

  新版本的GCC提供一些这方面优化,称为“全程序优化”或“链接时优化",允许在工程范围内越过对象文件进行内联。但是,基本上还是不允许通过动态链接的方式来实现内联(如通过内联的方式实现zlib的调用等)。许多大型项目都是通过复制标准库的功能到它们的代码中来实现。


Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Outils d'IA chauds

Undresser.AI Undress

Undresser.AI Undress

Application basée sur l'IA pour créer des photos de nu réalistes

AI Clothes Remover

AI Clothes Remover

Outil d'IA en ligne pour supprimer les vêtements des photos.

Undress AI Tool

Undress AI Tool

Images de déshabillage gratuites

Clothoff.io

Clothoff.io

Dissolvant de vêtements AI

AI Hentai Generator

AI Hentai Generator

Générez AI Hentai gratuitement.

Article chaud

R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Meilleurs paramètres graphiques
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
R.E.P.O. Comment réparer l'audio si vous n'entendez personne
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Où trouver la courte de la grue à atomide atomique
1 Il y a quelques semaines By DDD

Outils chauds

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Break or Return of Java 8 Stream Forach? Break or Return of Java 8 Stream Forach? Feb 07, 2025 pm 12:09 PM

Java 8 présente l'API Stream, fournissant un moyen puissant et expressif de traiter les collections de données. Cependant, une question courante lors de l'utilisation du flux est: comment se casser ou revenir d'une opération FOREAK? Les boucles traditionnelles permettent une interruption ou un retour précoce, mais la méthode Foreach de Stream ne prend pas directement en charge cette méthode. Cet article expliquera les raisons et explorera des méthodes alternatives pour la mise en œuvre de terminaison prématurée dans les systèmes de traitement de flux. Lire plus approfondie: Améliorations de l'API Java Stream Comprendre le flux Forach La méthode foreach est une opération terminale qui effectue une opération sur chaque élément du flux. Son intention de conception est

Pourquoi une erreur se produit-elle lors de l'installation d'une extension à l'aide de PECL dans un environnement Docker? Comment le résoudre? Pourquoi une erreur se produit-elle lors de l'installation d'une extension à l'aide de PECL dans un environnement Docker? Comment le résoudre? Apr 01, 2025 pm 03:06 PM

Causes et solutions pour les erreurs Lors de l'utilisation de PECL pour installer des extensions dans un environnement Docker Lorsque nous utilisons un environnement Docker, nous rencontrons souvent des maux de tête ...

Programme Java pour trouver le volume de la capsule Programme Java pour trouver le volume de la capsule Feb 07, 2025 am 11:37 AM

Les capsules sont des figures géométriques tridimensionnelles, composées d'un cylindre et d'un hémisphère aux deux extrémités. Le volume de la capsule peut être calculé en ajoutant le volume du cylindre et le volume de l'hémisphère aux deux extrémités. Ce tutoriel discutera de la façon de calculer le volume d'une capsule donnée en Java en utilisant différentes méthodes. Formule de volume de capsule La formule du volume de la capsule est la suivante: Volume de capsule = volume cylindrique volume de deux hémisphères volume dans, R: Le rayon de l'hémisphère. H: La hauteur du cylindre (à l'exclusion de l'hémisphère). Exemple 1 entrer Rayon = 5 unités Hauteur = 10 unités Sortir Volume = 1570,8 unités cubes expliquer Calculer le volume à l'aide de la formule: Volume = π × r2 × h (4

Quel est le rôle de char dans les chaînes C Quel est le rôle de char dans les chaînes C Apr 03, 2025 pm 03:15 PM

En C, le type de char est utilisé dans les chaînes: 1. Stockez un seul caractère; 2. Utilisez un tableau pour représenter une chaîne et se terminer avec un terminateur nul; 3. Faire fonctionner via une fonction de fonctionnement de chaîne; 4. Lisez ou sortant une chaîne du clavier.

Comment exécuter votre première application Spring Boot dans Spring Tool Suite? Comment exécuter votre première application Spring Boot dans Spring Tool Suite? Feb 07, 2025 pm 12:11 PM

Spring Boot simplifie la création d'applications Java robustes, évolutives et prêtes à la production, révolutionnant le développement de Java. Son approche "Convention sur la configuration", inhérente à l'écosystème de ressort, minimise la configuration manuelle, allo

Programme Java pour insérer un élément au bas d'une pile Programme Java pour insérer un élément au bas d'une pile Feb 07, 2025 am 11:59 AM

Une pile est une structure de données qui suit le principe LIFO (dernier dans, premier sorti). En d'autres termes, le dernier élément que nous ajoutons à une pile est le premier à être supprimé. Lorsque nous ajoutons (ou poussons) des éléments à une pile, ils sont placés sur le dessus; c'est-à-dire surtout

Comment exécuter votre première application de démarrage de printemps dans Intellij? Comment exécuter votre première application de démarrage de printemps dans Intellij? Feb 07, 2025 am 11:40 AM

Intellij Idea simplifie le développement de Boot Spring, ce qui en fait un favori parmi les développeurs Java. Son approche de configuration de la convention minimise le code passe-partout, permettant aux développeurs de se concentrer sur la logique métier. Ce tutoriel montre deux métho

Comparaison de deux ArrayList en Java Comparaison de deux ArrayList en Java Feb 07, 2025 pm 12:03 PM

Ce guide explore plusieurs méthodes Java pour comparer deux listes de table. Une comparaison réussie nécessite que les deux listes aient la même taille et contiennent des éléments identiques. Méthodes pour comparer les listes d'arraises en Java Plusieurs approches existent pour comparer AR

See all articles