1

好的。我应该编写一个程序来将一个 20 GB 的文件作为输入,其中包含 1,000,000,000 条记录,并创建某种索引以加快访问速度。我基本上决定将 10 亿条记录分成 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){}
    }
}
4

2 回答 2

1

考虑使用 VisualVM 来查明瓶颈。下面的所有其他内容都是基于猜测 - 性能猜测通常是非常非常错误的。

认为你的写作策略有两个问题。

第一个是您在每次写入时都启动一个新线程;第二个是您在每次写入时都重新打开文件。

我认为,线程问题特别糟糕,因为我没有看到任何阻止一个线程在文件上写入与另一个线程重叠的东西。那会发生什么?坦率地说,我不知道——但我怀疑它是否好。

相反,考虑为所有 100 个打开文件创建一个数组。您的操作系统可能对此有问题 - 但我认为可能没有。然后为每个文件创建一个工作队列。创建一组工作线程(100 太多 - 想想 10 左右),其中每个“拥有”它循环通过的一组文件,输出和清空每个文件的队列。注意队列读取器和写入器之间的线程间交互 - 使用适当的队列类。

于 2011-09-26T00:47:03.057 回答
0

我会丢弃整个需求并使用数据库。

于 2011-09-26T10:32:29.783 回答