Soru Java Büyük Dosyaları Disk IO Performansı


Sabit diskimde iki (2GB) dosyam var ve bunları birbirleriyle karşılaştırmak istiyorum:

  • Orijinal dosyaları Windows gezgini ile kopyalama yaklaşık sürer. 2-4 dakika (okuma ve yazma - aynı fiziksel ve mantıksal disk üzerinde).
  • İle okuma java.io.FileInputStream iki baytlık bayt bazında bayt dizilerini 20+ dakika ile karşılaştırır.
  • java.io.BufferedInputStream arabellek 64kb, dosyalar yığın halinde okunur ve sonra karşılaştırılır.
  • Karşılaştırma yapıldığı gibi sıkı bir döngüdür

    int numRead = Math.min(numRead[0], numRead[1]);
    for (int k = 0; k < numRead; k++)
    {
       if (buffer[1][k] != buffer[0][k])
       {
          return buffer[0][k] - buffer[1][k];
       }
    }
    

Bunu hızlandırmak için ne yapabilirim? NIO'nun daha sonra düz akışları olması daha mı hızlı? Java, DMA / SATA teknolojilerini kullanamıyor ve bunun yerine bazı yavaş OS-API çağrıları yapıyor mu?

DÜZENLE:
Cevaplar için teşekkürler. Onlara dayalı bazı deneyler yaptım. Andreas'ın gösterdiği gibi

akışları veya nio yaklaşımlar çok farklı değildir.
  Daha önemli olan, doğru arabellek boyutu.

Bu kendi deneylerim tarafından onaylandı. Dosyalar büyük parçalar halinde okunurken, ek tamponlar bile (BufferedInputStream) hiçbir şey vermeyin. Karşılaştırmayı optimize etmek mümkün ve en iyi sonuçları 32-kat açma ile elde ettim, ancak zaman harcaması disk okumaya kıyasla küçüktü, dolayısıyla hız küçüktür. Yapabileceğim hiçbir şey yok gibi görünüyor;


16
2018-06-08 10:54


Menşei


Not: Varsayılan olarak, DMA / SATA teknolojileri tüm dosya I / O işlemlerinde (modern işletim sistemlerinde) işletim sistemi tarafından yönetilir. - ivan_ivanovich_ivanoff


Cevaplar:


İki farklı 3,8 gb dosyayı arabellek boyutları 8 kb ile 1 MB arasında karşılaştırmak için üç farklı yöntem denedim. İlk ilk yöntem sadece iki tamponlu giriş akışı kullanmıştır

ikinci yaklaşım, iki farklı dişte okuyan ve üçüncü birde karşılaştırılan bir iplik dizisi kullanır. Bu yüksek bir cpu kullanımı pahasına biraz daha yüksek çıktı. iş parçacığının yönetilmesi, kısa süren görevlerle çok fazla uğraşmaktadır.

üçüncü yaklaşım laginimaineb tarafından yayınlanan nio, kullanır

Gördüğünüz gibi, genel yaklaşım çok farklı değil. daha önemli olan, doğru tampon boyutudur.

thread kullanarak daha az 1 bayt okuduğum garip olan şey. hatayı zor göremedim.

comparing just with two streams
I was equal, even after 3684070360 bytes and reading for 704813 ms (4,98MB/sec * 2) with a buffer size of 8 kB
I was equal, even after 3684070360 bytes and reading for 578563 ms (6,07MB/sec * 2) with a buffer size of 16 kB
I was equal, even after 3684070360 bytes and reading for 515422 ms (6,82MB/sec * 2) with a buffer size of 32 kB
I was equal, even after 3684070360 bytes and reading for 534532 ms (6,57MB/sec * 2) with a buffer size of 64 kB
I was equal, even after 3684070360 bytes and reading for 422953 ms (8,31MB/sec * 2) with a buffer size of 128 kB
I was equal, even after 3684070360 bytes and reading for 793359 ms (4,43MB/sec * 2) with a buffer size of 256 kB
I was equal, even after 3684070360 bytes and reading for 746344 ms (4,71MB/sec * 2) with a buffer size of 512 kB
I was equal, even after 3684070360 bytes and reading for 669969 ms (5,24MB/sec * 2) with a buffer size of 1024 kB
comparing with threads
I was equal, even after 3684070359 bytes and reading for 602391 ms (5,83MB/sec * 2) with a buffer size of 8 kB
I was equal, even after 3684070359 bytes and reading for 523156 ms (6,72MB/sec * 2) with a buffer size of 16 kB
I was equal, even after 3684070359 bytes and reading for 527547 ms (6,66MB/sec * 2) with a buffer size of 32 kB
I was equal, even after 3684070359 bytes and reading for 276750 ms (12,69MB/sec * 2) with a buffer size of 64 kB
I was equal, even after 3684070359 bytes and reading for 493172 ms (7,12MB/sec * 2) with a buffer size of 128 kB
I was equal, even after 3684070359 bytes and reading for 696781 ms (5,04MB/sec * 2) with a buffer size of 256 kB
I was equal, even after 3684070359 bytes and reading for 727953 ms (4,83MB/sec * 2) with a buffer size of 512 kB
I was equal, even after 3684070359 bytes and reading for 741000 ms (4,74MB/sec * 2) with a buffer size of 1024 kB
comparing with nio
I was equal, even after 3684070360 bytes and reading for 661313 ms (5,31MB/sec * 2) with a buffer size of 8 kB
I was equal, even after 3684070360 bytes and reading for 656156 ms (5,35MB/sec * 2) with a buffer size of 16 kB
I was equal, even after 3684070360 bytes and reading for 491781 ms (7,14MB/sec * 2) with a buffer size of 32 kB
I was equal, even after 3684070360 bytes and reading for 317360 ms (11,07MB/sec * 2) with a buffer size of 64 kB
I was equal, even after 3684070360 bytes and reading for 643078 ms (5,46MB/sec * 2) with a buffer size of 128 kB
I was equal, even after 3684070360 bytes and reading for 865016 ms (4,06MB/sec * 2) with a buffer size of 256 kB
I was equal, even after 3684070360 bytes and reading for 716796 ms (4,90MB/sec * 2) with a buffer size of 512 kB
I was equal, even after 3684070360 bytes and reading for 652016 ms (5,39MB/sec * 2) with a buffer size of 1024 kB

kullanılan kod:

import junit.framework.Assert;
import org.junit.Before;
import org.junit.Test;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.Arrays;
import java.util.concurrent.*;

public class FileCompare {

    private static final int MIN_BUFFER_SIZE = 1024 * 8;
    private static final int MAX_BUFFER_SIZE = 1024 * 1024;
    private String fileName1;
    private String fileName2;
    private long start;
    private long totalbytes;

    @Before
    public void createInputStream() {
        fileName1 = "bigFile.1";
        fileName2 = "bigFile.2";
    }

    @Test
    public void compareTwoFiles() throws IOException {
        System.out.println("comparing just with two streams");
        int currentBufferSize = MIN_BUFFER_SIZE;
        while (currentBufferSize <= MAX_BUFFER_SIZE) {
            compareWithBufferSize(currentBufferSize);
            currentBufferSize *= 2;
        }
    }

    @Test
    public void compareTwoFilesFutures() 
            throws IOException, ExecutionException, InterruptedException {
        System.out.println("comparing with threads");
        int myBufferSize = MIN_BUFFER_SIZE;
        while (myBufferSize <= MAX_BUFFER_SIZE) {
            start = System.currentTimeMillis();
            totalbytes = 0;
            compareWithBufferSizeFutures(myBufferSize);
            myBufferSize *= 2;
        }
    }

    @Test
    public void compareTwoFilesNio() throws IOException {
        System.out.println("comparing with nio");
        int myBufferSize = MIN_BUFFER_SIZE;
        while (myBufferSize <= MAX_BUFFER_SIZE) {
            start = System.currentTimeMillis();
            totalbytes = 0;
            boolean wasEqual = isEqualsNio(myBufferSize);

            if (wasEqual) {
                printAfterEquals(myBufferSize);
            } else {
                Assert.fail("files were not equal");
            }

            myBufferSize *= 2;
        }

    }

    private void compareWithBufferSize(int myBufferSize) throws IOException {
        final BufferedInputStream inputStream1 =
                new BufferedInputStream(
                        new FileInputStream(new File(fileName1)),
                        myBufferSize);
        byte[] buff1 = new byte[myBufferSize];
        final BufferedInputStream inputStream2 =
                new BufferedInputStream(
                        new FileInputStream(new File(fileName2)),
                        myBufferSize);
        byte[] buff2 = new byte[myBufferSize];
        int read1;

        start = System.currentTimeMillis();
        totalbytes = 0;
        while ((read1 = inputStream1.read(buff1)) != -1) {
            totalbytes += read1;
            int read2 = inputStream2.read(buff2);
            if (read1 != read2) {
                break;
            }
            if (!Arrays.equals(buff1, buff2)) {
                break;
            }
        }
        if (read1 == -1) {
            printAfterEquals(myBufferSize);
        } else {
            Assert.fail("files were not equal");
        }
        inputStream1.close();
        inputStream2.close();
    }

    private void compareWithBufferSizeFutures(int myBufferSize)
            throws ExecutionException, InterruptedException, IOException {
        final BufferedInputStream inputStream1 =
                new BufferedInputStream(
                        new FileInputStream(
                                new File(fileName1)),
                        myBufferSize);
        final BufferedInputStream inputStream2 =
                new BufferedInputStream(
                        new FileInputStream(
                                new File(fileName2)),
                        myBufferSize);

        final boolean wasEqual = isEqualsParallel(myBufferSize, inputStream1, inputStream2);

        if (wasEqual) {
            printAfterEquals(myBufferSize);
        } else {
            Assert.fail("files were not equal");
        }
        inputStream1.close();
        inputStream2.close();
    }

    private boolean isEqualsParallel(int myBufferSize
            , final BufferedInputStream inputStream1
            , final BufferedInputStream inputStream2)
            throws InterruptedException, ExecutionException {
        final byte[] buff1Even = new byte[myBufferSize];
        final byte[] buff1Odd = new byte[myBufferSize];
        final byte[] buff2Even = new byte[myBufferSize];
        final byte[] buff2Odd = new byte[myBufferSize];
        final Callable<Integer> read1Even = new Callable<Integer>() {
            public Integer call() throws Exception {
                return inputStream1.read(buff1Even);
            }
        };
        final Callable<Integer> read2Even = new Callable<Integer>() {
            public Integer call() throws Exception {
                return inputStream2.read(buff2Even);
            }
        };
        final Callable<Integer> read1Odd = new Callable<Integer>() {
            public Integer call() throws Exception {
                return inputStream1.read(buff1Odd);
            }
        };
        final Callable<Integer> read2Odd = new Callable<Integer>() {
            public Integer call() throws Exception {
                return inputStream2.read(buff2Odd);
            }
        };
        final Callable<Boolean> oddEqualsArray = new Callable<Boolean>() {
            public Boolean call() throws Exception {
                return Arrays.equals(buff1Odd, buff2Odd);
            }
        };
        final Callable<Boolean> evenEqualsArray = new Callable<Boolean>() {
            public Boolean call() throws Exception {
                return Arrays.equals(buff1Even, buff2Even);
            }
        };

        ExecutorService executor = Executors.newCachedThreadPool();
        boolean isEven = true;
        Future<Integer> read1 = null;
        Future<Integer> read2 = null;
        Future<Boolean> isEqual = null;
        int lastSize = 0;
        while (true) {
            if (isEqual != null) {
                if (!isEqual.get()) {
                    return false;
                } else if (lastSize == -1) {
                    return true;
                }
            }
            if (read1 != null) {
                lastSize = read1.get();
                totalbytes += lastSize;
                final int size2 = read2.get();
                if (lastSize != size2) {
                    return false;
                }
            }
            isEven = !isEven;
            if (isEven) {
                if (read1 != null) {
                    isEqual = executor.submit(oddEqualsArray);
                }
                read1 = executor.submit(read1Even);
                read2 = executor.submit(read2Even);
            } else {
                if (read1 != null) {
                    isEqual = executor.submit(evenEqualsArray);
                }
                read1 = executor.submit(read1Odd);
                read2 = executor.submit(read2Odd);
            }
        }
    }

    private boolean isEqualsNio(int myBufferSize) throws IOException {
        FileChannel first = null, seconde = null;
        try {
            first = new FileInputStream(fileName1).getChannel();
            seconde = new FileInputStream(fileName2).getChannel();
            if (first.size() != seconde.size()) {
                return false;
            }
            ByteBuffer firstBuffer = ByteBuffer.allocateDirect(myBufferSize);
            ByteBuffer secondBuffer = ByteBuffer.allocateDirect(myBufferSize);
            int firstRead, secondRead;
            while (first.position() < first.size()) {
                firstRead = first.read(firstBuffer);
                totalbytes += firstRead;
                secondRead = seconde.read(secondBuffer);
                if (firstRead != secondRead) {
                    return false;
                }
                if (!nioBuffersEqual(firstBuffer, secondBuffer, firstRead)) {
                    return false;
                }
            }
            return true;
        } finally {
            if (first != null) {
                first.close();
            }
            if (seconde != null) {
                seconde.close();
            }
        }
    }

    private static boolean nioBuffersEqual(ByteBuffer first, ByteBuffer second, final int length) {
        if (first.limit() != second.limit() || length > first.limit()) {
            return false;
        }
        first.rewind();
        second.rewind();
        for (int i = 0; i < length; i++) {
            if (first.get() != second.get()) {
                return false;
            }
        }
        return true;
    }

    private void printAfterEquals(int myBufferSize) {
        NumberFormat nf = new DecimalFormat("#.00");
        final long dur = System.currentTimeMillis() - start;
        double seconds = dur / 1000d;
        double megabytes = totalbytes / 1024 / 1024;
        double rate = (megabytes) / seconds;
        System.out.println("I was equal, even after " + totalbytes
                + " bytes and reading for " + dur
                + " ms (" + nf.format(rate) + "MB/sec * 2)" +
                " with a buffer size of " + myBufferSize / 1024 + " kB");
    }
}

14
2018-06-11 10:20



+1. Aferin, Andreas. Aynı veri ve makinede 64MB (evet, megabayt) arabelleği çalıştırmak için sizi rahatsız edebilir miyim? @alamar, arama sonuçlarının eksikliğinden dolayı mükemmel sonuçlar doğuracağını düşünüyor, ki bu da kendi sonuçlarına gerçek dünya deneyimini daha yakın bir şekilde kuşkuluyorum. - Stu Thompson
Deneylerim de, testlerinizde olduğu gibi 64kb / 128kb gibi tampon boyutlarının optimum olduğunu gösterdi. Bir adımda 64kb'lik bir bayt [] değerini okumak için, FileInputStream'in üstünde BufferedInputStream kullanırsam veya kullanmazsam, aynı şeyi gerçekleştirmezler. Sorunum olsa da, dosya bir kez okunduktan sonra, disk önbelleklemesi nedeniyle zamanlamalar küçülüyor. - Peter Kofler
Ve işletim sisteminde 'yazılabilir blok boyutu' olarak yapılandırılan nedir? - VitalyT


Böyle büyük dosyalar ile ile daha iyi bir performans elde edeceksin java.nio.

Ek olarak, java akışları ile tek baytları okumak çok yavaş olabilir. Bir bayt dizisi kullanmak (kendi deneyimlerimden 2-6K öğeleri, platform / uygulamaya özgü göründüğü için ymmv) okuma performansınızı akışlarla önemli ölçüde geliştirecektir.


7
2018-06-08 11:00



Ben bundan korkuyordum. Kod oldukça eski ve uzun zamandır iyi çalıştı, ama dosyalar her zaman büyümeye eğilimli ... - Peter Kofler
Bir MappedByteBuffer (işletim sisteminin sanal bellek sayfalama sistemini kullanan) ile devam ederseniz, koddaki değişiklikleri en aza indirebilir ve hızda önemli gelişmeler elde edebilirsiniz. Daha hızlı "büyüklük emirleri" tahmininde bulunacağım. - Stu Thompson
NIO kafa karıştırıcı olabilir, en yüksek performansı elde etmek için ByteBuffer.allocateDirect () ile başlamak isteyeceksiniz (bu noktada bellek eşlemeli dosyaları kullanır). java.sun.com/javase/6/docs/api/java/nio/ByteBuffer.html - AgileJon
NIO'lu G / Ç dosyası çok karışık değil; java.io. Kafanızı karıştırmak istiyorsanız asenkron ağ iletişimine atlayın. - Stu Thompson


Dosyaları Java ile okumak ve yazmak aynı hızda olabilir. Kullanabilirsiniz FileChannels. Dosyaları karşılaştırmaya gelince, bayt ile bayt arasında çok fazla zaman harcanacak. İşte FileChannels ve ByteBuffers kullanarak bir örnek (daha da optimize edilmiş olabilir):

public static boolean compare(String firstPath, String secondPath, final int BUFFER_SIZE) throws IOException {
    FileChannel firstIn = null, secondIn = null;
    try {
        firstIn = new FileInputStream(firstPath).getChannel();
        secondIn = new FileInputStream(secondPath).getChannel();
        if (firstIn.size() != secondIn.size())
            return false;
        ByteBuffer firstBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
        ByteBuffer secondBuffer = ByteBuffer.allocateDirect(BUFFER_SIZE);
        int firstRead, secondRead;
        while (firstIn.position() < firstIn.size()) {
            firstRead = firstIn.read(firstBuffer);
            secondRead = secondIn.read(secondBuffer);
            if (firstRead != secondRead)
                return false;
            if (!buffersEqual(firstBuffer, secondBuffer, firstRead))
                return false;
        }
        return true;
    } finally {
        if (firstIn != null) firstIn.close();
        if (secondIn != null) firstIn.close();
    }
}

private static boolean buffersEqual(ByteBuffer first, ByteBuffer second, final int length) {
    if (first.limit() != second.limit())
        return false;
    if (length > first.limit())
        return false;
    first.rewind(); second.rewind();
    for (int i=0; i<length; i++)
        if (first.get() != second.get())
            return false;
    return true;
}

6
2018-06-08 11:01



bayt başına bayttan daha hızlı karşılaştırma hakkında herhangi bir fikriniz var mı? - Peter Kofler
Şey ... Dediğim gibi, FileChannels (ve ByteBuffers) kullanabilirsiniz. İki 1.6GB dosyayı 60 saniyede karşılaştırabilirim. Kullandığım kodu eklemek için orijinal gönderimi düzenledim. - laginimaineb
Bu örneği beğendim. onları karşılaştırmak için WHOLE dosyalarını dizilere okumaya gerek yoktur. aksi halde, 2 bayt okumak yerine, bayt 1'de aynı olabilecek dosyaları okumak için çok zaman harcıyordunuz. - John Gardner


NIO karşılaştırma fonksiyonunuzu değiştirdikten sonra aşağıdaki sonuçları elde ederim.

I was equal, even after 4294967296 bytes and reading for 304594 ms (13.45MB/sec * 2) with a buffer size of 1024 kB
I was equal, even after 4294967296 bytes and reading for 225078 ms (18.20MB/sec * 2) with a buffer size of 4096 kB
I was equal, even after 4294967296 bytes and reading for 221351 ms (18.50MB/sec * 2) with a buffer size of 16384 kB

Not: Bu, dosyaların 37 MB / s hızında okunacağı anlamına gelir

Aynı şeyi daha hızlı sürmek

I was equal, even after 4294967296 bytes and reading for 178087 ms (23.00MB/sec * 2) with a buffer size of 1024 kB
I was equal, even after 4294967296 bytes and reading for 119084 ms (34.40MB/sec * 2) with a buffer size of 4096 kB
I was equal, even after 4294967296 bytes and reading for 109549 ms (37.39MB/sec * 2) with a buffer size of 16384 kB

Not: Bu, dosyaların 74,8 MB / s hızında okunacağı anlamına gelir

private static boolean nioBuffersEqual(ByteBuffer first, ByteBuffer second, final int length) {
    if (first.limit() != second.limit() || length > first.limit()) {
        return false;
    }
    first.rewind();
    second.rewind();
    int i;
    for (i = 0; i < length-7; i+=8) {
        if (first.getLong() != second.getLong()) {
            return false;
        }
    }
    for (; i < length; i++) {
        if (first.get() != second.get()) {
            return false;
        }
    }
    return true;
}

6
2018-06-12 06:58





Aşağıda, java'da bir dosyayı okumaya yönelik farklı yolların göreceli yararları hakkında iyi bir makale yer almaktadır. Bazı kullanımlarda olabilir:

Dosyaları nasıl hızlı okunur


5
2018-06-08 11:08



Bağlantı için bir Milyar teşekkürler !!!!!!!!!! - Ahamed


Bir göz atabilirsin G / Ç Ayarı için Suns Makale (şimdiden biraz tarihli), belki de oradaki örnekler ile kodunuz arasında benzerlikler bulabilirsiniz. Ayrıca bir göz atın java.nio java.io'dan daha hızlı I / O öğeleri içeren paket. Dobbs Journal'ın oldukça hoş bir makalesi var. java.nio kullanarak yüksek performanslı IO.

Öyleyse, kodunuzu hızlandırmanıza yardımcı olabilecek diğer örnekler ve ayarlama ipuçları vardır.

Dahası, Arrays sınıfı bayt dizilerini karşılaştırmak için yöntemler inşa etmek, belki bunlar da işleri daha hızlı yapmak ve döngüsünü biraz temizlemek için kullanılabilir.


2
2018-06-08 11:06



Arrays sınıfı ile iyi bir fikir. Kapağın altında sıkı bir döngüde byte-bilge karşılaştırma yapıyor. Şu anda kullandığım 32 kat açılı döngü kadar hızlı değil, ancak kodu önemli ölçüde kısaltır. IO performansını test etmek için. - Peter Kofler


Daha iyi bir karşılaştırma için iki dosyayı bir kerede kopyalamayı deneyin. Bir sabit sürücü, bir dosyayı iki okumadan çok daha verimli bir şekilde okuyabilir (başın ileri ve geri gitmesi gerektiğinden) Bunu azaltmanın bir yolu daha büyük tamponları kullanmaktır, örn. 16 MB. ByteBuffer ile.

ByteBuffer ile, uzun değerleri getLong () ile karşılaştırarak bir kerede 8 bayt karşılaştırırsınız.

Java'nız verimli ise, çalışmaların çoğu okuma / yazma için disk / işletim sistemindedir, bu yüzden başka bir dil kullanmaktan çok daha yavaş olmamalıdır (disk / OS darboğazdır)

Kodunuzda bir hata olmadığını belirleyene kadar Java'nın yavaş olduğunu düşünmeyin.


1
2018-06-09 06:32



Uzun süreleri, uçmak için inşa edilmeleri gerektiği için karşılaştırıyorum. Döngüyü 8 kez daha hızlı açmak gerekmez mi? (veya deneylerimde optimal görünen 32 kat). "Seçme bozuk değil" diye katılıyorum, yani IO hızlı olacak, ama geçmişten (ve belki de artık doğru değil) Java IO'nun Pascal / C IO'dan çok daha yavaş olduğunu biliyorum. Ancak çoğu uygulama düz IO'dan daha fazlasını içerdiği için, Java bugünlerde hala daha hızlıdır. - Peter Kofler
Doğrudan ByteBuffers için, Java'da uzunlar oluşturulmaz. Bu JNI için sadece bir çağrıdır (C kodunda oluşturulabilirler) Her bayt için bir çağrıdan daha hızlı olduğundan eminim. Daha sonraki bir cevapta, bu dosyanın, aynı diskten yeterince hızlı olabilen iki dosyayı okuyarak @ 74,8 MB / s olduğunu gösterdim. - Peter Lawrey
@Peter Lawrey: Bu büyük tamponları test ettiniz mi? O sen miydin bana söyle OS'nin birden fazla dosyaya önceden sahip olabileceği ve bunu yaparken dahili olarak büyük arabellekleri kullandığı anlaşılıyor. - maaartinus
@maaartinus, yüksek oranda parçalanmış bir diske sahipse, birden fazla dosyayı bir kerede okumak, kafa hareketini geliştirebilir (daha iyi seçenekler sunarak). Ancak eğer değilse, başı olabildiğince az hareket ettirmek size en iyi performansı verecektir. - Peter Lawrey


Bu yazıya bağlı birçok makalenin gerçekten çıkmış olduğunu fark ettim (ayrıca çok anlayışlı şeyler de var). 2001'den bağlantılı bazı makaleler var ve bilgiler en iyi şekilde sorgulanabilir. Mekanik sempati Martin Thompson 2011 yılında bu konuda biraz yazdı. Lütfen bunun için ne yazdığını ve bunun teorisi için bakın.

NIO'nun ya da NIO'nun performansla çok az ilgisi olduğunu buldum. Çıktı tamponlarınızın boyutuyla ilgili çok daha fazla şey var (okunan bayt dizisi). NIO, sihirli bir web skalası sosuna dönüşmez.

Martin'in örneklerini alıp 1.0 dönemi OutputStream'i kullanıp çığlık atmayı başardım. NIO da hızlıdır, ancak en büyük gösterge, bellek eşlemeli bir NIO'yu kullanmanızın gerekmediği sürece, NIO'yu kullanıp kullanmadığınızı değil, çıktı tamponunun büyüklüğüdür. :)

Bu konuda güncel bilgilere ulaşmak isterseniz, bkz.

http://mechanical-sympathy.blogspot.com/2011/12/java-sequential-io-performance.html

NIO'nun ne kadar fark yaratmadığını görmek istiyorsanız (daha hızlı olan düzenli IO'yu kullanarak örnekler yazabildiğim gibi) şunu görün:

http://www.dzone.com/links/fast_java_io_nio_is_always_faster_than_fileoutput.html

Yeni Windows dizüstü bilgisayarımda hızlı bir sabit disk, SSD, bir EC2 xlarge ve bir EC2 4x büyük IOPS / yüksek hızlı I / O (ve yakında büyük bir disk NAS fiber disk ile) benim varsayım test dizisi) böylece çalışır (daha küçük EC2 örnekleri için bununla ilgili bazı sorunlar vardır, ancak performansa önem veriyorsanız ... küçük bir EC2 örneğini mi kullanacaksınız?). Gerçek donanım kullanıyorsanız, şimdiye kadar yaptığım testlerde, geleneksel IO her zaman kazanır. Yüksek / IO EC2 kullanırsanız, bu aynı zamanda açık bir kazanandır. Güçlendirilmiş EC2 örneklerinde kullanırsanız, NIO kazanabilir.

Kıyaslama için herhangi bir ikame yoktur.

Her neyse, uzman değilim, sadece Sir Martin Thompson'ın blog mesajında ​​yazdığı çerçeveyi kullanarak bazı ampirik testler yaptım.

Bunu bir sonraki adıma aldım ve kullandım Files.newInputStream (JDK 7’den) ile TransferQueue Java I / O çığlığı oluşturmak için bir reçete oluşturmak (küçük EC2 örneklerinde bile). Tarif, Boon için bu belgenin alt kısmında bulunabilir.https://github.com/RichardHightower/boon/wiki/Auto-Growable-Byte-Buffer-like-a-ByteBuilder). Bu, geleneksel bir OutputStream kullanmamı, ancak daha küçük EC2 örneklerinde iyi çalışan bir şey kullanmamı sağlar. (Ben Boon'un ana yazarıyım. Ama yeni yazarları kabul ediyorum. Maaş saatte 0 dolar. Ama iyi haber şu ki, istediğin zaman ödemeni ikiye katlayabilirim.)

2 sentim.

Bunu görmek için buna bakın TransferQueue önemli. http://php.sabscape.com/blog/?p=557

Anahtar öğrenenler:

  1. Performansı önemsemiyorsanız, asla, asla kullanmayın BufferedOutputStream.
  2. NIO her zaman performansa eşit değildir.
  3. Tampon boyutu en çok önemlidir.
  4. Yüksek hızlı yazma için geri dönüşüm arabellekleri çok önemlidir.
  5. GC, yüksek hızlı yazmalarda performansınızı etkileyebilir.
  6. Harcanan arabellekleri yeniden kullanmak için bazı mekanizmalara sahip olmanız gerekir.

1
2017-11-09 22:48





DMA / SATA, donanım / düşük seviyeli teknolojilerdir ve herhangi bir programlama dili tarafından görülmemektedir.

Bellek eşlenmiş giriş / çıkış için java.nio kullanmalısınız, inanıyorum.

Bu dosyaları bir baytla okumadığınızdan emin misiniz? Bu savurgan olurdu, bunu blok-by-block yapmayı öneririm ve her blok, arama yapmayı en aza indirmek için 64 megabayt gibi bir şey olmalıdır.


0
2018-06-08 11:03



64kb demek istiyorsun, evet? megabayt değil mi? - Stu Thompson
Neden, megabaytlar, eğer paranız varsa (bugün yapabilirsiniz). İki dosyayı 64 kilobayt ile okumak, IMO'nun iyi bir fikir olmadığını çünkü sürücünün sürekli olarak arama yapmasını beklerdi. - alamar
Oh, bir tür olduğunu düşündüm. Bu bana erken optimizasyon gibi kokuyor. Böyle büyük bir değeri sorgularım çünkü okuma 64MB'nin tamamı okunana kadar bloke olacak ve sonuçta daha yavaş bir performans sergileyecek. Sadece gerçek performans metrikleri kesin olarak gösterilecek, ancak ben sizin teorinize çok şüpheyle yaklaşıyorum. - Stu Thompson
Testleri yap, grafiği çiz. - alamar
Ardışık veri 64mb okuma yavaş değil. - Kimble


Giriş akışında arabelleği birkaç megabayta kadar ayarlamayı deneyin.


-1
2018-06-13 13:47