Как ускорить / оптимизировать запись файлов в моей программе - PullRequest
1 голос
/ 26 сентября 2011

Хорошо.Я должен написать программу, которая будет принимать файл размером 20 ГБ в качестве входных данных с 1 000 000 000 записей и создавать какой-то индекс для более быстрого доступа.Я в основном решил разделить записи 1 бил на 10 сегментов и 10 вложенных сегментов.Я рассчитываю два значения хеша для записи, чтобы найти ее соответствующий сегмент.Теперь я создаю 10 * 10 файлов, по одному на каждое вложенное ведро.И, когда я хэширую запись из входного файла, я решаю, к какому из 100 файлов она идет;затем добавьте смещение записи к этому конкретному файлу.Я проверил это на примере файла с 10 000 записей.Я повторил процесс 10 раз.Эффективно эмулирует 100 000 записей.На это у меня уходит около 18 секунд.Это означает, что мне понадобится вечность, чтобы сделать то же самое для файла записи 1 билл.Есть ли в любом случае я могу ускорить / оптимизировать мое письмо.И я прохожу все это, потому что я не могу сохранить все записи в основной памяти.

import java.io.*;

// PROGRAM DOES THE FOLLOWING

// 1. READS RECORDS FROM A FILE. 
// 2. CALCULATES TWO SETS OF HASH VALUES N, M
// 3. APPENDING THE OFFSET OF THAT RECORD IN THE ORIGINAL FILE TO ANOTHER FILE "NM.TXT"  i.e REPLACE THE VALUES OF N AND M.
// 4.  

class storage
{

        public static int siz=10;
    public static FileWriter[][] f;
}

class proxy
{

    static String[][] virtual_buffer;
    public static void main(String[] args) throws Exception
    {
        virtual_buffer = new String[storage.siz][storage.siz]; // TEMPORARY STRING BUFFER TO REDUCE WRITES


        String s,tes;


        for(int y=0;y<storage.siz;y++)
            {
            for(int z=0;z<storage.siz;z++)
            {
            virtual_buffer[y][z]="";            // INITIALISING ALL ELEMENTS TO ZERO
            }
            }




        int offset_in_file = 0;          

        long start = System.currentTimeMillis();


              // READING FROM THE SAME IP FILE 20 TIMES TO EMULATE A SINGLE BIGGER FILE OF SIZE 20*IP FILE
        for(int h=0;h<20;h++){                

         BufferedReader in = new BufferedReader(new FileReader("outTest.txt"));
         while((s = in.readLine() )!= null)
         {
            tes = (s.split(";"))[0];
            int n = calcHash(tes); // FINDING FIRST HASH VALUE
            int m = calcHash2(tes); // SECOND HASH
            index_up(n,m,offset_in_file); // METHOD TO WRITE TO THE APPROPRIATE FILE I.E NM.TXT
                offset_in_file++;

         }
         in.close();
        }



         System.out.println(offset_in_file);
         long end = System.currentTimeMillis();
         System.out.println((end-start));
    }




    static int calcHash(String s) throws Exception

    {
        char[] charr = s.toCharArray();;
        int i,tot=0;
        for(i=0;i<charr.length;i++)
        {
            if(i%2==0)tot+= (int)charr[i];
        }
        tot = tot % storage.siz;
        return tot;
    }




       static int calcHash2(String s) throws Exception

    {
        char[] charr = s.toCharArray();
        int i,tot=1;
        for(i=0;i<charr.length;i++)
        {
            if(i%2==1)tot+= (int)charr[i];
        }   
        tot = tot % storage.siz;
        if (tot<0)
            tot=tot*-1;
        return tot;
    }


      static void index_up(int a,int b,int off) throws Exception
   {
    virtual_buffer[a][b]+=Integer.toString(off)+"'"; // THIS BUFFER STORES THE DATA TO BE WRITTEN
    if(virtual_buffer[a][b].length()>2000)           // TO A FILE BEFORE WRITING TO IT, TO REDUCE NO. OF WRITES
    {                                                .

    String file = "c:\\adsproj\\"+a+b+".txt";   
    new writethreader(file,virtual_buffer[a][b]);    // DOING THE ACTUAL WRITE PART IN A THREAD.
    virtual_buffer[a][b]="";


    }
    }
}



class writethreader implements Runnable
{
    Thread t;
    String name, data;
    writethreader(String name, String data)
    {
        this.name = name;
        this.data = data;

        t = new Thread(this);
        t.start();
    }

    public void run()
    {
        try{


        File f = new File(name);
        if(!f.exists())f.createNewFile();   
        FileWriter fstream = new FileWriter(name,true);  //APPEND MODE 
        fstream.write(data);
        fstream.flush(); fstream.close();
            }
        catch(Exception e){}
    }
}

Ответы [ 2 ]

1 голос
/ 26 сентября 2011

Рассмотрите возможность использования VisualVM для выявления узких мест.Все остальное ниже основано на догадках - и догадки о производительности часто действительно, действительно неправильны.

Я думаю У вас есть две проблемы с вашей стратегией записи.

Перваячто вы начинаете новую тему при каждой записи;во-вторых, вы заново открываете файл при каждой записи.

Проблема с потоками особенно серьезна, я думаю, потому что я не вижу ничего, препятствующего перекрытию одной записи одного файла с другим.,Что происходит потом?Честно говоря, я не знаю - но я сомневаюсь, что это хорошо.

Вместо этого рассмотрите возможность создания массива открытых файлов для всех 100. Ваша ОС может иметь проблемы с этим - но я думаю вероятно нет.Затем создайте очередь работы для каждого файла.Создайте набор рабочих потоков (100 - это слишком много - примерно 10 или около того), где каждый «владеет» набором файлов, которые он перебирает, выводя и освобождая очередь для каждого файла.Обратите внимание на взаимодействие между нитями и средством чтения очереди - используйте соответствующий класс очереди.

0 голосов
/ 26 сентября 2011

Я бы отбросил все требования и использовал бы базу данных.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...