#java #io
#java #io
Вопрос:
Я пытаюсь улучшить чтение файла в своем коде, поэтому я подумал сначала сделать микробеншмарк, интересный результат, который я наблюдал, показан ниже. Позвольте мне сначала объяснить каждый тест; который считывает файл с использованием кода:
private void read(String source,Blackhole blackhole) throws IOException {
byte[] buffer = new byte[512];
InputStream inputStream = new FileInputStream(source);
int offset = 0,read = 0;
while((read = inputStream.read(buffer,0,512))!=-1){
blackhole.consume(buffer);
offset =read;
}
System.out.println(offset/(1024*1024) " MB read");
}
единственное различие в каждом бенчмарке — это исходный файл, который объясняется ниже:
compress = gzip version of orignal file which has on disk size 181MB
normal = actual file of 2.0G
normalCompressSize = actual file truncated to size of compressed file i.e. 181MB
Результаты
Benchmark Mode Cnt Score Error Units
FileReader.compress avgt 20 5.722 ± 0.207 s/op
FileReader.normal avgt 20 1.728 ± 0.010 s/op
FileReader.normalCompressSize avgt 20 0.160 ± 0.004 s/op
Теперь я не могу найти причину, по которой сжатый файл читается с такой низкой скоростью. Я даже не использую GZIPInputStream для раздувания данных, но все равно это занимает так много времени по сравнению с другими, особенно с обработанным файлом того же размера.
Есть какая-либо конкретная причина, по которой это происходит?
Дайте мне знать, если я пропустил какую-либо важную деталь.
Отредактировано: Добавлен фрагмент для объяснения теста:
public static void main(String[] args) throws IOException {
Options opt = new OptionsBuilder()
.include(".*" FileReader.class.getSimpleName() ".*")
.jvmArgs("-server")
.forks(1)
.build();
try {
new Runner(opt).run();
} catch (RunnerException e) {
e.printStackTrace();
}
}
Тесты:
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
public void compress(Blackhole blackhole) throws IOException {
read("~/Documents/data.csv.gz",blackhole);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
public void normalCompressSize(Blackhole blackhole) throws IOException {
read("~/Documents/data181MB.csv",blackhole);
}
@Benchmark
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.SECONDS)
public void normal(Blackhole blackhole) throws IOException {
read("~/Documents/data.csv",blackhole);
}
Редактировать: обновлен код для байтов.
Конечные результаты
Benchmark Mode Cnt Score Error Units
FileReader.compress avgt 20 0.160 ± 0.005 s/op
FileReader.normal avgt 20 1.818 ± 0.235 s/op
FileReader.normalCompressSize avgt 20 0.150 ± 0.001 s/op
Комментарии:
1. вы измеряете циклы процессора, время настенных часов … или что?
2. Я использую JMH с этими аннотациями @Benchmark @BenchmarkMode (Режим. Среднее время) @OutputTimeUnit (временная единица. СЕКУНДЫ)
3. Чтение сжатого файла с помощью программы чтения не имеет особого смысла. Файл gzip не содержит символов.
4. Программа чтения не просто преобразует байты в символы. Он использует кодировку символов (Charset) для декодирования последовательностей байтов в символы. Это может быть очень просто для одних кодировок и более сложно для других. Например, UTF8 содержит символы, закодированные в 1, 2 или более байтах, и некоторые последовательности байтов недопустимы.
5. Вы измеряете время для преобразования сжатых двоичных данных в 16-разрядные символы Юникода, даже если это изначально не кодировка символов. Вы ничего не делаете правильно, поэтому время, которое требуется, не представляет интереса.