Навигация
 
 
 
 
Languages
 
 

Немного о 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
			// ...
		}
	}
}

Paranoid прав кроме

Paranoid прав кроме одного - массив будет создан не на стеке, а в куче. использование ThreadLocal не только не оправданно в данном случае, но и вредно потому что увеличивается время жизни переменной (на время жизни нитки), что создает дополнительную нагрузку на GC. ну и кроме того доступ к переменным в ThreadLocal медленный сам по себе. а вообще копирование нужно делать через NIO с использованием техники zero copy - быстрее не бывает

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

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

проверяли

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

Для Сотоны

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

привет

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

Отправить комментарий

Содержание этого поля является приватным и не предназначено к показу.
  • Allowed HTML tags: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Syntax highlight code surrounded by the {syntaxhighlighter OPTIONS}...{/syntaxhighlighter} tags.

Подробнее о форматировании

CAPTCHA
Защита от спам сообщений
 
 
 
 
 
 
  • emmie
  • hooligan
  • cupuyc
  • ESoImk
  • LeKz
 
 
 
© 2006-2009 kobyleha.com