[英]How can I speed up my Java text file parser?
我正在阅读大约600个文本文件,然后分别解析每个文件,并将所有术语添加到地图中,以便我可以知道600个文件中每个单词的频率。 (大约400MB)。
我的解析器功能包括以下步骤(有序):
在双核2.2GHz,2GB Ram上,我花了大约8分钟48秒。 我想提出有关如何加快此过程的建议。 我应该期望它这么慢吗? 如果可能的话,我怎么能(在netbeans中)知道哪些函数需要花费更多的时间来执行?
找到的独特词:398752。
码:
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 :
如果尚未使用-Xmx,请确保增加堆大小。 对于此应用程序,影响可能是惊人的。
您的代码中可能对性能产生最大影响的部分是执行最多的部分-您未显示的部分。
内存截图后更新
查看屏幕快照中的所有Pattern $ 6对象。 我认为您正在重新编译很多模式-可能是每一行。 这将花费很多时间。
更新2-将代码添加到问题之后。
是的-每行编译两种模式-显式模式,以及拆分中的“-”(当然便宜得多)。 我希望他们不要将split()添加到String,除非它以编译模式作为参数。 我看到其他一些可以改进的地方,但是没有什么比大编译好。 只需在此函数之外将模式编译一次,也许作为静态类成员即可。
如果尚未执行此操作,请使用BufferedInputStream和BufferedReader读取文件。 这样的双缓冲比单独使用BufferedInputStream或BufferedReader更好。 例如:
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
。 尝试使用单个正则表达式,该正则表达式具有与标签中每个单词匹配的组-因此,单个正则表达式可用于您的整个输入,并且不会有单独的“拆分”阶段。
否则,您的方法似乎是合理的,尽管我不明白“获取String [] ...”的含义-我认为您正在使用ArrayList。 无论如何,都应尽量减少对象的创建,无论是建造成本还是垃圾收集成本。
只是解析花费了这么长时间,还是正在读取文件?
对于文件读取,您可以通过在多个线程上读取文件来加快速度。 但是第一步是要弄清楚是花时间还是在进行解析,因此您可以解决正确的问题。
通过Netbeans探查器运行代码,找出最耗时的时间(在项目上单击鼠标右键并选择探查,请确保您没有浪费时间)。
您向我们展示的代码中没有任何东西显然是性能问题的根源。 问题可能与您解析线条或提取单词并将其放入地图的方式有关。 如果您需要更多建议,则需要发布这些方法的代码,以及声明/初始化地图的代码。
我的一般建议是分析应用程序并查看瓶颈所在,然后使用该信息找出需要优化的内容。
@Ed Staub的建议也很合理。 使用太小的堆运行应用程序会导致严重的性能问题。
看起来大部分时间都花在正则表达式上。 我将首先尝试在不使用正则表达式的情况下编写代码,然后使用多个线程,好像该进程似乎仍受CPU约束。
对于计数器,我将考虑使用TObjectIntHashMap来减少计数器的开销。 我将只使用一个映射,而不是创建字符串数组-然后使用计数来构建另一个映射,这可能会浪费大量时间。
预编译模式,而不是每次都通过该方法进行编译,并摆脱双重缓冲:使用new BufferedReader(new FileReader(...))。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.