Posts Tagged ‘性能’

IO和性能

July 3rd, 2009

最近几天看了几家互联网公司的和架构有关的PPT,有支付宝,linkedin,douban等。这些公司所使用的具体的技术有差别,但是为了能做到支持大规模访问,他们都在与缓慢的IO做斗争! 比如说豆瓣网的历次架构变迁,不是因为磁盘IO成为瓶颈,就是因为网络IO成为瓶颈。如果能把IO的问题解决掉,那么对于互联网企业来说,性能问题就解决掉一半了,我想。

与飞速的CPU和内存相比,磁盘和网络的IO慢如蜗牛,这是问题的根源。如果没有大规模廉价而又足够快的存储方案出现的话,这个问题还将继续下去。我们只能期待这一革命性的技术出现来从根本上解决这一问题吧!

那对于现在的我们该怎么办呢?大家的想法可能都是一样的,一是加快IO速度,二是避免不必要的IO。豆瓣曾经通过购买更高性能的硬盘来解决这个问题,如果想要更好的效果,需要投入更多的资金来购买整套的高性能存储方案,但是这成本太高了,很多公司后来都会放弃。于是大部分公司都会极力采用后者,就是避免不必要的IO,缓存就是用来做这样的事的。

将低速介质上的数据放到高速介质上,访问者先访问高速介质,在找不到需要数据时才访问低速介质,以此来提升访问数据的速度,这样的技术就是缓存了。设在一段时间内有m次没有命中缓存,n次命中,而访问一次缓存的时间是t1, 访问慢速介质的时间是t2,那么为了是缓存有效就得满足不等式: m * (t1 + t2) + n * t1 < (m + n) * t2, 于是有 m / n < t2 / t1 -1 。由此可见,在介质的速度比一定的情况下,命中比率要高于一定的值,缓存才有效果。提高命中比率,就是要把那些最常用的数据放到缓存里。另一方面,缓存里数据如果被修改了,就要同步到低速存储介质中,同样的,如果低速存储介质的数据被修改了,也要同步到缓存里。如果加上同步的开销,就需要更高的命中率。提高命中率和保证数据的同步,是使用缓存的两个艰巨的任务。

豆瓣网使用memcache,还使用专门的nigix服务器来提供图片的服务,其实也是cache。linkedin则使用了数十台大内存的服务器作为缓存服务器,运行着用c++写的专门的缓存程序。可见这些网站在使用缓存方面都是不遗余力呀。如果能把缓存用好,那么就把一大半的IO问题解决掉了。

IO往往会成为程序的瓶颈,因此,程序员应当时刻的注意,你写的代码是否在进行IO操作,是否可以减少IO操作,等等。

  • Share/Bookmark

软件的质量属性

June 17th, 2009

1 软件的质量属性

如果要我们描述一个人,我们会说,他的年龄多少,性别是什么,姓名是什么,等等。这些年龄,性别和姓名等,就是一个人的属性。类比的,软件也有属性,本文将讨论一下和软件质量相关的一些重要的属性。

2.1 正确性(Correctness)

正确性是软件最基本,最重要的属性。他代表了这个软件能够正确的执行计算并给出用户正确的结果。如果软件不能保证正确性,那么这个软件将没有价值可言。比如,一个总是计算错误的财务软件,显然是没有任何用处的。对小型的,功能单一的软件来说,正确性是显而易见的,要么正确,要么不正确。但是对于大型的复杂的软件来说,衡量正确性的标准都相当复杂或不确定,所以正确性本身也不是个简单的是和否的问题了。需求不等于正确性,需求不仅要求正确性,还会要求其他属性,如性能等,需求也不一定要求100%的正确性,只要计算结果对于最终用户来说是可用的就可以了。

2.2 有效性

有效性是指软件能在有效的时间内给出计算结果。一个无效的软件,即便其必然能得到正确的结果,也是无价值的。比如,穷举法总是正确的,但是在解决某些问题时,穷举法并不能在有效的时间内给出结果。如果一个用来预报明天天气的软件,却要在后天才能算出明天的天气情况,即使算正确了,也是没有意义的。

2.3 可用性(Availability)

可用性和有效性是对正确性和和有效性的一个综合,一个正确而有效的软件,才是可用的软件。如果在一段里,一个软件总能在有效的时间里给出正确的结果,那么这个软件在这段时间里就是可用的。而高可用,就是说一个软件可以在相当长的时间里保持可用性。

2.4 健壮性(Robustness)

在异常状况下,软件仍能够保持可用性,被称为健壮性。如果一个软件,由于输入数据不正确,或者运行时发生了些不正常状况等,就立刻崩溃,以致于不能再工作,显然是不健壮的。相反的,在这样恶劣的情况下,仍能够工作,则是健壮的。

2.5 可靠性(Reliability)

可靠性是指一个软件能在很长的时间内保持可用。一个健壮的软件,显然能提可靠性。对于某些持续提供服务的软件来说,高可用是很重要的。比如,网络服务器,我们往往需要它7×24不停的可用。通过故障恢复等措施,可以提供软件的可靠性。

2.6 容错性

容错性是指软件能够自动的纠正错误的输入,得出正确的结果。比如大部分的浏览器,都能够解析不是很严格正确的html。容错性可以提高最终用户的用户体验。

2.7 性能

直观的说,性能就是软件快不快。但是仔细考虑的话,可以把性能分成很多更细的属性。

2.7.1 效率

在完成相同的计算任务时,软件占用越少的CPU时间越少的内存空间等计算资源,性能越高。换句话说,在相同的计算资源的条件下,完成的计算任务越多,效率越高。效率就是软件利用计算资源的能力。

2.7.2 响应时间

响应是软件对用户操作作出回应的速度。用户使用软件时,犹如和人交流,快速的响应,犹如和用户对答如流,会让用户更加的开心。比如,点击开始按钮后,出现一个显示计算进度的进度条,要比立刻全屏锁定,不让用户做任何操作要好多了即使后者可以更快的完成所有的任务。

2.7.3 吞吐量

单位时间内,软件能处理的数据量,或任务量。比如,一个网络服务器,单位时间内内够处理的http请求,和生成的html的数据量。吞吐量侧重于从输入输出上衡量软件的性能。

2.7.4 负载

负载是软件能承受的访问压力的能力。同样以网络服务器举例,能同时支持越多的用户访问,负载能力就越强。负载和吞吐量不完全相同。吞吐量很高,比一定能支持很多人访问;相应的,负载很好,单位时间内的输入输出可能并不高。

2.8 可伸缩性

在不修改,或者很少修改代码的情况下,通过添加硬件计算资源就可以提高软件整体性能的能力。对于大型的服务器软件,可伸缩性是很被重视的。理想情况下,系统的计算能力能随着硬件的添加而线性增长,很可惜,没有软件能达到这一程度。大部分软件在设计之初并没有考虑到可伸缩性,根本就不可伸缩,而另一些软件,增添硬件会使性能下降,或降低可靠性。

2.9 安全性

软件保护重要资源免受非法访问或恶意攻击的能力。安全性对于某些软件来说是非常重要的,对于另外一些软件来说则不那么重要。安全是一个复杂的工程,往往和整个软件运行环境相关。

2.10 适应性

软件不需要修改,就可以在别的环境下运行的能力。适应性高的程序,在设计之初就要考虑到软件可能运行的各种计算环境,并做好相对的准备。这样在程序生成后,不需要修改就可以在不同的环境下运行。

2.11 可移植性

将软件从一个环境下迁移到另一个环境下运行的能力。为了实现可移植,要抽象出软件所依赖的计算资源,在这一抽象层之上开发。移植时,只要修改抽象层在别的环境下的实现,而不必修改其上的部分。

2.12 一致性

软件的结构一致,是指软件用相同的方式处理相同的问题,用相同的符号表示相同的概念。一致性给程序带来美感,使程序更简单。一致性差的软件,就像被混淆器混淆过,最终只能使程序失去生命力。

2.13 可读性

软件代码可以被阅读和理解的能力。除了正确和有效,可读性可能就是我们最关心的属性。可读性好的代码,即便有缺陷,还有修正的机会,相反,犹如天书一般的代码,不能进化,没有前途。一致性可以提高可读性。

2.14 可扩展性

在尽量不修改原有代码的基础上通过添加新的代码而修正缺陷,实现新功能的能力。扩展性要求程序在设计之初就考虑到程序的哪些地方将来可能需要扩展,并留下余地。

2.15 可测试性

程序对测试方法和测试工具的友好性。容易测试的程序,在变动之后才容易验证其正确性。

2.16 可维护性

软件投入生产后被维护的难易程度。理想状态下,软件在投入生产后不需要停止服务,只要修改少部分代码,就可以实现新的功能需求或错误修正。一致性好,可读性好,可扩展性好,可测试性好的软件拥有更好的可维护性。一个上线后不久就没人看得懂源程序,修改一个小bug就要牵一发而动全身,修改后不知道其他功能能否正常运行的软件,是维护人员的噩梦。

2.17 易用性

指最终使用者学习和使用软件的难以程度。

3 属性间的相互影响

以上列出的各属性并非相互之间没有关系的,有些属性的提高利于其它属性的提高,而有些属性的提高则会降低其他属性。比如,程序中做了很多便于用户使用的计算工作,必然会降低程序的吞吐量;为了提高代码效率而使用各种小技巧导致代码难以阅读和理解;越容易阅读的代码,越容易扩展,越容易维护,等等。具体它们之间是怎样的关系要具体问题具体分析。

4 小结

软件的众多属性可以分成内在和外在两大类。内在属性是用户感觉不到的,而外在属性是用户感觉得到的属性。比如正确性和响应速度是用户感觉得到的,但是可扩展性和易读性用户就不知道了。我们应当在满足外在属性要求的同时提高内在属性,不能外表光鲜,内里脏乱。不同的软件,不同的场景,对不同的属性的要求是不同的,而且这些属性也有相互冲突的,因此我们不可能兼顾所有,只能抓住主要矛盾。一般情况下,正确性,有效性和易读性是最重要的。

  • Share/Bookmark

Console的写操作在windows和linux下的性能差异

April 9th, 2008

在做项目的时候,为了调试方便,把很多日志信息通过console打印出来。每次进行一个操作,输出的日志非常多,导致程序看起来非常慢。难道向控制台打印信息就这么慢吗?我突然想到以前用linux时好像没有这么慢,于是就做了一个简单的测试。测试程序非常简单,就是用System.out.println()向控制台写一个字符串,写十万次。在我的windows xp和ubuntu 8.04下分别测试了10次,结果发现,在linux下平均用时9.8秒,而windows下要用18.6秒,差不多是linux的两倍。两边用的都是sun的1.6版的虚拟机,没想到会有这么大的差异。

是不是java在linux上就比在windows上要快呢?我想找一些更全面,更权威的测试,但是没有找到。sun的官方论坛上,有人说在两个系统上的表现是差不多的,不知道他是从哪里得到的结论。通过这个简单的测试,至少可以看出,在x86平台上,同是sun 1.6的虚拟机,写控制台的时候,在windows xp上,比在ubunut 8.04上要慢一倍

  • Share/Bookmark