java.nio.file.Files.copy кушает процессорное время
От: sergey123_1  
Дата: 18.01.15 13:42
Оценка:
Если скачивать файлы с помощью java.nio.Files.copy, то в момент скачивания файла, в top-е видно как java поедает процессорное время. Если качать тоже самое обычным wget-ом, то процессорное время потребляется значительно меньше.

$ time wget http://speedtest.london.linode.com/100MB-london.bin
...
real    0m5.434s
user    0m0.056s
sys     0m0.536s

$ time java -jar Test.jar http://speedtest.london.linode.com/100MB-london.bin

real    0m4.937s
user    0m0.828s
sys     0m0.572s


Время скачивания, что через java, что через wget всегда примерно одинаковое (+/- 1 секунда), но вот потребление CPU (и это видно в user time) у java всегда больше.

Есть ли способы качать файлы на java быстрее, чем java.nio.Files.copy? (обязательное условие — возможность задать timeout на connect и read)

package test;

import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;

public class Test {

    public static void main(String[] args) throws MalformedURLException, IOException {

        URL url = new URL(args[0]);
        URLConnection urlConnection = url.openConnection();
        urlConnection.setConnectTimeout(5000);
        urlConnection.setReadTimeout(5000);
        
        Files.copy(urlConnection.getInputStream(), (new File("1.iso")).toPath(), StandardCopyOption.REPLACE_EXISTING);
    }   
}
java.nio copy http cpu
Re: java.nio.file.Files.copy кушает процессорное время
От: tavr  
Дата: 19.01.15 08:32
Оценка:
Здравствуйте, sergey123_1, Вы писали:


_>Если скачивать файлы с помощью java.nio.Files.copy, то в момент скачивания файла, в top-е видно как java поедает процессорное время. Если качать тоже самое обычным wget-ом, то процессорное время потребляется значительно меньше.

_>
_>        Files.copy(urlConnection.getInputStream(), (new File("1.iso")).toPath(), StandardCopyOption.REPLACE_EXISTING);
_>

попробуй обернуть в BufferedInputStream
Re[2]: java.nio.file.Files.copy кушает процессорное время
От: vpchelko  
Дата: 20.01.15 19:55
Оценка:
Здравствуйте, tavr, Вы писали:

T>Здравствуйте, sergey123_1, Вы писали:



_>>Если скачивать файлы с помощью java.nio.Files.copy, то в момент скачивания файла, в top-е видно как java поедает процессорное время. Если качать тоже самое обычным wget-ом, то процессорное время потребляется значительно меньше.

_>>
_>>        Files.copy(urlConnection.getInputStream(), (new File("1.iso")).toPath(), StandardCopyOption.REPLACE_EXISTING);
_>>

T>попробуй обернуть в BufferedInputStream

Скорее всего, также надо обернуть BufferedOutputStream — чтобы уменьшить количество Write операций в файл (писать большими кусками — а не по байтам)/. Гонять байты из натив в манаджед и обратно в натив не дешевые операции. Лучше читать большими кусками читать из in-стрима и писать в out-стрим, или через некий интервал времени.

Если очень хочется избавится от потерь CPU — надо избегать попадание данных в манаджед, а сразу писать нативный стрим в файл — как вариант запуск wget из java приложения.
Сало Украине, Героям Сала
Отредактировано 20.01.2015 20:41 vpchelko . Предыдущая версия . Еще …
Отредактировано 20.01.2015 20:40 vpchelko . Предыдущая версия .
Отредактировано 20.01.2015 20:34 vpchelko . Предыдущая версия .
Отредактировано 20.01.2015 20:34 vpchelko . Предыдущая версия .
Отредактировано 20.01.2015 19:57 vpchelko . Предыдущая версия .
Re[3]: java.nio.file.Files.copy кушает процессорное время
От: sergey123_1  
Дата: 21.01.15 21:52
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>Здравствуйте, tavr, Вы писали:


T>>Здравствуйте, sergey123_1, Вы писали:


_>>>Если скачивать файлы с помощью java.nio.Files.copy, то в момент скачивания файла, в top-е видно как java поедает процессорное время. Если качать тоже самое обычным wget-ом, то процессорное время потребляется значительно меньше.

_>>>
_>>>        Files.copy(urlConnection.getInputStream(), (new File("1.iso")).toPath(), StandardCopyOption.REPLACE_EXISTING);
_>>>

T>>попробуй обернуть в BufferedInputStream

V>Скорее всего, также надо обернуть BufferedOutputStream — чтобы уменьшить количество Write операций в файл (писать большими кусками — а не по байтам)


Попробовал делать Bufferred и для in и для out разными способами, либо потребляется ещё больше cpu, либо столько же, сколько и Files.copy
Re[4]: java.nio.file.Files.copy кушает процессорное время
От: vpchelko  
Дата: 21.01.15 23:40
Оценка:
Здравствуйте, sergey123_1, Вы писали:

_>Попробовал делать Bufferred и для in и для out разными способами, либо потребляется ещё больше cpu, либо столько же, сколько и Files.copy


Это да, проверил — java или ОCь (windows 7) сама оптимизирует запись на диск (файл растет большими кусками по 10-50 мегабайт за раз). Хотя у меня CPU практически не жрет (больше 1% в диспетчере задач не показывает).

П.с. хотя тот же curl стабильно 0% показывает. Издержки JVM тут ничего не поделаешь.

П.п.с https://bugs.openjdk.java.net/browse/JDK-8069327
========================================================

Хороший совет дают на стек оверфлове:

http://stackoverflow.com/questions/921262/how-to-download-and-save-a-file-from-internet-using-java

Возможно то что надо:

Using transferFrom() is potentially much more efficient than a simple loop that reads from the source channel and writes to this channel. Many operating systems can transfer bytes directly from the source channel into the filesystem cache without actually copying them.

Сало Украине, Героям Сала
Отредактировано 22.01.2015 10:04 vpchelko . Предыдущая версия . Еще …
Отредактировано 22.01.2015 0:32 vpchelko . Предыдущая версия .
Отредактировано 22.01.2015 0:04 vpchelko . Предыдущая версия .
Отредактировано 22.01.2015 0:03 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:57 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:56 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:48 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:48 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:47 vpchelko . Предыдущая версия .
Отредактировано 21.01.2015 23:41 vpchelko . Предыдущая версия .
Re: java.nio.file.Files.copy кушает процессорное время
От: Blazkowicz Россия  
Дата: 22.01.15 09:05
Оценка:
Здравствуйте, sergey123_1, Вы писали:

_>Если скачивать файлы с помощью java.nio.Files.copy, то в момент скачивания файла, в top-е видно как java поедает процессорное время. Если качать тоже самое обычным wget-ом, то процессорное время потребляется значительно меньше.

Клиентская Java интерпретируется. Вероятно это и отнимает дополнительные ресурсы. Если процессорное время критично, можно попробовать запустить с опцией -server и "разгореть". А потом замерять. Разница должна быть существенной.
Re[5]: java.nio.file.Files.copy кушает процессорное время
От: sergey123_1  
Дата: 22.01.15 19:42
Оценка:
Здравствуйте, vpchelko, Вы писали:

V>Это да, проверил — java или ОCь (windows 7) сама оптимизирует запись на диск (файл растет большими кусками по 10-50 мегабайт за раз). Хотя у меня CPU практически не жрет (больше 1% в диспетчере задач не показывает).


Значит у вас просто интернет-канал <=100мбит/с. На серверах, подключенных к интернету на скорости 1G или 10G Java кушает значительно больше CPU, чем wget/curl

V>П.п.с https://bugs.openjdk.java.net/browse/JDK-8069327


Спасибо, а то oracle не уведомил меня по email, что мою заявку JI-9018329 превратили в баг JDK-8069327

V>Хороший совет дают на стек оверфлове:


всякие transferFrom я уже перепробовал... результаты такие же, что и у Files.copy
Re[6]: java.nio.file.Files.copy кушает процессорное время
От: vpchelko  
Дата: 22.01.15 20:36
Оценка:
Здравствуйте, sergey123_1, Вы писали:

_>Спасибо, а то oracle не уведомил меня по email, что мою заявку JI-9018329 превратили в баг JDK-8069327


V>>Хороший совет дают на стек оверфлове:


_>всякие transferFrom я уже перепробовал... результаты такие же, что и у Files.copy


Крайний вариант — использовать JNA / JNI.
Сало Украине, Героям Сала
Отредактировано 22.01.2015 20:37 vpchelko . Предыдущая версия . Еще …
Отредактировано 22.01.2015 20:37 vpchelko . Предыдущая версия .
Re[2]: java.nio.file.Files.copy кушает процессорное время
От: sergey123_1  
Дата: 26.01.15 16:37
Оценка:
Здравствуйте, Blazkowicz, Вы писали:

B>Клиентская Java интерпретируется. Вероятно это и отнимает дополнительные ресурсы. Если процессорное время критично, можно попробовать запустить с опцией -server и "разгореть". А потом замерять. Разница должна быть существенной.


Добавление -server не помогает
Re[3]: java.nio.file.Files.copy кушает процессорное время
От: Blazkowicz Россия  
Дата: 26.01.15 17:00
Оценка:
Здравствуйте, sergey123_1, Вы писали:

_>Добавление -server не помогает

Так одного прогона не достаточно.
Re[4]: java.nio.file.Files.copy кушает процессорное время
От: sergey123_1  
Дата: 26.01.15 17:12
Оценка: 1 (1)
Здравствуйте, Blazkowicz, Вы писали:

B>Здравствуйте, sergey123_1, Вы писали:


_>>Добавление -server не помогает

B>Так одного прогона не достаточно.

я сделал цикл в коде, не помогает оно.

да и разработчики openjdk ничего подобного не предлагают https://bugs.openjdk.java.net/browse/JDK-8069327 . там предлагают протестировать производительность компонента из java.net, который выкачивает по http, займусь этим на днях, только вот сказать им об этом не смогу ибо публичный баг-трекер у них шикарный, баг запостить можно, а потом ничего добавить или откомментировать нельзя :))) придётся ещё один баг запиливать, если проблема в http качалке из java.net
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.