3.3. 好点子

简单好用的点子并不多,而被广泛应用的点子更是罕见。而缓存就是好点子之一。Web浏览器把从网络上获得的网页放在缓存中,当你再次访问同一文档时,浏览器就直接从本地硬盘或内存中的缓存中获得网页,这要比重新下载要快得多。域名服务器把它从远程服务器上获得的应答结果保存在缓存中。有人第二次查询统一域名时,由于服务器已经缓存了结果,因此无需再次执行耗时的网络对话。操作系统从磁盘上读取数据时,很可能会将数据缓存在内存中,以便再次使用;CPU从内存中获取数据时,会将数据缓存在特殊的缓存存储器中,这个缓存存储器要比普通内存快得多。

在实际的应用程序中,缓存无处不在。几乎任何程序都会有几个函数,可以通过缓存提高其性能。但缓存的真正价值在于它是纯机械劳动。如果要提高函数的性能,可以重写函数,引入更好的数据结构,或使用更完善的算法。这需要相当的创造力,而创造力往往是稀缺资源。但添加缓存完全不需要动脑子,添加缓存所需的修改永远是一样的。如这个函数:

sub some_function {
  $result = some computation involving @_;
  return $result;
}
			

只需将它变成:

{ my %cache;
  sub some_function_with_caching {
    my $key = join ',', @_;
    return $cache{$key} if exists $cache{$key};
    $result = the same computation involving @_;
    return $cache{$key} = $result;
  }
}
			

修改方式几乎对任何函数都一样。唯一需要变化的就是join ',', @_一行。该行负责将函数的参数数组转化为字符串,当作散列的键使用。像这样将任意的值转换为字符串的操作称为序列化serialization)或马歇尔化marshalling)。 [7] 前面的join ',', @_只有当函数的参数是数字,或者是不含逗号的字符串时才能正常使用。稍后我们将详细讨论如何生成缓存的键。



[7] 马歇尔化这个名字是由于Edward Waite Marshall在1962年首次研究它而得名,之后通用电气继续研究。