Многопоточность и файловый IO
От: ChaM  
Дата: 01.04.10 15:07
Оценка:
Товарищи подскажите можно ли сделать следующее.

есть некий обработчик файла, который читает файл, обрабатывает поочерёдно каждую строку и по каждой строке результат записывает в другой файл.

Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)

Например если делаю вот так через очередь то получается гораздо медленнее чем если сразу результат в файл записывать


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);
                }
            }
        }
        
    }




}
Re: Многопоточность и файловый IO
От: Blazkowicz Россия  
Дата: 01.04.10 15:15
Оценка:
Здравствуйте, ChaM, Вы писали:

CM>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)

Теоретически — да, можно.

CM>Например если делаю вот так через очередь то получается гораздо медленнее чем если сразу результат в файл записывать


Вместо кустарной синхронизации возьмите какую-нибудь подходящую очередь из java.util.concurrent
http://rsdn.org/File/13923/ukliam3.gif
Re: Многопоточность и файловый IO
От: Gurney Великобритания www.kharlamov.biz
Дата: 01.04.10 15:23
Оценка: +1
Здравствуйте, ChaM, Вы писали:

CM>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)

В современных ОС, если вы явно не управляете кешированием, запись на диск происходит асинхронно. Условно говоря в другом потоке. Так что такое разделение вам ничего не даст. Более того обработка информации процессорами на порядки быстрее операции ввода вывода, в лучшем случае вы можете получить какой-то выигрыш, разделив обработку файла на куски и запустив их отдельно на разных процессорах. Хотя для этого вам нужно будет иметь дисковую систему с внутренней параллельностью, например RAID массив.
Re[2]: Многопоточность и файловый IO
От: Blazkowicz Россия  
Дата: 01.04.10 16:14
Оценка:
Здравствуйте, Gurney, Вы писали:

CM>>Можно ли в данном случае ускорить весь процесс если осуществлять запись результатов для каждой строки в другом потоке? (с целью что бы разбор файла не ждал каждый раз записи на диск)

G>В современных ОС, если вы явно не управляете кешированием, запись на диск происходит асинхронно. Условно говоря в другом потоке. Так что такое разделение вам ничего не даст. Более того обработка информации процессорами на порядки быстрее операции ввода вывода, в лучшем случае вы можете получить какой-то выигрыш, разделив обработку файла на куски и запустив их отдельно на разных процессорах. Хотя для этого вам нужно будет иметь дисковую систему с внутренней параллельностью, например RAID массив.

Оптимизировать возможно если распараллелить IO и обработку. Но тут выигрышь сильно зависит от того сколько времени занимает одно и другое. Так как могут не окупиться затраты на распареллеливание.
http://rsdn.org/File/13923/ukliam3.gif
Re: Многопоточность и файловый IO
От: maxkar  
Дата: 01.04.10 17:23
Оценка:
Здравствуйте, ChaM, Вы писали:


CM>Например если делаю вот так через очередь то получается гораздо медленнее чем если сразу результат в файл записывать


CM>
    
CM>    synchronized (queue) {
CM>        while((str=queue.poll())!=null){                    
CM>            bw.write(str);
CM>        }
CM>    }
CM>


У вас машина однопроцессорная? Вот этот вот кусок кода упорно пытается проверить, не появилось ли что-то в очереди, мешая второму процессу выполняться. Возьмите какую-нибудь
готовую блокирующую очердеь. Или прочитайте про wait/notify.

Да, по вашему коду еще и IOException stream already closed очень вероятен — вы поток закрываете, а после этого может произойти попытка записи. isEnd должен быть volatile, иначе выполняющаяся нить может не увидеть изменения этого поля. А еще поток может никогда не завершиться — он ждет сообщения в очереди (которого нет) а isEnd не проверяет.
Re[2]: Многопоточность и файловый IO
От: maxkar  
Дата: 01.04.10 17:34
Оценка:
Здравствуйте, maxkar, Вы писали:

M> А еще поток может никогда не завершиться — он ждет сообщения в очереди (которого нет) а isEnd не проверяет.

Здесь я не прав — во внешний цикл оно выходит когда очередь пустая. Но все остальные проблемы остаются. Т.е. polling и отсутствие volatile.
Re[3]: Многопоточность и файловый IO
От: Gurney Великобритания www.kharlamov.biz
Дата: 07.04.10 17:12
Оценка:
Здравствуйте, 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 потока у них сразу работают
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.