Languages
 
 
 
 
Navigation
 
 
 
 
 
 

Немного о Java I/O производительности

Работая над производительностью одного java проекта, я нашел что наиболее узкое место - это метод copy в утилитах file. Метод был реализован без использования буфера. Реализация была следующая: простой цикл while, в котором читался входящий поток, и сразу прочитанные данные писались в исходящий поток.

Есть хорошая статья о производительности ввода/вывода на сайте sun.

Пример 4-4 из статьи выглядит подходящим, но, как оказывается, и он не идеален. На это есть причины: моё приложение многопоточное. Каждый раз, когда я делаю синхронизацию по статическому полю, я создаю узкое место в программе – потому, что все потоки будут блокироваться, ожидая входа в синхронизированный блок кода.

Но существует метод, позволяющий избежать этой проблемы. Если Вы хотите использовать буфер, который не инициализируется каждый раз, когда метод вызывается, Вы должны использовать ThreadLocal переменную с временной ссылкой на буфер, что даст возможность нормально освобождать память по необходимости.

Результат будет следующий:

import java.io.*;

public class CopyExample {
  // Thread buffer size
  private static final int BUFF_SIZE = 1024 * 4;

  // Thread buffer variable
  private static final ThreadLocal<byte[]> buffCache = new ThreadLocal<byte[]>() {
    @Override
    protected byte[] initialValue() {
      return new byte[BUFF_SIZE];
    }
  };

  private CopyExample() {
  }

  public static void copy(File from, File to) throws IOException {
    InputStream in = null;
    OutputStream out = null;
    try {
      in = new FileInputStream(from);
      out = new FileOutputStream(to);
      byte[] buffer = buffCache.get();
      int amountRead;
      while ((amountRead = in.read(buffer)) != -1) {
        out.write(buffer, 0, amountRead);
      }
    } finally {
      // close in and out streams
      // ...
    }
  }
}

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.

немогу понять,

немогу понять, а в чем собственно проблема? массив, определенный внутри метода, скорей всего будет находится в стеке а не в хипе, поэтому работа с ним будет довольно быстрой. хороший пример - java.io.BufferedOutputStream, который принимает поток, который нужно обернуть в буффер, и размер буффера. в зависимости от скорости вливания, буффер можна сделать от 2 до 20 килобайт. производительность действительно увеличивается на глазах - скорость копирования файла таким образом у меня не уступала скорости копирования каким-либо из системных приложений (даже как-то замерял скорость в зависимости от размера буффера). если честно, считаю что такой способ чуть лучше, потому что обращение к таким штукам, как ThreadLocal, реализовано скорей для надежности чем для скорости.

привет

для Камаде. придумка интересная :) кстати - а мерял кто-то эти всякие буферы или чисто теоретически считается, что так быстрее? ...dali bude...

проверяли

посмотри на статью на сайте sun, там есть табличка "Copy Times". Мой пример по скорости такой же как и custom buffer 2.

Для Сотоны

На счёт инициализации буфера, врядли можно на глаз определить по времени, 4Кб должно лихо выделятся на нормальной тачке как мне кадежется... А вот если размер буфера маловат, то тут да, на файлике 5 Мб можно на глаз это всё прочувствовать. А вообще странно что для этих целей используется Java I/O, когда начиная с 1.4 есть такой пакет как NIO. Я уверен что как раз в этом случае выигрыш будет значительнее. На счёт ThreadLocal тоже всё неоднозначно, хотя в самом простом варианте конечно прокатит и однозначно рекомендован. Для серьёзного приложения, где акцент идёт на многопоточность и рациональное использование ресурсов памяти, надо писать имплементацию Poolа. И к тому же в идеале размер буффера надо динамически менять, исходя из размера файла.

Post new comment

The content of this field is kept private and will not be shown publicly.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>

More information about formatting options

 
 
 
 
 
 
  • hooligan
  • cupuyc
  • ESoImk
  • LeKz
  • Anton
 
 
 
© 2006-2008 kobyleha.com