Je veux créer un nouveau tableau d'objets rassemblant deux tableaux plus petits.
Ils ne peuvent pas être nuls, mais la taille peut être égale à 0.
Je ne peux pas choisir entre ces deux méthodes: sont-elles équivalentes ou l'une est-elle plus efficace (par exemple, system.arraycopy () copie des morceaux entiers)?
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
System.arraycopy(publicThings, 0, things, 0, publicThings.length);
System.arraycopy(privateThings, 0, things, publicThings.length, privateThings.length);
ou
MyObject[] things = new MyObject[publicThings.length+privateThings.length];
for (int i = 0; i < things.length; i++) {
if (i<publicThings.length){
things[i] = publicThings[i]
} else {
things[i] = privateThings[i-publicThings.length]
}
}
La seule différence est-elle l'aspect du code?
EDIT: merci pour la question liée, mais ils semblent avoir une discussion non résolue:
Est-ce vraiment plus rapide si it is not for native types
: byte [], Object [], char []? dans tous les autres cas, une vérification de type est exécutée, ce qui serait mon cas et donc serait équivalent ... non?
Sur une autre question liée, ils disent que the size matters a lot
, pour une taille> 24 system.arraycopy () gagne, pour moins de 10, le manuel pour la boucle est meilleur ...
Maintenant, je suis vraiment confus.
arraycopy()
est un appel natif, qui est certainement plus rapide.Réponses:
Je sais que les tests JUnit ne sont pas vraiment les meilleurs pour l'analyse comparative, mais
testHardCopyBytes a pris 0,157 s pour terminer
et
testArrayCopyBytes a pris 0,086 s pour terminer.
Je pense que cela dépend de la machine virtuelle, mais il semble que cela copie des blocs de mémoire au lieu de copier des éléments de tableau unique. Cela augmenterait absolument les performances.
EDIT:
Il semble que les performances de System.arraycopy soient partout. Lorsque des chaînes sont utilisées au lieu d'octets et que les tableaux sont petits (taille 10), j'obtiens ces résultats:
Voici à quoi cela ressemble lorsque les tableaux sont à la taille 0x1000000. Il semble que System.arraycopy gagne définitivement avec des tableaux plus grands.
Comme c'est étrange!
Merci Daren d'avoir signalé que les références se copient différemment. Cela en a fait un problème beaucoup plus intéressant!
la source
Arrays.copyOf(T[], int)
est plus facile à lire. En interne, il utiliseSystem.arraycopy()
ce qui est un appel natif.Vous ne pouvez pas l'obtenir plus rapidement!
la source
copyOf
ne peut pas toujours remplacerarraycopy
, mais c'est approprié pour ce cas d'utilisation.Cela dépend de la machine virtuelle, mais System.arraycopy devrait vous fournir le plus proche possible des performances natives.
J'ai travaillé pendant 2 ans en tant que développeur java pour les systèmes embarqués (où les performances sont une priorité absolue) et partout où System.arraycopy pouvait être utilisé, je l'ai principalement utilisé / vu utilisé dans du code existant. Il est toujours préférable aux boucles lorsque les performances sont un problème. Si les performances ne sont pas un gros problème, je suivrais la boucle. Beaucoup plus facile à lire.
la source
Arrays.copy
n'existe pas,Arrays.copyOf
est une fonction de bibliothèque.Au lieu de me fier à des spéculations et peut-être à des informations obsolètes, j'ai exécuté des tests de étrier. En fait, Caliper est livré avec quelques exemples, dont un
CopyArrayBenchmark
qui mesure exactement cette question! Tout ce que tu as à faire c'est courirMes résultats sont basés sur la VM serveur 64 bits Java HotSpot (TM) d'Oracle, 1.8.0_31-b13, fonctionnant sur un MacBook Pro mi-2010 (macOS 10.11.6 avec Intel Arrandale i7, 8 Gio de RAM). Je ne pense pas qu'il soit utile de publier les données de synchronisation brutes. Je vais plutôt résumer les conclusions avec les visualisations à l'appui.
En résumé:
for
boucle manuelle pour copier chaque élément dans un tableau nouvellement instancié n'est jamais avantageux, que ce soit pour des tableaux courts ou des tableaux longs.Arrays.copyOf(array, array.length)
etarray.clone()
sont tous les deux toujours rapides. Ces deux techniques sont presque identiques en performance; celui que vous choisissez est une question de goût.System.arraycopy(src, 0, dest, 0, src.length)
est presque aussi rapide que et , mais pas tout à fait systématiquement. (Voir le cas pour 50000 s.) À cause de cela, et de la verbosité de l'appel, je recommanderais si vous avez besoin d'un contrôle précis sur quels éléments sont copiés et où.Arrays.copyOf(array, array.length)
array.clone()
int
System.arraycopy()
Voici les graphiques de synchronisation:
la source
L'exécution de méthodes natives comme
Arrays.copyOf(T[], int)
cela a une surcharge, mais cela ne signifie pas que ce n'est pas rapide car vous l'exécutez en utilisant JNI.Le moyen le plus simple est d'écrire un benchmark et un test.
Vous pouvez vérifier que
Arrays.copyOf(T[], int)
c'est plus rapide que votrefor
boucle normale .Le code de référence d' ici : -
System.arraycopy()
utilise JNI (Java Native Interface) pour copier un tableau (ou des parties de celui-ci), il est donc extrêmement rapide, comme vous pouvez le confirmer icila source
System.arraycopy
ne l'utilise pas.System.arraycopy
n'utilise pas JNI, qui sert uniquement à appeler des bibliothèques tierces. Au lieu de cela, il s'agit d'un appel natif, ce qui signifie qu'il existe une implémentation native dans la machine virtuelle.Il n'est pas possible que ce
Arrays.copyOf
soit plus rapide queSystem.arraycopy
puisqu'il s'agit de la mise en œuvre decopyOf
:la source
System.arraycopy()
est un appel natif qui effectue une opération de copie directement en mémoire. Une copie de mémoire unique serait toujours plus rapide que votre boucle forla source