2011-07-06 12 views
0

Je dois écrire un algorithme pour le tri externe en Java, en utilisant uniquement la RAM JVM (essentiellement, je ne peux pas mapper les fichiers). Donc, la première partie que je veux faire est de lire les données d'un fichier en morceaux.Optimisation du tri externe

J'ai trouvé this tutorial.

Le problème est que le tutoriel est sur la lecture byte s, et je dois lire int s. Je ne suis pas sûr comment IntBuffer est mis en œuvre, mais je pense que c'est un emballage autour d'un tampon d'octets. Étant donné ce fait, ai-je raison que la chose la plus rapide que je puisse faire est d'utiliser la méthode "FileChannel avec ByteBuffer direct et byte array" du tutoriel (code ci-dessous), puis créer un tableau séparé avec int s, que je "manuellement" obtenir des octets en utilisant des opérations de bits?

FileInputStream f = new FileInputStream(name); 
FileChannel ch = f.getChannel(); 
ByteBuffer bb = ByteBuffer.allocateDirect(BIGSIZE); 
byte[] barray = new byte[SIZE]; 
long checkSum = 0L; 
int nRead, nGet; 
while ((nRead=ch.read(bb)) != -1) 
{ 
    if (nRead == 0) 
     continue; 
    bb.position(0); 
    bb.limit(nRead); 
    while(bb.hasRemaining()) 
    { 
     nGet = Math.min(bb.remaining(), SIZE); 
     bb.get(barray, 0, nGet); 
     for (int i=0; i<nGet; i++) 
      checkSum += barray[i]; 
    } 
    bb.clear(); 
} 

Aussi, j'ai une petite question supplémentaire: Je veux lire et trier en parallèle (déchets d'E/S d'un beaucoup de temps), dois-je utiliser une approche tout à fait différente, ou utilise cette méthode dans un fil et le tri dans l'autre fil bonne approche? Je veux vraiment me battre pour chaque nanoseconde de performance.

+6

Je pense que vous devriez écrire quelque chose qui fonctionne d'abord, et * ensuite * se battre pour les nanosecondes de performance. Comment allez-vous être capable de prédire ce qui est plus rapide quand vous ne pouvez pas le mesurer? –

+1

qu'est ce que "JVM RAM"? –

Répondre

1
new DataInputStream(new BufferedInputStream(new FileInputStream(file))); 

puis d'utiliser readInt(). Ce sera aussi rapide que tout ce que vous pouvez faire avec FileChannels à court d'un fichier mappé, et ils sont seulement environ 20% plus rapide que les E/S normales.

Les buffers d'octets directs ne vous aideront pas non plus ici. Ils sont plus utiles lorsque vous ne voulez pas regarder ou modifier les données vous-même, vous ne faites que copier entre les canaux. Il sauve deux fois les données de la frontière JNI/Java, il reste juste à l'intérieur de la couche JNI. Ne s'applique pas à ce cas.

+0

Salut, merci pour votre réponse! Alors, qu'en est-il de la lecture asynchrone? Comment est-il mis en œuvre? Est-ce qu'il essaie de lire à l'avance, ou devrais-je initialiser un fil séparé pour lire à l'avance? Aussi, quelle est la taille du tampon par défaut? Merci pour votre aide! – nivwusquorum

+1

Il n'y a pas de lecture asynchrone en Java avant 1.7. Vous obtenez juste ce que le contrôleur de disque et le système d'exploitation font, ce qui est assez vaste: mise en cache, lecture anticipée, toutes sortes de choses. La taille du tampon par défaut pour BufferedInputStream est 8192 (bien que non spécifiée), ce qui devrait être adéquat: sinon, essayez de jouer avec, par exemple, de gros facteurs, par exemple. essayez 64k. – EJP

1

Si vous voulez vous battre pour toujours des performances de nano-seconde, achetez des disques plus rapides, par ex. en utilisant SSD ou RAID N ou les deux. Un lecteur SSD peut transférer des données jusqu'à 10 fois plus vite qu'un disque en mouvement. Cela fera beaucoup plus de différence que tout ce que vous pouvez faire en Java.