За Пасху я сделал программу, которая берет большой файл журнала, читает его, анализирует и выводит в табличное представление с помощью javafx. Программа работает и поэтому превратилась в .jar с помощью Intellij, чтобы ее можно было легко использовать без IDE.
Однако при запуске программы требуется примерно в 2-3 раза больше времени при запуске методов ввода-вывода в форме JAR программы.
(файл .java) 3,5 секунды чтение -> (файл .jar) 11,3 секунды
(файл .java) 0,014 секунды на запись -> (файл .jar) 0,034 секунды
Я прочитал более старые вопросы об этом. Попробовали синхронизировать методы, убедившись, что используется последняя версия JDK / JRE.
Методы, которые, как я уверен, замедляются при запуске как jar:
/**
* Method that filters a file based on a search string and a selected radio button
*
* @param num index of a selected radio button
* @param filterSearch String that is being searched for
* @param path Of the log file that is being filtered through
* @return The new file that contains only the desired lines
*/
public static String filterFile(int num, String filterSearch, String path) {
long startTime = System.currentTimeMillis();
ArrayList<String> toOutput = new ArrayList<>();
Scanner in = null;
File inputFile = new File(path);
try {
in = new Scanner(inputFile);
String searchString = null;
//While the log file has a line
while (in.hasNext()) {
//the next line to be searched is stored in searchString
searchString = in.nextLine();
switch (num) {
//if the user radio button is selected
case 1:
//if the searchString contains the filter search
//print the whole line to the new file
if (searchString.contains("user=\"" + filterSearch)) {
//System.out.println(searchString);
toOutput.add(searchString);
}
break;
case 2:
//if the searchString contains the filter search
//print the whole line to the new file
if (searchString.contains("srcip=\"" + filterSearch)) {
toOutput.add(searchString);
}
break;
}
}
} catch (Exception e) {
System.out.println("Cannot open file: ");
System.exit(0);
}finally {
in.close();
}
long endTime = System.currentTimeMillis();
double duration = (endTime - startTime)/1000.0;
System.out.println("first formatedSeconds = "+ duration);
return createFilterFile(toOutput);
}
/**
* Create a new file with the filtered results inside
* @param toPrint lines from the log file that have been filtered out
* @return Path to this new file
*/
private static String createFilterFile(ArrayList<String> toPrint){
long startTime = System.currentTimeMillis();
Date date = new Date();
String fileName = "New filtered search file " + sdf.format(date) + ".log";
PrintWriter out = null;
try{
FileWriter outputFile = new FileWriter(fileName, true);
out = new PrintWriter(outputFile);
for(String item: toPrint){
out.println(item);
}
}catch(Exception e){
e.printStackTrace();
}finally {
out.close();
}
long endTime = System.currentTimeMillis();
double duration = (endTime - startTime)/1000.0;
// formatedSeconds = (0.xy seconds)
System.out.println("second formatedSeconds = "+ duration);
return fileName;
}
Редактировать добавил к обоим методам предложение finally, не изменив производительность, хотя
Этот код берет большой файл журнала, ищет в каждой строке искомую строку и добавляет ее в список массивов, а затем создает новый файл. Этот файл значительно меньше, поэтому его легко открыть.
Любая помощь в улучшении производительности jar будет принята с благодарностью, поскольку у меня нет большого опыта работы с файлами .jar!
Обновлено: переход от сканера к буферизированному считывателю радикально улучшил производительность
(файл .java) 1,39 секунды чтение -> (файл .jar) 1,82 секунды
(файл .java) 0,014 секунды на запись -> (файл .jar) 0,034 секунды
/**
* Method that filters a file based on a search string and a selected radio button
*
* @param num index of a selected radio button
* @param filterSearch String that is being searched for
* @param path Of the log file that is being filtered through
* @return The new file that contains only the desired lines
*/
public static String filterFile(int num, String filterSearch, String path) {
long startTime = System.currentTimeMillis();
ArrayList<String> toOutput = new ArrayList<>();
BufferedReader reader = null;
File inputFile = new File(path);
try {
reader = new BufferedReader(new FileReader(inputFile));
String searchString = null;
//While the log file has a line
//the next line to be searched is stored in searchString
while ((searchString = reader.readLine())!=null) {
switch (num) {
//if the user radio button is selected
case 1:
//if the searchString contains the filter search
//print the whole line to the new file
if (searchString.contains("user=\"" + filterSearch)) {
toOutput.add(searchString);
}
break;
case 2:
//if the searchString contains the filter search
//print the whole line to the new file
if (searchString.contains("srcip=\"" + filterSearch)) {
toOutput.add(searchString);
}
break;
}
}
} catch (IOException e) {
System.out.println("Cannot open file: ");
System.exit(0);
}finally {
try{
reader.close();
}catch (IOException ef){
}
}
long endTime = System.currentTimeMillis();
double duration = (endTime - startTime)/1000.0;
System.out.println("first formatedSeconds = "+ duration);
return createFilterFile(toOutput);
}
Конечно, есть еще около полсекунды, но это не так заметно, если кто-нибудь может объяснить, почему существует такая резкая разница между сканером и буферизованным считывателем, я был бы признателен.
Должен ли я всегда использовать буферизованный ридер? Даст ли буферизованный писатель аналогичный прирост производительности? Почему все еще есть разница в производительности?
Спасибо всем :)
@ user3237736 Я не думаю, что это связано с моей IDE, я впервые заметил разницу между производительностью, когда я запускал этот код на своем ноутбуке, используя netbeans, когда код был немного более беспорядочным, если вы не имеете в виду что-то еще? и спасибо да добавлю блок finally :)
Хм, может быть, попробуйте использовать BufferedReader вместо Scanner для чтения файла. Я понятия не имею, почему это решит проблему, но черт возьми, почему бы не попробовать
Записан ли файл в текущий каталог? Когда вы создаете банку, этот файл находится внутри нее?
@ user3237736 Ну, это имело огромное значение, я заменил сканер на буферизованный ридер, и он занял 1,39 секунды в файле java и 1,82 секунды в файле jar (я обновлю свой вопрос в ближайшее время) есть ли для этого какие-либо причины вы можете думать о. Я не использовал буферизованный ридер, поэтому мало о нем знаю?
@ cricket_007 файлы, записанные программой, записываются в текущий каталог
@JoeKerr BufferedReaders может быть быстрее, чем сканеры, особенно для больших файлов. Для объяснения, пожалуйста, Google. Однако я понятия не имею, почему сканер работает намного медленнее в JAR по сравнению с IDE, извините
BufferedReader - это практически документированный способ чтения файла. stackoverflow.com/a/5868528/2308683. Также ответьте на мой второй вопрос выше? Можете ли вы перечислить его содержимое в файле JAR?
@ cricket_007 нет, файл отдельный, jar содержит только файлы классов java, которые запускают методы / gui. Затем будет найден путь к этому файлу журнала. Если я понимаю ваш вопрос. И я полагаю, что мне никогда не приходилось использовать ничего, кроме сканеров, чему нас учили.




Звучит странно. Это может быть кеширование в вашей среде IDE. Возможно, сделайте недействительными какие-либо кеши и перезапустите IDE. Значит, он все еще работает так же быстро? В качестве альтернативы ваша IDE может быть настроена для запуска JVM с большим объемом памяти, чем ваша система при запуске jar. И между прочим: то, как вы пишете файл, не очень «лучшая практика». Вы должны поместить вызов
close()вfinally. а еще лучше использоватьtry-with-resources.