我正在阅读大约600个文本文件,然后单独解析每个文件并将所有术语添加到地图中,这样我就可以知道600个文件中每个单词的频率。 (约400MB)。
我的解析器功能包括以下步骤(已订购):
在双核2.2GHz,2GB Ram中,我花了大约8分48秒。我想就如何加快这个过程提出建议。我应该期待这么慢吗?如果可能的话,我怎么知道(在netbeans中)哪些函数需要更多的时间来执行?
找到独特的单词:398752。
CODE:
File file = new File(dir);
String[] files = file.list();
for (int i = 0; i < files.length; i++) {
BufferedReader br = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(
new FileInputStream(dir + files[i])), encoding));
try {
String line;
while ((line = br.readLine()) != null) {
parsedString = parseString(line); // parse the string
m = stringToMap(parsedString, m);
}
} finally {
br.close();
}
}
编辑:检查一下:
![在此处输入图片说明] [1]
我不知道该结束什么。
编辑:使用此功能的时间为80%
public String [] parseString(String sentence){
// separators; ,:;'"\/<>()[]*~^ºª+&%$ etc..
String[] parts = sentence.toLowerCase().split("[,\\s\\-:\\?\\!\\«\\»\\'\\´\\`\\\"\\.\\\\\\/()<>*º;+&ª%\\[\\]~^]");
Map<String, String> o = new HashMap<String, String>(); // save the hyphened words, aaa-bbb like Map<aaa,bbb>
Pattern pattern = Pattern.compile("(?<![A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû-])[A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû]+-[A-Za-zÁÉÍÓÚÀÃÂÊÎÔÛáéíóúàãâêîôû]+(?![A-Za-z-])");
Matcher matcher = pattern.matcher(sentence);
// Find all matches like this: ("aaa-bb or bbb-cc") and put it to map to later add this words to the original map and discount the single words "aaa-aa" like "aaa" and "aa"
for(int i=0; matcher.find(); i++){
String [] tempo = matcher.group().split("-");
o.put(tempo[0], tempo[1]);
}
//System.out.println("words: " + o);
ArrayList temp = new ArrayList();
temp.addAll(Arrays.asList(parts));
for (Map.Entry<String, String> entry : o.entrySet()) {
String key = entry.getKey();
String value = entry.getValue();
temp.add(key+"-"+value);
if(temp.indexOf(key)!=-1){
temp.remove(temp.indexOf(key));
}
if(temp.indexOf(value)!=-1){
temp.remove(temp.indexOf(value));
}
}
String []strArray = new String[temp.size()];
temp.toArray(strArray);
return strArray;
}
600个文件,每个文件大约0.5MB
EDIT3# - 每次读取一行时都不再编译该模式。新图片是:
2:
答案 0 :(得分:3)
请确保使用-Xmx增加堆大小(如果尚未增加)。对于这个应用程序,影响可能是惊人的。
代码中可能影响最大的部分是执行次数最多的部分 - 这些部分是您未显示的部分。
内存屏幕截图后更新
查看屏幕截图中的所有Pattern $ 6对象。我认为你正在重新编译模式 - 可能是每一行。这将花费很多时间。
更新2 - 代码添加到问题后。
Yup - 在每一行编译的两种模式 - 明确的一种,以及分裂中的“ - ”(当然要便宜得多)。我希望他们没有将split()添加到String而不将编译模式作为参数。我看到其他一些可以改进的东西,但没有其他东西像大编译。只需在此函数外部编译模式一次,可以作为静态类成员。
答案 1 :(得分:1)
如果您还没有这样做,请使用BufferedInputStream和BufferedReader来读取文件。像这样的双缓冲比单独使用BufferedInputStream或BufferedReader要好得多。 E.g:
BufferedReader rdr = new BufferedReader(
new InputStreamReader(
new BufferedInputStream(
new FileInputStream(aFile)
)
/* add an encoding arg here (e.g., ', "UTF-8"') if appropriate */
)
);
如果您发布代码的相关部分,我们就有机会评论如何改进处理。
编辑:
根据您的修改,以下是一些建议:
parseString
时编译。temp.indexOf(key)
和temp.indexOf(value)
的值,然后使用存储的值,而不是第二次调用indexOf
。答案 2 :(得分:1)
尝试使用具有匹配标记内每个单词的组的单个正则表达式 - 因此单个正则表达式可用于整个输入,并且不会有单独的“拆分”阶段。
否则你的方法似乎是合理的,虽然我不明白你的意思是“获取String [] ......” - 我以为你使用的是ArrayList。无论如何,尝试最小化对象的创建,包括建筑成本和垃圾收集成本。
答案 3 :(得分:1)
只是解析花了这么长时间,还是文件读取?
对于文件读取,您可以通过读取多个线程上的文件来加快速度。但第一步是弄清楚它是读书还是正在解析的解析,以便你能解决正确的问题。
答案 4 :(得分:1)
通过Netbeans探查器运行代码并找出它花费最多时间的位置(在项目上单击鼠标右键并选择配置文件,确保您没有时间记忆)。
答案 5 :(得分:1)
您向我们展示的代码中没有任何内容是性能问题的明显来源。问题可能与解析线条或提取单词并将其放入地图的方式有关。如果您需要更多建议,您需要发布这些方法的代码,以及声明/初始化地图的代码。
我的一般建议是分析应用程序并查看瓶颈所在,并使用该信息确定需要优化的内容。
@Ed Staub的建议也很合理。运行具有太小的堆的应用程序会导致严重的性能问题。
答案 6 :(得分:0)
看起来它大部分时间花在正则表达式上。我首先尝试编写代码而不使用正则表达式然后使用多个线程,就好像进程仍然看起来是CPU绑定的。
对于计数器,我会考虑使用TObjectIntHashMap来减少计数器的开销。我只使用一个地图,而不是创建一个字符串数组 - 然后我用它来构建另一个地图,这可能会浪费很多时间。
答案 7 :(得分:0)
预编译模式,而不是每次通过该方法编译它,并摆脱双缓冲:使用新的BufferedReader(新的FileReader(...))。