我们有一个处理平面文件并(仅通过几次验证)插入数据库的系统。
此代码:
//There can be 8 million lines-of-codes
for(String line: lines){
if (!Class.isBranchNoValid(validBranchNoArr, obj.branchNo)){
continue;
}
list.add(line);
}
isBranchNoValid
的定义:
//the array length ranges from 2 to 5 only
public static boolean isBranchNoValid(String[] validBranchNoArr, String branchNo) {
for (int i = 0; i < validBranchNoArr.length; i++) {
if (validBranchNoArr[i].equals(branchNo)) {
return true;
}
}
return false;
}
验证是在行级别进行的(我们必须过滤或跳过数组中没有branchNo
的行)。以前不是这样(过滤)。
现在,高性能降级正在困扰着我们。
我了解(可能是我错了),这种重复的函数调用导致大量stack
创建,从而导致很高的GC
调用。
我想不出一种方法(甚至有可能)来执行这种过滤器而不会造成性能降低的高昂代价(有一点点差别就可以了)。
答案 0 :(得分:0)
这肯定不是堆栈问题,因为您的函数不是递归的,因此两次调用之间的堆栈中没有任何内容。每次调用后,变量将被删除,因为不再需要它们了。
您可以将有效数字放在一个集合中,并使用该数字进行一些优化,但对于您而言,由于您最多有5个元素,因此我不确定它是否会带来任何好处。
答案 1 :(得分:0)
因此,您的方案中可能存在几个瓶颈。
通常,您会说IO是最慢的,所以1.和2.您什么也没说,除了2.已更改,对吧?太奇怪了。
无论如何,如果您想对其进行优化,那么我将不会传递约800万次该数组,并且也不会每次都对其进行迭代。由于您的有效分支是已知的,因此请从中创建一个HashSet
-它具有O(1)访问权限。
Set<String> validBranches = Arrays.stream(branches)
.collect(Collectors.toCollection(HashSet::new));
然后,迭代行
for (String line : lines) {
YourObject obj = parse(line);
if (validBranches.contains(obj.branchNo)) {
writeToDb(obj);
}
}
或者,在流版本中
Files.lines(yourPath)
.map(this::parse)
.filter(o -> validBranches.contains(o.branchNo))
.forEach(this::writeToDb);
我还将检查首先收集一批对象然后写入db效率是否更高。另外,如果解析需要大量时间,则并行处理这些行可能会提高速度。