1

バッファリングされたリーダーメカニズムを介してログファイルを読み取っています。実行時間の合計はミリス単位です:12944、パフォーマンスを改善して今回を下げる方法を教えてください。nioはバッファリングされたリーダーよりもパフォーマンスが優れていることをアドバイスしてください。 !!ログファイルなのでファイルサイズは10MBです。これと同じことがnioでもどのように達成できるかについてもアドバイスしてください..!!

public class BufferedRedeem
{

    public static void main(String[] args)
    {

        BufferedReader br = null;
        long startTime = System.currentTimeMillis();

        try
        {
            String sCurrentLine;
            br = new BufferedReader(new FileReader("C://abc.log"));

            while ((sCurrentLine = br.readLine()) != null)
            {

            }
            long elapsedTime = System.currentTimeMillis() - startTime;

            System.out.println("Total execution time taken in millis: " + elapsedTime);
        }
        catch (IOException e)
        {
            e.printStackTrace();
        }
        finally
        {
            try
            {
                if (br != null)
                    br.close();
            }
            catch (IOException ex)
            {
                ex.printStackTrace();
            }
        }
    }
}
4

4 に答える 4

4

OPは、NIOを使用してこれを行う方法を知りたいと考えているためです。

ファイルが小さいので違いがわかりにくいですが、測定可能です。

public static void main(String... args) throws IOException {
    PrintWriter pw = new PrintWriter("abc.log");
    for (int i = 0; i < 100 * 1000; i++) {
        pw.println("0123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789");
    }
    pw.close();

    long start2 = System.nanoTime();
    int count2 = 0;
    BufferedReader br = new BufferedReader(new FileReader("abc.log"));
    while (br.readLine() != null) count2++;
    br.close();
    long time2 = System.nanoTime() - start2;
    System.out.printf("IO: Took %,d ms to read %,d lines%n", time2 / 1000 / 1000, count2);

    long start = System.nanoTime();
    FileChannel fc = new FileInputStream("abc.log").getChannel();
    ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size());
    fc.read(bb);
    fc.close();
    bb.flip();

    CharBuffer cb = ByteBuffer.allocateDirect(bb.remaining() * 2).order(ByteOrder.nativeOrder()).asCharBuffer();
    CharsetDecoder cd = Charset.forName("UTF-8").newDecoder();
    cd.decode(bb, cb, true);
    cb.flip();
    StringBuilder sb = new StringBuilder();
    int count = 0;
    while (cb.remaining() > 0) {
        char ch = cb.get();
        if (isEndOfLine(cb, ch)) {
            // process sb
            count++;
            sb.setLength(0);
        } else {
            sb.append(ch);
        }
    }
    long time = System.nanoTime() - start;
    System.out.printf("NIO as UTF-8: Took %,d ms to read %,d lines%n", time / 1000 / 1000, count);

    long start3 = System.nanoTime();
    FileChannel fc2 = new FileInputStream("abc.log").getChannel();
    MappedByteBuffer bb2 = fc2.map(FileChannel.MapMode.READ_ONLY, 0, fc2.size());
    bb.flip();
    StringBuilder sb3 = new StringBuilder();
    int count3 = 0;
    while (bb2.remaining() > 0) {
        char ch = (char) bb2.get();
        if (isEndOfLine(bb2, ch)) {
            // process sb
            count3++;
            sb3.setLength(0);
        } else {
            sb3.append(ch);
        }
    }
    fc2.close();
    long time3 = System.nanoTime() - start3;
    System.out.printf("NIO as ISO-8859-1: Took %,d ms to read %,d lines%n", time3 / 1000 / 1000, count3);


}

private static boolean isEndOfLine(CharBuffer cb, char ch) {
    if (ch == '\r') {
        if (cb.remaining() >= 1 && cb.get() == '\n') {
            return true;
        }
        cb.position(cb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}

private static boolean isEndOfLine(ByteBuffer bb, char ch) {
    if (ch == '\r') {
        if (bb.remaining() >= 1 && bb.get() == '\n') {
            return true;
        }
        bb.position(bb.position() - 1);
        return true;
    } else if (ch == '\n') {
        return true;
    }
    return false;
}

各行の長さは 102 バイトなので、ファイルは ~ 10 MB になります。

IO: Took 112 ms to read 100,000 lines
NIO as UTF-8: Took 207 ms to read 100,000 lines
NIO as ISO-8859-1: Took 87 ms to read 100,000 lines

前に述べたように、NIO を使用して 35 ミリ秒を節約するという余分な複雑さに見合う価値はありそうにありません。

ところで: HDD があり、ファイルがメモリにない場合は、ドライブの速度だけが問題になります。

于 2012-09-19T16:58:16.937 に答える
1

ループ内にループがあり、基本的にすべての呼び出しで出力をフラッシュする必要があるためSystem.out.println(sCurrentLine);、これは通常非常に非効率的です。

出力してその時間を測定する代わりに、行を ArrayList に入れてみることはできますか? そのように同じくらいの時間を費やしますか?

于 2012-09-19T16:19:19.030 に答える
0

ログファイルなのでファイルサイズは10MB

次に、適切なコンピューターを使用している場合は、ファイル全体を一度に読み取ることは問題になりません (Java 7 が必要です)。

public static void main(String[] args) {
    try {
        long start = System.nanoTime();
        List<String> lines = Files.readAllLines(Paths.get("C:/temp/test.log"), Charset.
                forName("UTF-8"));
        System.out.println("Lines read: " + lines.size());
        System.out.println("Total execution time taken in millis: "
                + ((System.nanoTime() - start) / 1000000));
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

注: 6MB のファイルを読み取るには、私のコンピューターでその方法を使用すると 75 ミリ秒かかります。

于 2012-09-19T16:21:58.397 に答える
0

あなたの実行時間は主にSystem.out.println(sCurrentLine);. sysout だけでなく、何らかの処理やフィルタリングを行いたいと思います。

BufferedReader の速度を確認したい場合は、カウンターを使用して読み取った行数をカウントし、カウントを出力するだけです。

于 2012-09-19T16:19:13.253 に答える