由“百鸡问题”浅谈程序性能
今天中午下了一个“易语言”瞧了瞧,看到里面有个示例是“百鸡”问题,于是深思了一下。
题目:母鸡每只3元,公鸡每只2元,小鸡每只0.5元,计算一下如何100块钱买100只鸡。
思路:用数学的观点来解一下题,母鸡i只,公鸡j只,小鸡k只,那么有3i+2j+0.5k=100,i+j+k=100。用程序解决的思路,最明显的就是3层嵌套循环。
JavaScript代码如下:
<script
language="JavaScript">
<!--
//3i+2j+0.5k=100
//i+j+k=100
<!--
//3i+2j+0.5k=100
//i+j+k=100
//实现一:三次循环
var loop=0;
var begin = new Date();
for (var i=1; i<100; i++) {//一层
for (var j=0; j<=100; j++) {//二层
for (var k=0; k<=100; k++) {//三层
var begin = new Date();
for (var i=1; i<100; i++) {//一层
for (var j=0; j<=100; j++) {//二层
for (var k=0; k<=100; k++) {//三层
loop++;
var m = 3*i+2*j+0.5*k;
var n = i+j+k;
if (m==100 && n==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
var m = 3*i+2*j+0.5*k;
var n = i+j+k;
if (m==100 && n==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
}
}
}
var end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
}
}
var end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
//实现二:改进一下,减少循环次数
loop=0;
begin = new Date();
for (var i=1; i<100; i++) {
for (var j=0; j<=100-i; j++) {//二层,加了-i
for (var k=0; k<=100-i-j; k++) {//三层,加了-i-j
loop++;
var m = 3*i+2*j+0.5*k;
var n = i+j+k;
if (m==100 && n==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
loop=0;
begin = new Date();
for (var i=1; i<100; i++) {
for (var j=0; j<=100-i; j++) {//二层,加了-i
for (var k=0; k<=100-i-j; k++) {//三层,加了-i-j
loop++;
var m = 3*i+2*j+0.5*k;
var n = i+j+k;
if (m==100 && n==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
}
}
}
end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
}
}
end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
//实现三:再改进一下,更多减少循环次数
loop=0;
begin = new Date();
for (var i=1; i<100; i++) {//一层
for (var j=0; j<=100-i; j++) {//二层,去掉了第三层
begin = new Date();
for (var i=1; i<100; i++) {//一层
for (var j=0; j<=100-i; j++) {//二层,去掉了第三层
loop++;
var k = 100-i-j;
var m = 3*i+2*j+0.5*k;
if (m==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
var k = 100-i-j;
var m = 3*i+2*j+0.5*k;
if (m==100) {
document.write("3 * <b>"+i+"</b> + 2 * <b>"+j+"</b> + 0.5 * <b>"+k+"</b> = 100<br>");
}
}
}
end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
//-->
</script>
}
end = new Date();
document.write("loop="+loop+",time="+(end-begin)+"<hr>");
//-->
</script>
程序执行结果:
3 *
2 + 2 * 30 + 0.5 * 68 = 100
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=1009899,time=3255
3 * 2 + 2 * 30 + 0.5 * 68 = 100
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=171699,time=520
3 * 2 + 2 * 30 + 0.5 * 68 = 100
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=5049,time=20
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=1009899,time=3255
3 * 2 + 2 * 30 + 0.5 * 68 = 100
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=171699,time=520
3 * 2 + 2 * 30 + 0.5 * 68 = 100
3 * 5 + 2 * 25 + 0.5 * 70 = 100
3 * 8 + 2 * 20 + 0.5 * 72 = 100
3 * 11 + 2 * 15 + 0.5 * 74 = 100
3 * 14 + 2 * 10 + 0.5 * 76 = 100
3 * 17 + 2 * 5 + 0.5 * 78 = 100
3 * 20 + 2 * 0 + 0.5 * 80 = 100
loop=5049,time=20
好的,结果出来了,我们看到三种实现方法都得到了一样的结果(其中的2*0项可以过滤掉),但是性能差异非常大。
1)loop=1009899,time=3255,我的浏览器差点死掉
2)loop=171699,time=520,浏览器还是有点慢
3)loop=5049,time=20,浏览器非常快,打开了结果就出来了。
上例中,20毫秒一般人察觉不到,0.5秒感觉也不明显,3秒就很慢了……
现在我们经常遇到的一个问题是,程序在开发阶段,执行的完全正常,找测试人员测试也没问题,但是一到上线后,性能马上出问题了,运行速度像蜗牛,客户不堪忍受,为什么?简单的说,开发人员自测,估计也就几条数据,测试人员测试,估计也就几十上百条数据,一般的程序代码,在这个数量级,性能瓶颈根本就表现不出来。但是上线后,客户的数据一般都上升到10000级别的,如果程序代码中没有做到细微之处都很严谨的话,问题就马上暴露出来了。