首先说说缓存的问题,比如我们有1000000个字符串构成的List<string>需要缓存在内存中,大约占用了100M的内存空间。如果需要对这些数据进行检索的话,很明显直接由于数据量太大,即使在内存中检索效率也不会太高。
一般可以想到的办法就是利用层次话的字典结构来解决,比如SortedList<char, Sorted<char, List<string>> 这样就构成了2层结构,可以把字符串的第一个和第二个字母作为字典的Key,这样一下子可以把检索的数据量下降2个数量级都不止。
当然,在现实应用中可能存放的不是List<string>而是一个List<Entity>,这个Entity里面可能有N个属性,我们可能需要检索的就不止是一个字段这么简单了,可能需要为了检索Entity中的ID属性做个Dictionary<int, Entity>,也可能需要为了检索其中的Name属性做一个Dictionary<char, List<Entity>>,这就需要多份字典。
前面说过了,这个原始数据List<string>占用100M内存,那么你可能会想了,再来一个SortedList<char, Sorted<char, List<string>>那么就需要200M内存了,如果多份字典的话,更占内存?但是想想字典结构的效率真是高啊,怎么取舍呢?其实,如果你试验一下的话可以发现,再弄个SortedList<char, Sorted<char, List<string>> 可能只会占用1M内存,加起来一共是101M而不是200M,这是为什么呢?
记得引用类型和值类型的区别吗,如果你的数据结构大部分是引用类型,比如string的话,一个string的List,它其实存放了N个处于托管堆上的string的指针,那么如果我们再来一个字典结构的话,不是说我们就多存放了这些string,而是多存放了一套指针,外加Key所占用的一些空间。所以,遇到这种情况不用吝啬多一些字典结构来提高效率。
上面的例子我想说明一个问题,缓存多份数据不一定会占用相同的多份内存。
还有,缓存的数据可以放在那里呢?一般来说有这么几种,static变量,.NET类库提供的HttpRuntime.Cache或者就是一些分布式的缓存解决方案,比如memcached。
有一些误解,很多人非常不喜欢static变量,我想有两个原因,一是可能觉得把100M数据存放到一个变量中,这是很可怕的事情,一个变量竟然占用100M内存,其实我们大多时候缓存的是一个引用类型,变量存放的只是一个指针罢了,100M的值类型确实可怕,二是很多做ASP.NET的人会觉得不能乱用static变量,就产生了这个错觉。其实,我觉得static变量的问题在于它没有线程安全的机制,二是它作为缓存方案不能过期,一旦创建后也不能删除,只能把它设置为空引用,等待GC回收。但对于某些情况,静态变量是适合的,比如我们缓存的数据是只读并且永远不需要过期的,静态变量作为缓存的确足够简单,也不用担心“丢失”!
HttpRuntime.Cache之类的方案的优势在于它提供了过期、依赖、线程同步的支持,也是我们用的最多的。
最后说说分布式缓存解决方案,比如memcached。其实我觉得在一般情况下不要去随便使用分布式的缓存方案,除非我们能满足以下的需求:1、缓存的数据非常多,一台机器的内存不够用,确实需要分布。2、需要确保数据不能丢失,在多台机器上做备份。为什么说不要轻易用,因为分布是有代价的,如果应用服务器和缓存服务器分开的话,势必就需要TCP通讯,这是一个消耗,另外一个消耗是缓存的数据需要序列化和反序列化。分布式缓存使用缓存一些直接能绑定到UI的数据,或者说直接用于呈现的数据,对于大块的数据非常不适合存放到memcached中。比如之前提到的List<string>,如果这个数据是100M,它不能直接用需要做一些计算再返回给WEB服务器,那么我们做的事情就是序列化后缓存到memcached中,然后再反序列化从TCP获取,放到内存中计算后返回给WEB服务器,然后内存中的100M数据等待GC回收。其中白白折腾了网络、CPU和内存(虽然会回收,但是GC一直回收100M的数据,谁受得了)。
上面的例子我想说明一个问题,缓存的方案需要根据应用来选择,静态变量不一定不好,分布式缓存也不一定好。
最后,还有一个有关CPU占用的有趣问题,很多人很怕服务器占用CPU很高,觉得CPU占用一高就有性能问题。其实我想说的是,有的时候CPU占用的高不一定是坏事情。假设有两个网站。A网站它的数据源是数据库,每一个请求(假设是同步请求数据库)都需要1秒来从数据库获取数据,由于IO操作的时间会比CPU处理数据时间长很多,所以这个网站即使很繁忙,WEB服务器的CPU占用还不是很高,用户一个页面打开至少要等1秒,网站管理员看着WEB服务器CPU常年处理20%的情况觉得很满意,但想想这真能说明网站性能高吗?还有一个网站B,它数据都是从内存中读取的,由于内存的操作会比IO操作快很多,CPU处理一个请求的数据只需要20毫秒,由于网站页面速度快,用户满意度和数量比A网站高很多,CPU很忙,常年处于90%的负荷,网站管理员看了觉得很害怕,是不是哪里出现性能问题了,服务器会不会瘫痪。其实,我觉得B网站的管理员应该高兴,因为B网站的用户比A网站高一个数量级,服务器虽然很忙,但页面打开速度很快,CPU得到了充分的利用。
上面的例子我想说明一个问题,只要不是死循环等恶性代码问题的话,CPU如果占用的高不一定就是坏事情。
很多时候事情往往不是像我们想的那样,很多时候好的东西往往也不一定是适合的。希望这三个小例子能给大家一些启发。
最后,想说一下最近使用LINQ的经验。不可否认,如果不分层,在网站中直接使用LINQ TO SQL和LINQ进行数据的存取以及转换,结合匿名类型等特性,至少提高开发效率一倍。有很多人关心LINQ的效率,其实我们应该要区分LINQ还是LINQ TO SQL,是使用LINQ TO SQL进行数据的转换还是使用LINQ进行内存中数据的转换很关键。要知道,尽量从数据库中拿少点东西,尽量少的进行数据库访问,所以说LINQ TO SQL的代码不适合放在循环中,如果要对大量数据操作的话,要先ToList()加载到内存中,然后之后的工作就是LINQ(TO OBJECT)了。如果项目对性能要求高的话,尽量在做好项目之后,多看看SQL监视器,观察一下页面究竟访问了几次数据库,因为程序写的很爽的时候可能会迷糊,导致页面访问N次数据库,这个时候要使用LoadWith来“化解”。
分享到:
相关推荐
目前主流CPU都具有一级缓存和二级缓存,一级缓存用于暂时存储各类运算指令,并向CPU递送所需数据,二级缓存就是存储那些CPU处理时需要的,但是一级缓存无法存储的那些数据,以此进一步提高CPU访问速度,那么如何为...
CPU缓存失效导致性能下降:主板BIOS损坏导致CPU缓存失效.pdf
每个程序员都应该了解的_CPU_高速缓存
DELL服务器CPU的主频、缓存、前端总线以及QPI的一些基本知识.pdf
本文主要是关于二极缓存的介绍,并阐述了二级缓存是否损坏的查看方法,并探讨了二级缓存对CPU性能的影响。二级缓存二级缓存的工作原理是当CPU要读取一个数据时,首先从缓存中查找,如果找到就立即读取并送给CPU处理...
为了节省带宽同时又不增加CPU负担,我们消除了导致CPU效率低下的函数调用,提出了部分分解存储与查询的即时(JiT)编译相结合的方案。
缓存与CPU 解析处理器缓存的作用.pdf
从底层数据结构和CPU缓存两方面剖析LinkedList的查询效率为什么比ArrayList低。以前只直到数据结构会影响两者的查询效率,偶然间得知cpu缓存(硬件级别)也会有影响
开启CPU二级缓存 经典的东西 适合老款电脑
这是一个检视cpu的软件,可以观察cpu名称,厂商,时钟,缓存,点击此处,立即下载是一个检视cpu的软件,可以观察cpu名称,厂商,时钟,缓存,点击此处,立即下载是一个检视cpu的软件,可以观察cpu名称,厂商,时钟,...
CPU二级缓存打开器576479373 最近登录: 2008-12-28认证信息: 卖家信用: 商品数量: 0 开店时间: 2008-05-31 店铺所在地: 北京 您好,欢迎您光临我的小店"576479373"!我
时钟频率和二级缓存大小对CPU效率的影响.pdf
缓存、缓存算法和缓存框架简介
CPU的二级缓存直接影响着用户计算机的性能,CPU二级缓存越高,则系统运行越快,应用程序相应的执行时间也越短
什么是CPU一级缓存.pdf
Android通过IPackageStatsObserver.aidl 、PackageStats.aidl两个AIDL文件获取第三方应用的占用大小,包括缓存、数据、应用大小,经验证和手机设置里面显示的大小完全一致。。。。。。如果还需要其他比如清除缓存之...
什么是CPU一级缓存归纳.pdf
最近发现php网站发布信息比较慢,而且同网站目录下的asp经常登录后立即就重新登录,立即考虑到服务器资源占用问题,所以进服务器看到原来mysql占用率较高 25-60%左右,偶尔能跑到100%,所有导致上述问题的发生
5-3JMM-CPU缓存一致性协议MESI.mp4
linux下查看被缓存的文件工具