用程序的思想浅谈优化福州一中发书

作者:福州第一中学 陈靖一

转载请注明出处 http://www.cnblogs.com/turtlegood/

欢迎用用我写的网站:享作业(zuoye.us)——一人记作业,全班齐分享!

1 现状

    当一个班级派来的几名代表想要搬书时,必须首先先在外面等待相当长的一段时间。排队排到了以后,就进入存有书的小房间。这个房间里有两个人(设为A、B),房间内有码的整整齐齐的半房间书,和许多捆、许多叠散放在地上的书(捆指100本工厂生产的、还有带子捆住的书,叠指一捆书拆开带子后剩下的一部分书)。

    代表先报上自己的班级和人数,A就会新拿出一张小纸条,上面印有某某书每人要几本,并在上面写下这个班总共要几本某某书。写完之后,他就会一项接一项地念单子上的东西。每念一项,他就停下来,在旁边的B就从地上的那些书中找到需要的。如果A要求的小于100本,B就看看有没有不成捆的书,有则从中数出要求的,没有则拆开一捆书。如果大于100本,B除了上述的做法,还会给几捆书。所有给的书,都是B处理后用手指着叫其中一个代表搬出去数数,并要求所有的书都要数过(工厂处理的一捆也不例外)。如果代表数后发现书的数量有错误,则在回到里头来要求再拿几本或还几本。

    而且,AB二人经常同时处理几个班级。因此,B本来在拿我所在的班级的294本书,却被4班的同学误以为是他们的(因为他们的书也才拿了一部分),便搬走了,造成了糊涂账。

    此外,再介绍一下其它情况。福州一中高一共16个班,每个班人数都在50人上下。一捆书是100本,其中每25本就会换个方向叠上去,所以可以很容易地从中分离25的倍数本,而分离非这个数就需要一本一本点数了。

2 改进方案

2.1 内存对齐:假设一个班50人

    现有的方式是“有几个人,点几本书,再叫你自己点,再多退少补。”例如我们班需要294本书,那么B就会拿出两捆书,再拿出一捆,由他拆开,再由他点出6本放到桌子上(桌子上都是几本几本的零散的书),剩下的再交给我们。这一整个过程中,拆开和点出6本非常花时间,而都是由B来做的,这就是一个性能瓶颈。

    考虑到反正他都要我们重新数一遍(有时一叠书的确会差一两本),B可以将书全部以50100本的规格来输出。例如294本,他就给我们3捆,我们点数之后再退还。如果是147本,他就给一捆和50本(如之前所说,50本比47本好点多了,而且50本可以预处理,而47不行)。这样,AB两人(调度器)的的耗时就会减少,代表们的等待就能减少了。

    这种方案将B(服务器、调度器)的工作转交给了代表(客户端、工作线程)来做,减少调度器负载,避免无法调度的问题。

2.2 减少调度器负载:自助多退少补

    如前面所说,假设一个班50人可以极大地将调度器负载转移到工作线程(代表)上,避免响应延迟的问题。本段的方法与那个方法结合使用更佳。

    我们先看看原来的情况。如果某个代表数出多了或少了几本书,就会回来告诉A。A并不会检查真实性(真的是代表吗,真的多了少了书吗),直接就从桌子上给书或拿走书了。从安全性的角度考虑,这里肯定要增加一道权限检查。那既然一中并没有这么做,新的方法也不检查这一道了。

    考虑到就算A来帮忙,也是从桌上拿书或放书,代表们应该多了书就自己把它放到那张桌子上,少了就从中拿。这样,调度器负载又能显著降低了。

2.3 关闭并发:处理完一个班后再处理下一个

    如上所说,现有模式是服务器经常出现并发情况。A、B说话时,并没有每一句话都明确交代是和谁讲的,导致代表理解错误。让我们看看并发的过程:CPU挂起线程1并保存状态,运行线程2,等一会儿之后再继续运行线程1并恢复状态。电脑的保存恢复挂起等操作不会花费多少时间。而且,我们说服务器并发效率高,是因为服务器是多核的,而且存在等待、避免阻塞、异步等情况。

    而人类的情况不一样。人脑并非电脑,恢复状态会经常出错,这些操作也非常费时,还会费大脑,让人糊里糊涂的,最后只会造成效率降低。如果强制要求处理完一个班后才能接下一个任务,就能避免如上的问题。也许有人会觉得,这样想要多退少补的人就要等很久了。但是如果使用了前一点的建议,这个问题将不复存在。

2.4 调度器异步:AB两人独立处理事

    现在的情况是,A发出拿某书的指令后,就在那儿看着、等着B拿书。这里“看”的时间就花去了不少。也许有人认为,这样看是为了避免数错书,但如果使用了第一个建议,这就没必要了。这样看,一点好处都没有。

    既然这样,AB两人应该分开独立做事,互不干扰。这样,原来只有一个“工作窗口”,现在就有两个了,效率是原来的两倍。也许有人认为,一个人既要看纸条,又要弄东西,两个工作之间的切换很费时间。但是别忘了,现在由于只有50和100本两种规格,给每个代表的书都是一样的,多弄几次几乎都不要再看纸条了,不会费多少大脑。

    另一种做法是,A负责将书拆成50本,B负责原来AB干的工作,这样也可以节约时间。

2.5 预处理:先拆成50本,先摆好每个班一堆

    如果说上一种方法有切换任务浪费时间之嫌,那么可以使用这种预处理方式。由于第一个优化,现在假设每个班的人数都相同,于是每个班的哪种本子数也相同。这样,AB两人可以先将每个班的所有本子摆成一堆,代表来时叫每个班拿走一堆即可。(例如,每个班都是300本科作业,50本笔记,一堆中就放了这样的350本书。)

2.6 减少查找:书按某种顺序摆

    现在的情况是,如果某种书给完了,AB就从那半个教室的“存货”中拿出一捆,随意地放在已有的、正在使用的许多捆书中。如果B要某种书,就得用眼睛扫视一遍,才能找到。

    参考数据库的索引,B可以将书按照某种顺序来摆。例如,B可以按照那张小纸条上打印的书单顺序,这样就可以从左到右地拿出书来了。

原文地址:https://www.cnblogs.com/turtlegood/p/3947615.html