MappedByteBuffer
(Memory-Mapped-Datei in Java) Um zu versuchen, schrieb ich eine einfache wc -l
(Textdatei Zeilenzahl) Demo:Warum ist dieses Programm "Zeilenanzahl" in Java langsam? Mit MappedByteBuffer
int wordCount(String fileName) throws IOException {
FileChannel fc = new RandomAccessFile(new File(fileName), "r").getChannel();
MappedByteBuffer mem = fc.map(FileChannel.MapMode.READ_ONLY, 0, fc.size());
int nlines = 0;
byte newline = '\n';
for(long i = 0; i < fc.size(); i++) {
if(mem.get() == newline)
nlines += 1;
}
return nlines;
}
Ich habe versucht, dies auf eine Datei von etwa 15 MB (15.008.641 Byte), und 100k Linien. Auf meinem Laptop dauert es etwa 13.8 sec
. Warum ist es so langsam?
kompletter Klassencode ist hier: http://pastebin.com/t8PLRGMa
für den Hinweis, ich schrieb die gleiche Idee in C: http://pastebin.com/hXnDvZm6
Es läuft in etwa 28 ms oder 490 times faster
.
Aus Neugier, schrieb ich auch eine Scala-Version mit im Wesentlichen den gleichen Algorithmus und APIs wie in Java. Es läuft 10 times faster
, was darauf hindeutet, es ist definitiv etwas seltsam los.
Aktualisierung: Die Datei wird vom Betriebssystem zwischengespeichert, daher ist keine Ladezeit für die Datenträger erforderlich.
Ich wollte Speicherzuordnung für den wahlfreien Zugriff auf größere Dateien verwenden, die nicht in RAM passen. Deshalb benutze ich nicht nur einen BufferedReader.
Java-Version: OpenJDK 1.8.0 Plattform: Linux 4.1.16 – cidermole
'MappedByteBuffer' ist die falsche Sache zu verwenden, Ihr Programm braucht nichts anderes als eine Ebene' BufferedReader '. Sie verwenden keine der erweiterten Funktionen des 'MappedByteBuffer', also warum? –
Ich tippte eine Antwort, aber die Frage war geschlossen. Ihr Code ist langsam, weil Byte für Byte gelesen wird, und das ist sehr langsam. Lesen Sie Puffer nach Puffer, und die Leistung wird drastisch erhöht. Wenn Sie beispielsweise https://gist.github.com/jnizet/21341d48f631b7f10bc657e560c0f2de verwenden, beträgt die aufgewendete Zeit 50493us. vs 8646279us. für deine Originalversion. Aber ich stimme zu, dass ein BufferedInputStream sowieso einfacher wäre. –