【发布时间】:2012-10-23 01:37:35
【问题描述】:
背景
这是一个优化问题。 Oracle Forms XML 文件具有以下元素:
<Trigger TriggerName="name" TriggerText="SELECT * FROM DUAL" ... />
TriggerText 是任意 SQL 代码。每个 SQL 语句都被提取到唯一命名的文件中,例如:
sql/module=DIAL_ACCESS+trigger=KEY-LISTVAL+filename=d_access.fmb.sql
sql/module=REP_PAT_SEEN+trigger=KEY-LISTVAL+filename=rep_pat_seen.fmb.sql
我编写了一个脚本来使用蛮力方法生成一个完全重复的列表。
问题
有 37,497 个文件可供相互比较;将一个文件与所有其他文件进行比较需要 8 分钟。从逻辑上讲,如果A = B 和A = C,则无需检查B = C。那么问题来了:如何消除冗余比较?
脚本将在大约 208 天内完成。
脚本源代码
对比脚本如下:
#!/bin/bash
echo Loading directory ...
for i in $(find sql/ -type f -name \*.sql); do
echo Comparing $i ...
for j in $(find sql/ -type f -name \*.sql); do
if [ "$i" = "$j" ]; then
continue;
fi
# Case insensitive compare, ignore spaces
diff -IEbwBaq $i $j > /dev/null
# 0 = no difference (i.e., duplicate code)
if [ $? = 0 ]; then
echo $i :: $j >> clones.txt
fi
done
done
问题
您将如何优化脚本以便检查克隆代码的速度提高几个数量级?
想法 #1
将匹配的文件删除到另一个目录,这样就不需要检查两次了。
系统约束
使用带有 SSD 的四核 CPU;尽可能避免使用云服务。该系统是一台安装了 Cygwin 的基于 Windows 的机器——欢迎使用其他语言的算法或解决方案。
谢谢!
【问题讨论】:
-
两个初始问题:1)“重复”文件中的数据是否总是按相同的顺序排列,或者行是否可以乱序?我假设是前者,因为您使用的是
diff; 2)要被视为重复,我们可以假设它必须区分大小写吗?我假设不敏感,因为您专门将diff与不区分大小写的比较一起使用 - 但如果区分大小写,则存在更好的方法。 -
1) 文件应按相同顺序返回;这可以使用排序命令或
find的参数强制执行。 2)大小写需要不敏感匹配;只有空格和空行不同的文件必须被视为重复代码。 -
如果你想要性能,bash 脚本不是一个好主意。
-
Bash 不是问题,Dani(虽然我同意基于 C 的解决方案会执行得更快,但即使比较所有 37,000 个文件只需要 30 秒 [而不是 8 分钟],那也是还有 12 天)。算法是
O(n^2)任何语言。
标签: perl bash optimization big-o code-duplication