数据库系统实现课程笔记之:提高程序性能
一:提高程序性能
1. 磁盘(Disk)未必比内存(Memory)慢。
原理:Memory的随机存取(random access)需要消耗大量时间,数量级大概是500+个cycle,也就是每次随机存取,CPU都要花时间等数据从内存读过来。而虽然磁盘一次读取的时间确实比内存慢很多,但是顺序读取的话,系统会自动预读下一个数据放在L2 cache里面,而从L2到CPU里面的时间只需一个cycle;也就是说,在磁盘顺序读取大量数据,忽略掉overhead,可以达到一个cycle一组数据的速度,如果你的硬盘速度是5G/s,那平摊速度也基本达到5G/s。当然这个还跟硬盘数据存储结构有关,硬盘有很多能平行存取的盘,横向存数据的话就能平行地同时读取下一组数据;如果数据是纵向存在同一个盘的就不行,但是如果两次读取之间的其他代码cycle足够多的话,还是一样省时间(不过内存的随机存取,有足够的代码塞在两次读取之间也可以避免浪费时间)。
应用举例:将磁盘里的数据依次读出放在链表(不放数组是因为有时候不知道数据长度)里面以便下次读取,不如在需要时直接从磁盘读取。
2. 条件语句极大降低运行速度。
原理:学过Architecture的应该知道,进行条件语句(branch,包括循环的条件)的执行时,由于系统要预先读入一定数量的命令来增加速度,便进行条件语句块的猜测(即猜测是否进入if块还是else块),如果真的执行到那个条件语句时发现猜测是错误的,就把之前预读预先执行的命令全部回退掉(flash),重新执行正确的部分。结果就是之前的那些cycle时间都浪费掉,而且命令也是从内存读入的,命令指针改变了,就需要等待新的地址下的命令(即随机读取,需要500cycle)。因此我们应该尽量避免使用条件语句,或者避免预测错误。另外提一下:条件语句块的猜测(branch predicate)第一次会进入else的部分,每次执行后会记录更改predicate table以便下次有数据参照进行预测,至于用什么策略进行猜测是系统决定的。
应用举例:写如下语句纯属浪费时间,直接一句 num = 0; 就好了。
if(num != 0) num = 0;
for(int i=0; i<100; i++){ if( i != 0) ; //nothing to do else //i初始为0,会进入这部分语句块 Initialization(); if( i == 99)//前99次循环都不会试图进入这个语句块 Finalize(); }
int sum = 0; for(int i=0; i<100; i++){ if(a[i] >= 0)//不要写类似于if(a[i] <0) i++; 来跳过某些index的语句 sum += a[i]; }