JCIFS: поиск файла слишком медленный, чтобы его можно было использовать
Я просто тестировал JCIFS для доступа к общим ресурсам Windows. Это очень медленно до такой степени, что полностью непригодным для использования.
import jcifs.smb.*;
class First {
public static void main(String[] args) throws Exception {
try {
//jcifs.Config.setProperty( "jcifs.netbios.wins", "192.168.1.220" );
NtlmPasswordAuthentication auth = new NtlmPasswordAuthentication("domain.com", "Administrator", "password");
SmbFile f = new SmbFile("smb://10.17.15.12/Share/xml/file.xml", auth);
SmbFileInputStream in = new SmbFileInputStream(f);
byte[] b = new byte[8192];
int n;
while(( n = in.read( b )) > 0 ) {
System.out.write( b, 0, n );
}
} catch (SmbException smbe) {
System.err.println(smbe.getNtStatus());
System.err.println(smbe.toString());
System.err.println(smbe.getCause());
}
}
}
Первоначальный вывод занимает очень много времени, а последующее чтение также очень медленное. Есть идеи, как его использовать? Любые альтернативы, с помощью которых я могу написать код Java для доступа к общим ресурсам Windows в портативном режиме, также приветствуются
6 ответов
Я где-то обнаружил, что SmbFileInputStream не выполняет собственную буферизацию и, следовательно, причина медленной работы. Обертывание SmbFileInputStream в BufferedInputStream решило проблему.
SmbFile sFile = new SmbFile(path, authentication);
BufferedInputStream buf = new BufferedInputStream(new SmbFileInputStream(sFile));
В моем случае загрузка файлов в общую папку Windows через JCIFS была слишком медленной, чтобы ее можно было использовать.
Решением оказалось определение свойства
-Djcifs.resolveOrder=DNS
Включение BCAST по умолчанию - передача запроса имени NetBIOS на номер 255.255.255.255 - без необходимости приводило к длительной задержке. (Ссылка выше де-фрейма из документов API верхнего уровня.)
Я заметил, что jCIFS делает что-то jcifs.smb.SmbTransport.checkStatus(..))
для каждого блока, который он читает, т.е. для каждого блока, который считывается в буфер. Это означает использование BufferedInputStream
может действительно ускорить процесс, но реальная проблема все еще существует. Это происходит не так часто, как раньше, и поэтому оказывает меньшее влияние на общее время.
Очень помогает установить "jcifs.util.loglevel = 3" и посмотреть, что на самом деле не так!
В моем случае я должен был установить "jcifs.smb.client.dfs.disabled=false"
в конце концов, как "jcifs.resolveOrder=DNS"
не помогло..
Если вы можете полагаться на "что-то другое" для монтирования общего ресурса в качестве локального каталога, тогда чтение файлов в подключенном общем ресурсе в Java должно быть переносимым.
Даже если это ненастоящее решение, стоило бы попробовать это, чтобы увидеть, получите ли вы более высокую скорость чтения. Значительно более высокая скорость чтения может изменить ваше мнение об относительной важности переносимости. И если вы не получите значительное ускорение, то вы будете знать, что JCIFS не виноват...
Даже при существующих предложениях я все еще находил JCIFS слишком медленным для потоковой передачи видео по моей локальной сети. Похоже, что это связано с накладными расходами на чтение буфера из сети, даже чтение в большие буферы Сам JCIFS имел ограниченный размер буфера, что было проблемой.
Если вы посмотрите в https://jcifs.samba.org/src/patches/ есть патч LargeReadWrite.patch. Вам нужно будет применить патч и пересобрать код, чтобы использовать его, но для меня это имело большое значение.
Решение, добавленное @Xolve0, сработало и для меня. Проблема с буфером в SmbFileInput
также присутствует при попытке записи файлов. Я использовал то же самое BufferedInputStream(new SmbFileInputStream(sFile))
чтобы уменьшить время выполнения с 90 секунд до менее секунды для простого текстового файла.
Быстрый способ выявить эту конкретную проблему - отслеживать время между открытием JCIFS
путь и запись самого файла.
Я знаю, что это старый вопрос, но для тех, кто пробовал другие решения безрезультатно:
В моем случае я смог отследить замедление интенсивного использования jcifs SecureRandom
, который блокирует, если /dev/random
сообщает о недостаточной энтропии.
Установка rng-tools
и настройка и включение rngd
довел производительность до приемлемых уровней.
Вы можете проверить доступную энтропию (по крайней мере на RHEL) с помощью следующей команды:
cat /proc/sys/kernel/random/entropy_avail