确定。我应该编写一个程序,将20 GB的文件作为输入,包含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){}
}
}
答案 0 :(得分:1)
考虑使用VisualVM查明瓶颈。下面的所有其他内容都是基于猜测 - 而性能猜测通常是非常非常错误的。
我认为你的写作策略存在两个问题。
首先是你在每次写作时都开始一个新线程;第二个是你在每次写作时重新打开文件。
线程问题特别糟糕,我认为,因为我没有看到任何阻止一个文件写入文件与另一个文件重叠的内容。那么会发生什么?坦率地说,我不知道 - 但我怀疑它是好的。
相反,请考虑为所有100创建一个打开文件数组。您的操作系统可能有问题 - 但我认为可能不是。然后为每个文件创建一个工作队列。创建一组工作线程(100太多 - 想想10个左右),其中每个“拥有”它循环的一组文件,输出和清空每个文件的队列。注意队列读者和编写者之间的线程间交互 - 使用适当的队列类。
答案 1 :(得分:0)
我会抛弃整个要求并使用数据库。