Здравствуйте, ChaM, Вы писали:
CM>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)
В современных ОС, если вы явно не управляете кешированием, запись на диск происходит асинхронно. Условно говоря в другом потоке. Так что такое разделение вам ничего не даст. Более того обработка информации процессорами на порядки быстрее операции ввода вывода, в лучшем случае вы можете получить какой-то выигрыш, разделив обработку файла на куски и запустив их отдельно на разных процессорах. Хотя для этого вам нужно будет иметь дисковую систему с внутренней параллельностью, например RAID массив.
есть некий обработчик файла, который читает файл, обрабатывает поочерёдно каждую строку и по каждой строке результат записывает в другой файл.
Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)
Например если делаю вот так через очередь то получается гораздо медленнее чем если сразу результат в файл записывать
public class TESTTESTParserWithShift {
String _input_file_name="";
String _ouput_file_name="";
public TESTTESTParserWithShift(){
_input_file_name = "qwe";
_ouput_file_name = "ttt1.tmp";
LoadTest();
}
public int LoadTest() throws Exception{
MyWriter myWriter = new MyWriter();
while( br.readLine()){
Str res = ОбработчикСтроки();
myWriter.AddStr(cResultPacket.strResult);
}
myWriter.Stop();
myWriter.t.join();
bw.close();
return 1;
}
class MyWriter implements Runnable{
Queue<String> queue;
public Thread t;
boolean isEnd = false;
BufferedWriter bw;
public MyWriter(){
try {
bw = new BufferedWriter(new FileWriter(_ouput_file_name));
} catch (IOException e) {
LOG.error(e);
}
queue = new LinkedList<String>();
t = new Thread(this,"sdfdsf");
t.start();
}
public void AddStr(String str){
synchronized (queue){
queue.add(str);
}
}
public void Stop(){
isEnd = true;
try {
bw.close();
} catch (IOException e) {
LOG.error(e);
}
}
@Override
public void run() {
String str;
while(isEnd == false){
try {
synchronized (queue) {
while((str=queue.poll())!=null){
bw.write(str);
}
}
} catch (Exception e) {
LOG.error(e);
}
}
}
}
}
Здравствуйте, ChaM, Вы писали:
CM>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)
Теоретически — да, можно.
CM>Например если делаю вот так через очередь то получается гораздо медленнее чем если сразу результат в файл записывать
Вместо кустарной синхронизации возьмите какую-нибудь подходящую очередь из java.util.concurrent
Здравствуйте, Gurney, Вы писали:
CM>>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск) G>В современных ОС, если вы явно не управляете кешированием, запись на диск происходит асинхронно. Условно говоря в другом потоке. Так что такое разделение вам ничего не даст. Более того обработка информации процессорами на порядки быстрее операции ввода вывода, в лучшем случае вы можете получить какой-то выигрыш, разделив обработку файла на куски и запустив их отдельно на разных процессорах. Хотя для этого вам нужно будет иметь дисковую систему с внутренней параллельностью, например RAID массив.
Оптимизировать возможно если распараллелить IO и обработку. Но тут выигрышь сильно зависит от того сколько времени занимает одно и другое. Так как могут не окупиться затраты на распареллеливание.
У вас машина однопроцессорная? Вот этот вот кусок кода упорно пытается проверить, не появилось ли что-то в очереди, мешая второму процессу выполняться. Возьмите какую-нибудь
готовую блокирующую очердеь. Или прочитайте про wait/notify.
Да, по вашему коду еще и IOException stream already closed очень вероятен — вы поток закрываете, а после этого может произойти попытка записи. isEnd должен быть volatile, иначе выполняющаяся нить может не увидеть изменения этого поля. А еще поток может никогда не завершиться — он ждет сообщения в очереди (которого нет) а isEnd не проверяет.
Здравствуйте, maxkar, Вы писали:
M> А еще поток может никогда не завершиться — он ждет сообщения в очереди (которого нет) а isEnd не проверяет.
Здесь я не прав — во внешний цикл оно выходит когда очередь пустая. Но все остальные проблемы остаются. Т.е. polling и отсутствие volatile.
Здравствуйте, Blazkowicz, Вы писали:
B>Оптимизировать возможно если распараллелить IO и обработку. Но тут выигрышь сильно зависит от того сколько времени занимает одно и другое. Так как могут не окупиться затраты на распареллеливание.
Согласен, теоретически выигрыш от разделения IO и обработки получить можно. Но учитывая, как реально работает память, затраты на переключение контекстов, синхронизацию, есть большое сомнение в выгодности перекидывания строк из треда в тред.
Re: Многопоточность и файловый IO
От:
Аноним
Дата:
16.05.10 08:03
Оценка:
Здравствуйте, ChaM, Вы писали:
Вот здесь http://www.tbray.org/ongoing/When/200x/2009/09/27/Concur-dot-next бьются почти над той же проблемой. Но они не пишут сразу в файл, из каждой строки извлекается некая статистика, добавляемая в массив в памяти. Потом массив сортируется и дампится в текстовый файл. Получается быстро и 32 потока у них сразу работают