性能分析与调优


1.3 性能分析与调优 1.3.1 性能分析及调优原理 性能测试的目的是为了发现性能瓶颈并解决。性能分析是为了确定导致性能瓶颈的原因, 而调优就是用来解决性能瓶颈。通过某些手段来让系统的性能得到提升是性能调优的主要目 的。 性能分析主要有以下两种方法:  指标达成法 将测试结果与用户需求进行比较,如果达到用户需要则测试通过。 1.系统满足 10 万注册用户(其中活跃用户数为 1 万)访问; 2.系统处理能力:20 个注册/秒、45 个并发浏览/秒、30 个登录操作/秒; 3.服务器资源利用率在满负荷的情况下,忙时峰值 CPU 负载不超过 75%,内存占用不 超过 80%。 例如:需要对一个参加 100 米跑的选手在比赛前进行性能测试,确保其能获得冠军,那 么首先需要明确第一名所需要达到的性能目标(100 米短跑总时间),对其进行性能测试, 当发现测试结果能够达到冠军所具备的条件后,性能测试即可结束。  最优化分析法 通过分析并消除系统性能瓶颈,使系统的处理能力最大化,系统资源实现充分利用。 例如:需要对一个参加 100 米跑的选手进行技术指导,并不在乎他是否能够拿到冠军, 而是重点强调能否提升自己的比赛成绩,那么就需要进行系统的训练和指导,如规范起跑动 作、强化肌肉及协调性等,最终实现运动成绩的提高。 对应的性能调优方法也分为两大方向,如图 1.6 所示。 性能调优 应用程序诊断 (发现问题) 系统调优 (运行得更好) 定位应用瓶颈 独立瓶颈 软件硬件 迭代调优 图 1.6 性能调优方向 1.应用程序诊断 应用程序的诊断是性能测试的最初目的。通过模拟多用户操作形成负载,检验应用程 序是否能够满足用户性能需求。如果不能满足,则定位应用瓶颈,并寻找解决该瓶颈的方 案,确保系统在修正后能够满足用户需求。对于一个项目来说,一般都以应用诊断 为 主。 2.系统调优 性能测试的目的不是为了满足用户,而是超越自己,这个时候需要做的是让系统能够比 以前更加优秀地运行,通过生成负载,对测试结果进行分析,并且准备大量的软硬件环境进 行迭代测试,找出影响性能的要素,最终提升系统的性能。一般产品都会采用系统调优的方 式来逐步完善系统性能。 常见的性能瓶颈有如下一些情况: 1.硬件上的性能瓶颈 一般指的是 CPU、RAM 方面的问题,分为服务器硬件瓶颈、网络瓶颈(对局域网可以 不考虑)、服务器操作系统瓶颈(参数配置)、中间件瓶颈(参数配置、数据库、Web 服 务器等)、应用瓶颈(SQL 语句、数据库设计、业务逻辑、算法等)。 例如:确定了在数据库服务器上需要 6 个 CPU、12GB 内存。但是在测试时,发现 CPU 的持续利用率超过 95%,这时可以认为在硬件上出现了性能瓶颈。 2.应用软件上的性能瓶颈 一般指的是应用服务器、Web 服务器等应用软件,还包括数据库系统。 例如:在 WebLogic 平台上配置了 JDBC 连接池的参数,最大连接数为 50,最小连接数 为 5,增加量为 10。在测试时发现,当负载增加时,现有的连接数不足,系统会动态生成 10 个新的连接,导致交易处理的响应时间大大增加。这时可以认为在应用软件上出现了性 能瓶颈。 3.应用程序上的性能瓶颈 一般指的是开发人员新开发出来的应用程序。 例如:某程序员开发了一个缴费处理程序。在测试时发现,这个缴费处理程序在处理用 户的并发缴费请求时,只能串行处理,无法并行处理,导致缴费交易的处理响应时间非常长, 这时可以认为在应用程序上出现了性能瓶颈。 4.操作系统上的性能瓶颈 一般指的是 Windows、UNIX、Linux 等操作系统。 例如:在 Windows 操作系统中,对某软件进行性能测试,出现物理内存不足时,如果 虚拟内存设置也不合理,虚拟内存的交换效率就会大大降低,从而导致行为的响应时间大大 增加。这时可以认为在操作系统上出现了性能瓶颈。 5.网络设备上的性能瓶颈 一般指的是防火墙、动态负载均衡器、交换机等设备。 例如:在动态负载均衡器上设置了动态分发负载的机制,当发现某个应用服务器上的硬 件资源已经到达极限时,动态负载均衡器将后续的交易请求发送到其他负载较轻的应用服务 器上。在测试时发现,动态负载均衡机制没有起到相应的作用,这时可以认为在网络设备上 出现了性能瓶颈。 性能瓶颈出现的原因及其定位是十分复杂的,这里只是简单介绍一下常见的几种瓶颈类 型和特征,而性能测试所需要做的就是根据各种情况因素综合考虑,然后协助开发人员一起 定位性能瓶颈。 一般性能问题调优的步骤 确定问题  应用程序代码:在通常情况下,很多程序的性能问题都是写出来的,因此对于发现 瓶颈的模块,应该首先检查一下代码。  数据库配置:数据库配置经常引起整个系统运行缓慢,一些诸如 Oracle 的大型数 据库都是需要 DBA 进行正确的参数调整才能投产的。  操作系统配置:操作系统配置不合理也可能引起系统瓶颈。  硬件设置:硬盘速度、内存大小等都是容易引起瓶颈的原因,因此这些都是分析的重 点。  网络:网络负载过重导致网络冲突和网络延迟。 确定原因 当确定了问题之后,我们要明确这个问题影响的是响应时间吞吐量,还是其他问题?是 多数用户还是少数用户遇到了问题?如果是少数用户,这几个用户与其他用户的操作有什么 不同?系统资源监控的结果是否正常?CPU 的使用是否到达极限?I/O 情况如何?问题是否 集中在某一类模块中?是客户端还是服务器出现问题?系统硬件配置是否够用?实际负载 是否超过了系统的负载能力?是否未对系统进行优化? 通过这些分析以及一些与系统相关的问题,可以对系统瓶颈有更深入的了解,进而分析 出真正的原因。 确定调整目标和解决方案 提高系统吞吐量;缩短响应时间;更好地支持并发。 测试解决方案 对通过解决方案调优后的系统进行基准测试。 分析调优结果 系统调优是否达到或者超出了预定目标?系统是整体性能得到了改善,还是以牺牲某部 分性能来解决其他问题。调优是否可以结束了? 最后,如果达到了预期目标,调优工作就基本可以结束了。 例如在数据库中经常我们会出现查询响应时间较长的问题,解决这种 SQL 查询响应时 间长得方式通常会使用索引来解决。 什么是索引呢? 打个比方,你有很多的小抽屉,每个抽屉里面放一些杂物,假如你要找东西,最原始的 方法就是一个个抽屉翻,这就是没有索引的情况。 假如聪明一点,给抽屉编号(唯一键),把哪个号码的抽屉有什么东西记录在纸上,找东 西先看看这张纸,这就是普通索引,假如你要知道哪个抽屉有什么,你可以在纸上迅速找到 抽屉号码(大家知道这是使用查找树),然后得到相关的信息,这种情况普通索引是很快的; 但是要找到一个特定的东西哪些抽屉有,你就要把整张纸遍历一次,这就是 LIKE 查询,假 如你要找哪些抽屉同时有 2 种甚至更多种物品,LIKE 就更加繁琐了。假如一个表有上千万 的纪录,大家可以想象查询的代价。 在索引中又分为聚集索引和非聚集索引两种索引模式。 聚集索引 表中存储的数据按照索引的顺序存储,检索效率比普通索引高,索引占用硬盘 存储空间小(1%左右),但对数据新增/修改/删除的速度影响比较大(降低)。 特点: (1) 无索引,数据无序 (2) 有索引,数据与索引同序 (3) 数据会根据索引键的顺序重新排列数据 (4) 一个表只能有一个索引 (5) 叶节点的指针指向的数据也在同一位置存储 TSQL 语法:create CLUSTERED INDEX idxempID ON emp(empID) 非聚集索引 不影响表中的数据存储顺序,检索效率比聚集索引低,索引 占用硬盘存储 空间大(30%~40%),对数据新增/修改/删除的影响很少。 特点: (1) 一个表可以最多可以创建 249 个非聚集索引 (2) 先建聚集索引才能创建非聚集索引 (3) 非聚集索引数据与索引不同序 (4) 数据与非聚集索引在不同位置 (5) 非聚集索引在叶节点上存储,在叶节点上有一个“指针”直接指 向要查询的数据区域 (6) 数据不会根据非聚集索引键的顺序重新排列数据 TSQL 语法:create NONCLUSTERED INDEX idximpID ON emp(empID) 错误观点: 1、主键就是聚集索引 2、只要建立索引就能显著提高查询速度 3、把所有需要提高查询速度的字段都加进聚集索引,以提高查询速度 一般来说以下规则是正确的: 用聚合索引比用不是聚合索引的主键速度快 用聚合索引比用一般的主键作 order by 时速度快,特别是在小数据量情况下 使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少,而无 论聚合索引使用了多少个: “水可载舟,亦可覆舟”,索引也一样,不要过度使用索引 对于 SQL 语句优化的基本原则: 1、使用索引来更快地遍历表。 缺省情况下建立的索引是非群集索引,但有时它并不是最佳的。在非群集索引下,数据 在物理上随机存放在数据页上。合理的索引设计要建立在对各种查询的分析和预测上。一般 来说: ①.有大量重复值、且经常有范围查询(between, >,< ,>=,< =)和 order by、group by 发生的列,可考虑建立群集索引; ②.经常同时存取多列,且每列都含有重复值可考虑建立组合索引; ③.组合索引要尽量使关键查询形成索引覆盖,其前导列一定是使用最频繁的列。 2、IS NULL 与 IS NOT NULL 不能用 null 作索引,任何包含 null 值的列都将不会被包含在索引中。即使索引有多列 这样的情况下,只要这些列中有一列含有 null,该列就会从索引中排除。也就是说如果某列 存在空值,即使对该列建索引也不会提高性能。任何在 where 子句中使用 is null 或 is not null 的语句优化器是不允许使用索引的。 3、IN 和 EXISTS EXISTS 要远比 IN 的效率高。里面关系到 full table scan 和 range scan。几乎将所有的 IN 操作符子查询改写为使用 EXISTS 的子查询。 4、在海量查询时尽量少用格式转换。 5、当 在 SQL SERVER 2000 中,如果存储过程只有一个参数,并且是 OUTPUT 类型的, 必须在调用这个存储过程的时候给这个参数一个初始的值,否则会出现调用错误。 6、ORDER BY 和 GROPU BY 使用 ORDER BY 和 GROUP BY 短语,任何一种索引都有助于 SELECT 的性能提高。 注意如果索引列里面有 NULL 值,Optimizer 将无法优化。 7、任何对列的操作都将导致表扫描,它包括数据库函数、计算表达式等等,查询时要 尽可能将操作移至等号右边。 8、IN、OR 子句常会使用工作表,使索引失效。如果不产生大量重复值,可以考虑把 子句拆开。拆开的子句中应该包含索引。 9、SET SHOWPLAN_ALL ON 查看执行方案。DBCC 检查数据库数据完整性。 DBCC(DataBase Consistency Checker)是一组用于验证 SQL Server 数据库完整性的程序。 10、谨慎使用游标 在某些必须使用游标的场合,可考虑将符合条件的数据行转入临时表中,再对临时表定 义游标进行操作,这样可使性能得到明显提高。 注释:所谓的优化就是 WHERE 子句利用了索引,不可优化即发生了表扫描或额外开 销。经验显示,SQL Server 性能的最大改进得益于逻辑的数据库设计、索引设计和查询设计 方面。反过来说,最大的性能问题常常是由其中这些相同方面中的不足引起的。其实 SQL 优化的实质就是在结果正确的前提下,用优化器可以识别的语句,充份利用索引,减少表扫 描的 I/O 次数,尽量避免表搜索的发生。 其实 SQL 的性能优化是一个复杂的过程,上述这些只是在应用层次的一种体现,深入 研究还会涉及数据库层的资源配置、网络层的流量控制以及操作系统层的总体设计。 对于某一条查询语句我们可以使用查询计划获得查询性能例如: (1)仅在主键上建立聚集索引,并且不划分时间段: Select gid,fariqi,neibuyonghu,title from tgongwen 用时:128470 毫秒(即:128 秒) (2)在主键上建立聚集索引,在 fariq 上建立非聚集索引: select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate()) 用时:53763 毫秒(54 秒) (3)将聚合索引建立在日期列(fariqi)上: select gid,fariqi,neibuyonghu,title from Tgongwen where fariqi> dateadd(day,-90,getdate()) 用时:2423 毫秒(2 秒) 1、用聚合索引比用不是聚合索引的主键速度快。下面是实例语句:(都是提取 25 万条 数据) select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' 使用时间:3326 毫秒 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where gid<=250000 使用时间:4470 毫秒 这里,用聚合索引比用不是聚合索引的主键速度快了近 1/4。 2、用聚合索引比用一般的主键作 order by 时速度快,特别是在小数据量情况下 select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by fariqi 使用时间:12936 毫秒 select gid,fariqi,neibuyonghu,reader,title from Tgongwen order by gid 使用时间:18843 毫秒 这里,用聚合索引比用一般的主键作 order by 时,速度快了 3/10。 事实上,如果数据量很小的话,用聚集索引作为排序列要比使用非聚集索引速度快得明 显的多; 而数据量如果很大的话,如 10 万以上,则二者的速度差别不明显。 3、使用聚合索引内的时间段,搜索时间会按数据占整个数据表的百分比成比例减少, 而无论聚合索引使用了多少个: select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1'' 用时:6343 毫秒(提取 100 万条) select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-6-6'' 用时:3170 毫秒(提取 50 万条) select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi=''2004-9-16'' 用时:3326 毫秒(和上句的结果一模一样。如果采集的数量一样,那么用大于号和等 于号是一样的) select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1'' and fariqi<''2004-6-6'' 用时:3280 毫秒 4、日期列不会因为有分秒的输入而减慢查询速度 下面的例子中,共有 100 万条数据,2004 年 1 月 1 日以后的数据有 50 万条,但只有两 个不同的日期,日期精确到日;之前有数据 50 万 条 ,有 5000 个不同的日期,日期精确到秒。 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi>''2004-1-1'' order by fariqi 用时:6390 毫秒 select gid,fariqi,neibuyonghu,reader,title from Tgongwen where fariqi<''2004-1-1'' order by fariqi 用时:6453 毫秒 性能问题分析原则 原则 1:把事实与推测分开,总是用实际的证据来证明你的推测。 原则 2:在没有足够证据之前,不对程序进行优化。 原则 3:优先验证简单的假设。 原则 4:日志文件中没有错误并不代表真的没有错误。 原则 5:从系统到应用、从外到内进行层层剥离,缩小范围。确认是系统级问题还是 应用级问题;确认是否为外部系统问题(如密码鉴权问题、EJB 问题等);确认是应用程序 问题还是数据库问题。 原则 6:范围缩小后,再分割成多个小单元,对每个小单元反复进行压力测试,来确 定是哪个单元引起性能问题。 诊断性能问题,最常见的也是较难的判断的问题是:是应用程序还是数据库出了问题? 或者两者都有? 这是因为应用程序、数据库、WebLogic Server(Tomcat)都不是孤立运转的。因此脱 离应用架构单独运行测试(如 SQL 计时、JDBC 计时、线程计时等)几乎没有作用。关键 是对相互作用的了解。要熟知系统的性能度量方法,了解 SQL 的结构,了解用户发出的请 求在跨越整个系统时的端对端/点对点计时、SQL 的计时等;了解用户发出请求后所关联的 线程、JDBC 连接、数据库的活动及其之间的交互关系。 应用数据库典型的三大类性能问题分析如下。 1.过量的数据库调用 问题: 常见的性能瓶颈来自过量的数据库调用,引发这些问题不一定是 SQL 查询的 Execute() 或 Update(),而是应用程序与数据库的交互有关,例如 ResultSet 操作,常见的问题是指定 了过于精细的查询条件,然后使用 ResultSet.Next()详细搜寻返回的数据。 解决办法: 从数据库中大量取得所要求的数据,避免应用程序反复回调数据库。 2.数据库连接池问题 问题 1:连接池资源泄漏 虽然可以通过 WebLogic 自带工具、Jprofiler 工具或自编工具检测到数据库连接池资源 泄漏,但是很难在应用程序代码本身准确定位泄漏的源头! 解决办法: 仔细分析程序代码,是否没有 close()连接?是否遗漏了 finally 块?或者尽管有 close() 但并没有成功? 问题 2:连接池大小 连接池过小会导致连接池满后,新的客户无法连接上系统,在日志中出现错误信息。一 般的解决方法是增大连接池。但另一方面,连接池过大会造成资源无效损耗,可能会出现新 的性能问题,那么连接池调到多大比较合适呢? 解决办法: 经验法则 1:数据库连接池数=线程池数×每个线程需要连接数据库的平均数×1.1 (1.1 的含义是增加 10%的峰值期负载),通常每个线程需要连接数据库的平均数是 1,即当线程 池数为 120 时,数据库连接池数就是 132。 经验法则 2:设置最初池大小=最大池大小。 3.SQL 语句及其索引或锁定属性问题 问题:SQL 语句及其索引或锁定属性不合理可能引发 DISKIO 过忙(磁盘读写数据)或 者 CPU 过忙(在内存中索引排序),造成执行时间过长,阻塞线程的执行,最终引发系统 挂起或者执行超时引发系统挂起,例如错误信息: oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:2857) at oracle.jdbc.driver.OraclePreparedStatement.executeUpdate 死锁引发系统挂起,例如错误信息: java.sql.SQLException: ORA-00060: deadlock detected while waiting for resource at oracle.jdbc.dbaccess.DBError.throwSqlException(DBError.java:170) 解决办法: 优化 SQL 语句及其索引或锁定属性。 性能调优应该注意的要点 要点 1:在应用系统的设计开发过程中,应始终把性能放在考虑的范围内。 要点 2:确定清晰明确的性能目标是关键。 要点 3:必须保证调优后的程序运行正确。 要点 4:系统的性能更大程度上取决于良好的设计,调优技巧只是一个辅助手段。 要点 5: 调优过程是迭代渐进的过程,每次调优的结果都要反馈到后续的代码开发中去。 要点 6:性能调优不能以牺牲代码的可读性和可维护性为代价。 性能调优是一个很复杂的过程,就好比一个人每天在上班路上需要消耗 1 个半小时,如 何调优让这个人上班路上开销的时间变小。性能调优需要有全面的知识和背景,需要对被调 优对象有全面的了解和跟踪,才能逐步抽丝剥茧找到某块短板,将这块短板加长后,再找到 下一块短板,以此类推。 很多公司在招聘性能测试工程师的时候都会提及性能调优这个职责,但是只靠一个性能 测试专家是很难的,因为如果你想要对一个三层架构的网络应用进行调优,那么需要对网络 架构、WWW 服务、APP 应用、DB 数据库都相当精通,才能完成所谓的调优工作,而这样 的人已经可以胜任架构设计师的职位了,如果让他去做性能测试工程师是否有些大材小用了 呢? 不过作为一个性能测试工程师,在成长的初期需要对性能测试调优的各个对象都有所了 解,通过相关部门的人员协助完成调优工作,随后就是逐步加深,并且选择一个具体的方向 进行深化并成为某一方面的性能测试及调优专家。 1.3.2 常见系统性能瓶颈 1.硬件瓶颈 任何系统的性能问题最终都会体现在硬件上,影响系统性能的主要硬件部件通常都是 CPU、内存、硬盘,而其中的性能瓶颈往往是在硬盘上。作为计算机硬件中发展最慢的设备, 很多常见瓶颈都是由于硬盘的读写速度慢导致的。提高硬盘读写性能的方法无非是提高转速、 提高单碟容量、增加缓存和更新接口,传统的温氏硬盘已经基本没有太大的调优空间,因为 从稳定性的角度 15000 RPM(RPM 是 Revolutions Per Minute 的缩写,是转/每分钟。RPM 值越大,内部传输率就越快,访问时间就越短,硬盘的整体性能也就越好)已经几乎是极限 了,而提高单碟容量也存在一定的技术瓶颈,1TB 单碟的容量想要突破还需要比较长的时间。 对于现在的主流配置硬件来说,每秒钟十几 GB 的数据读取写入速度(内存)不在话下, 而传统的温氏硬盘到现在也只能做到平均 120MB/s 的读取速度,而这个速度还是针对大文 件读写的,而对于服务器(特别是 WWW 服务器)大量 4KB 小文件读写速度,会惊人的下 跌至 1MB 不到,而对应的 IOPS(每秒磁盘读写次数)会低的可怜,大量的数据都在排队从 硬盘上读取到内存中,再利用内存的超大带宽完成操作,这也是为什么内存大系统会运行的 比较快。而一旦内存耗尽,数据不得不从硬盘上读取,这时系统的响应时间会大幅下降。在 现在的很多系统中都会使用 Memory cache 技术来解决小文件读写的问题,但是这种技术存 在一个比较致命的缺点就是一旦内存掉电,那么就意味着数据丢失。而除了 Memory cache 技术以外,固态硬盘给了我们更多的选择,对于传统硬盘的读写速度瓶颈及 IOPS,固态硬 盘提供了全面的提升。 何为 IOPS? IOPS (Input/Output Per Second)即每秒的输入输出量(或读写次数),是衡量磁盘性能的主 要指标之一。IOPS 是指单位时间内系统能处理的 I/O 请求数量,一般以每秒处理的 I/O 请 求数量为单位,I/O 请求通常为读或写数据操作请求。随机读写频繁的应用,如 OLTP(Online Transaction Processing),IOPS 是关键衡量指标。另一个重要指标是数据吞吐量(Throughput), 指单位时间内可以成功传输的数据数量。对于大量顺序读写的应用,如 VOD(Video On Demand),则更关注吞吐量指标。 传统温氏磁盘本质上一种机械装置,如 FC, SAS, SATA 磁盘,转速通常为 5400/7200/10K/15K rpm 不等。影响磁盘的关键因素是磁盘服务时间,即磁盘完成一个 I/O 请求所花费的时间,它由寻道时间、旋转延迟和数据传输时间三部分构成。 寻道时间 Tseek 是指将读写磁头移动至正确的磁道上所需要的时间。寻道时间越短,I/O 操 作越快,目前磁盘的平均寻道时间一般在 3-15ms。 旋转延迟 Trotation 是指盘片旋转将请求数据所在扇区移至读写磁头下方所需要的时间。旋 转延迟取决于磁盘转速,通常使用磁盘旋转一周所需时间的 1/2 表示。比如,7200 rpm 的磁 盘平均旋转延迟大约为 60*1000/7200/2 = 4.17ms,而转速为 15000 rpm 的磁盘其平均旋转延 迟约为 2ms。 数据传输时间 Ttransfer 是指完成传输所请求的数据所需要的时间,它取决于数据传输率, 其值等于数据大小除以数据传输率。目前 IDE/ATA 能达到 133MB/s,SATA II 可达到 300MB/s 的接口数据传输率,数据传输时间通常远小于前两部分时间。 因此,理论上可以计算出磁盘的最大 IOPS,即 IOPS = 1000 ms/ (Tseek + Troatation),忽略 数据传输时间。假设磁盘平均物理寻道时间为 3ms, 磁盘转速为 7200,10K,15K rpm,则磁盘 IOPS 理论最大值分别为, IOPS = 1000 / (3 + 60000/7200/2) = 140 IOPS = 1000 / (3 + 60000/10000/2) = 167 IOPS = 1000 / (3 + 60000/15000/2) = 200 固态硬盘 SSD 是一种电子装置, 避免了传统磁盘在寻道和旋转上的时间花费,存储单 元寻址开销大大降低,因此 IOPS 可以非常高,能够达到数万甚至数十万。实际测量中,IOPS 数值会受到很多因素的影响,包括 I/O 负载特征(读写比例,顺序和随机,工作线程数,队 列深度,数据记录大小)、系统配置、操作系统、磁盘驱动等等。因此对比测量磁盘 IOPS 时,必须在同样的测试基准下进行,即便如何也会产生一定的随机不确定性。通常情况下, IOPS 可细分为如下几个指标: Toatal IOPS,混合读写和顺序随机 I/O 负载情况下的磁盘 IOPS,这个与实际 I/O 情况最为 相符,大多数应用关注此指标。 Random Read IOPS,100%随机读负载情况下的 IOPS。 Random Write IOPS,100%随机写负载情况下的 IOPS。 Sequential Read IOPS,100%顺序负载读情况下的 IOPS。 Sequential Write IOPS,100%顺序写负载情况下的 IOPS。 IOPS 的测试 benchmark 工具主要有 Iometer, IoZone, FIO 等,可以综合用于测试磁盘在不 同情形下的 IOPS。对于应用系统,需要首先确定数据的负载特征,然后选择合理的 IOPS 指标进行测量和对比分析,据此选择合适的存储介质和软件系统。 下面的磁盘 IOPS 数据来自 http://en.wikipedia.org/wiki/IOPS,给大家一个基本参考,见 表 1。 表 1 常见磁盘 IOPS 指标 Device T ype IOPS Interface Notes Simple SLC SS D SD ~400 IOPS[citation needed] SATA 3 Gb/s Intel X25-M G2(MLC) S SD ~8,600 IOPS[11] SATA 3 Gb/s Intel's data sheet[12] claims 6,600/8,600 IOPS (80 GB/160 GB version) and 35,000 IOPS for random 4 KB writes and reads, respectively. Intel X25-E (SLC) S SD ~5,000 IOPS[13] SATA 3 Gb/s Intel's data sheet[14] claims 3,300 IOPS and 35,000 IOPS for writes and reads, respectively. 5,000 IOPS are measured for a mix. Intel X25-E G1 has around 3 times higher IOPS compared to the Intel X25-M G2.[15] G.Skill Phoeni x Pro S SD ~20,000 IOPS[citation needed] SATA 3 Gb/s SandForce-1 200 based SSD drives with enhanced firmware, states up to 50,000 IOPS, but benchmarking shows for this particular drive ~25,000 IOPS for random read and ~15,000 IOPS for random write.[16] OCZ Vertex 3 S SD Up to 60,000 IOPS [17] SATA 6 Gb/s Random Write 4 KB (Aligned) Texas Memory Systems RamSan-20 S SD 120,000+ Random Read/Write IOPS[18] PCIe Includes RAM cache and UltraCapacitor Fusion-io ioDr ive S SD 140,000 Read IOPS, 135,000 Write IOPS [19] PCIe Virident SystemstachIOn S SD 320,000 sustained READ IOPS using 4KB blocks and 200,000 sustained WRITE IOPS using 4KB blocks [20] PCIe NAND SLC Flash up to 800G capacity [21] OCZ RevoDrive 3 X2 S SD 200,000 Random Write 4K IOPS [22] PCIe Fusion-io ioDrive Duo S SD 250,000+ IOPS [23] PCIe Violin MemoryViolin 3200 S SD 250,000+ Random Read/Write IOPS[24] PCIe /FC/Infiniband/iSCSI Flash Memory Array WhipTail, XLR8r 6TB S SD 250,000+ Write/Read IOPS[25] FC, iscsi, Infiniband, NAS Flash Based Storage Array DDRdrive X1, S SD 300,000+ (512B Random Read IOPS) and 200,000+ (512B Random Write IOPS)[26][27][28][29] PCIe Texas Memory Systems RamSan-720 Appliance S SD 400,000 4KB Random Read/Write IOPS[30] FC / InfiniBand 5,000 MB/s, High-Availability, No Single Point of Failure OCZ Single SuperScale Z-Drive R4 PCI-Express SSD S SD Up to 500,000 IOPS [31] PCIe 3,800MB/s Texas Memory Systems RamSan-630 Appliance S SD 1,000,000+ 4KB Random Read/Write IOPS[32] FC / InfiniBand 10,000 MB/s Fusion-io ioDrive Octal (single PCI Express card) S SD 1,180,000+ Random Read/Write IOPS[33] PCIe OCZ 2x SuperScale Z-Drive R4 PCI-Express SSD S SD Up to 1,200,000 IOPS[31] PCIe 5,600MB/s Texas Memory Systems RamSan-70 S SD 1,200,000 Random Read/Write IOPS[34] PCIe Includes RAM cache and UltraCapacitor to enable backup to flash memory at power loss, 2,500 MB/s 在这里我们可以看到虽然固态硬盘已经大幅提升 IOPS 了,但是高端策略还是要使 用 Memory Cache 从本质上解决。而且固态硬盘还有数据损坏无法恢复以及长时间使用 会存在碎片导致读写速度大幅下降的问题。 那么为什么固态硬盘没法做到内存的速度呢? 这是因为 ROM 固态硬盘和 RAM 内存的实现原理不同导致的。内存的发展速度已 经到达了第五代 DDR 内存(一般使用在显卡上),而我们通常主板上使用的都是 DDR3 内存。内存的主要性能指标是在读写带宽上,而影响带宽上的指标主要是内存通道数 及内存频率。 现在常见的内存一般型号为 DDR3 1333Mhz(工作在 1333Mhz 的频率下),我们可 以通过更换内存为更高频率及更低时序的方式来提升内存带宽。 何为时序呢? 内存时序是描述内存条性能的一种参数,一般存储在内存条的SPD 中,由“ A-B-C-D” 这样的结构组成。一般“A-B-C-D”分别对应的参数是“CL-tRCD-tRP-tRAS”,它们的含义 依次为:CAS Latency(简称 CL 值)内存 CAS 延迟时间,它是内存的重要参数之一, 某些牌子的内存会把 CL 值印在内存条的标签上; RAS-to-CAS Delay(tRCD), 内 存 行地址传输到列地址的延迟时间; RAS Precharge Delay(tRP),内存行地址选通脉冲预 充电时间; Row Active Delay(tRAS),内存行地址选通延迟。这是玩家最关注的 4 项时 序调节,在大部分主板的 BIOS 中可以设定,内存模组厂商也有计划的推出了低于 JEDEC 认证标准的低延迟型超频内存模组,在同样频率设定下,最低“2-2-2-5”这种序 列时序的内存模组确实能够带来比“3-4-4-8”更高的内存性能,幅度在 3 至 5 个百分点。 内存频率就比较好理解了,我们现在发烧级别的内存频率可以做到 2400Mhz,相 对于 1333 的默认频率几乎有了一倍的提升,而这种频率的提升可以换来带宽从 16GB 到 24GB 的提升。如果再能降低时序,那么结果会进一步提升,但是由于高频率内存一 般都是超频获得,本来就不太稳定,所以在这种情况下通常都对时序做了调慢处理, 从而确保稳定性。 通过调整内存时序和频率我们可以大幅提升内存的处理能力,而另外一种提升策 略就是通道,简单来说就是让多跟内存并行和内存控制器进行交互,从而成倍的提升 吞吐能力。从过去的单通道内存,到现在常见的双通道内存,再到 X58 主板提供的三 通道内存,以及最新 X79 主板提供的四通道内存。我们在不断的调优内存的吞吐能力, 但是实际情况并不是和我们理论上的情况一样。也就是说并不是四通道内存的吞吐量 就是单通道内存的四倍,这是由于处理器和内存控制器已经无法有效的使用那么强大 的带宽了(再未来出现更强的处理器和内存控制器时,四通道内存的优势才能真正发 挥)。在现在的测试结果来说,双通道内存明显优于单通道,三通道内存和四通道内存 接近双通道内存。 最终通过高频率的内存以及多通道内存我们即可解决内存读写的带宽问题,进一步 配合超大的内存容量,我们即可实现大量操作的内存化,这样处理速度就可以得到非常大的 提高。所以在很多设备上都会拥有内存,而其中 CPU 上的集成内存是速度最快的,从而确 保 CPU 可以无需等待的从一级缓存中读写数据。 在谈完硬盘和内存后我们来说一下 CPU 的常见性能指标。通常说到 CPU 我们第 一反应就是 CPU 工作频率,就是 CPU 的时钟频率,简单说是 CPU 运算时的工作的频 率(1 秒内发生的同步脉冲数)的简称。单位是 Hz。它决定计算机的运行速度,随着 计算机的发展,主频由过去 MHZ 发展到了现在的 GHZ (1GHZ=1000MHZ=1000000KHZ=1000000000HZ)。通常来讲,在同系列微处理器,主 频越高就代表计算机的速度也越快,但对于不同类型的处理器,它就只能作为一个参 数来作参考。另外 CPU 的运算速度还要看 CPU 的流水线的各方面的性能指标。由于 主频并不直接代表运算速度,所以在一定情况下,很可能会出现主频较高的 CPU 实际 运算速度较低的现象。因此主频仅仅是 CPU 性能表现的一个方面,而不代表 CPU 的 整体性能。 说到处理器主频,就要提到与之密切相关的两个概念:倍频与外频,外频是 CPU 的基准频率,单位也是 MHz。外频是 CPU 与主板之间同步运行的速度,而且目前的绝 大部分电脑系统中外频也是内存与主板之间的同步运行的速度,在这种方式下,可以 理解为 CPU 的外频直接与内存相连通,实现两者间的同步运行状态;倍频即主频与外 频之比的倍数。主频、外频、倍频,其关系式:主频=外频×倍频。早期的 CPU 并没有 “倍频”这个概念,那时主频和系统总线的速度是一样的。随着技术的发展,CPU 速度 越来越快,内存、硬盘等配件逐渐跟不上 CPU 的速度了,而倍频的出现解决了这个问 题,它可使内存等部件仍然工作在相对较低的系统总线频率下,而 CPU 的主频可以通 过倍频来无限提升(理论上)。我们可以把外频看作是机器内的一条生产线,而倍频则 是生产线的条数,一台机器生产速度的快慢(主频)自然就是生产线的速度(外频) 乘以生产线的条数(倍频)了。 所以经常我们可以通过提高外频降低倍频的方式来提升周边设备的处理能力,而 并不提高 CPU 最终的工作频率,最终调优系统。但是光光依赖 CPU 的工作频率并不 能解决我们的实际问题,所以各个厂商都推出了自己的特定指令集(例如 MMX,SSE4, EM64T,X86,RISC),通过对常见操作的底层支持大幅提升运算能力。我们现在使用 的 CPU 基本上都是基于 X86 兼容指令集的,也可以这样简单认为我们使用的 CPU 都 还不是 64 位指令集的,虽然可以在上面运行 X64 的系统,但是这里需要存在一个内部 指令集转换,所以我们常用 CPU 并不能完全发挥 64 位指令集的优势,但是通过兼容 的方式我们提供了更多的内存寻址能力。 当我们提高了频率,优化了指令集后我们发现仍然无法解决 CPU 处理能力瓶颈的 问题,而且随着 CPU 工艺的复杂,我们已经很难再进一步提升频率了(工艺、散热及 电子迁移影响)。而大多数时候我们的问题还不是在 CPU 处理一件事情上慢,而是 CPU 拥有一个很大的任务队列,依次处理慢。所以现在我们会看到 CPU 在往多核化发展, 通过在一个 CPU 中集成多个核心,每个核心再支持超线程技术,让应用程序可以更好 的通过将一个任务分配到多个 CPU 上进行并行计算,从而解决性能问题。 除了上面主要的硬盘、内存和 CPU 以外,接口的类型也可能成为系统的瓶颈。为 了确保设备之间的读取速度,我们在不断的更新接口类型。最早我们使用的 USB1.0 设 备是属于低速设备,当我们通过这种接口的 U 盘来传输文件结果可想而知,而最新的 USB3.0 技术提供了 5Gbps 全双工(USB2.0 则为 480Mpbs 半双工)带宽,几乎可以和 SATA6 的 6Gbps 相媲美,这个时候我们会发现瓶颈重新回到了 U 盘自身。而对于高端 的固态硬盘普通的 SATA6 都无法满足其强大的处理能力,往往会选择 PCI-E 这种高速 接口来进行连接。 对于网络应用来说网络接口也比较容易出现瓶颈。我们常见的网络都是 100Mpbs 网络折合实际网络情况理论值大约为 12MB/s,当我们在局域网上传输文件时,通常的 瓶颈就是在网卡上(硬盘传输速度都在 100MB/s 以上)。如果我们升级到 1000Mpbs 的 网络时,网络理论传输速度可以达到 120MB/s 了,这个时候瓶颈会出现在发送数据的 硬盘或者接收数据的硬盘上了。我们普通使用的双绞线一般为五类线,其提供了 100MHZ 的传输频率,到了千兆网络这种五类线已经不能满足所以我们一般会升级选 择超五类双绞线,虽然超五类非屏蔽双绞线也能提供高达 1000Mb/s 的传输带宽,但实 际使用情况是无法达到的,由于我们使用的双绞线在屏蔽和加工工艺上的缺陷,导致 超五类非屏蔽双绞线并不能发挥千兆网络的最大速度,一般只能达到 80%左右的使用 率,带宽峰值约为 700Mb/s。所以在高端应用中我们会放弃使用传统的双绞线技术,而 转投光纤技术,彻底解决传输材质带来的瓶颈。另一方面当我们使用万兆交换/路由的 时候,交换机/路由器是否能够处理如此大数量的多协议并进行路由转发会成为另外一 个瓶颈。 对于硬件上的常见性能指标我们可以通过 AIDA64、SiSoftware、PC Mark、 HDTunePro、Iometer,、IoZone、 FIO 等工具进行基准测试获得。 例如我们使用 AIDA64 获得 CPU 上各种缓存的性能指标,如图 1.7。 图 1.7 使用 AIDA 测试 Cache 和内存的性能指标 2.操作系统 操作系统作为和硬件的交互层,它的性能决定了在操作系统下运行的应用的性能。对于 操作的调优主要是在硬件支持和自身开销上体现的。 在 Windows Vista 中内存管理和文件系统方面引入了 SuperFetch 技术,可以把经常使用 的程序预存入到内存,提高性能,此外你的后台程序不会夺取较高的运行等级了,不用担心 突然一个后台程序运作其他让你动弹不得。所以在使用 Vista 及 Win7 的时候会发现内存暂 用率相对以前的操作系统上升,这是一种更加合理使用空闲内存的策略,通过这种策略可以 大幅提升我们访问常见应用的响应时间。除此以外一般新版本的操作系统都会对新硬件提供 更好的支持,从而最大化发挥硬件本身的性能,例如在 Win7 中支持固态硬盘的 Trim 命令, 并且会禁用 SuperFetch、ReadyBoost,以及启动和程序预取,这些功能都是针对传统硬盘设 计的。 对于新版本的 Windows Sever 系列操作系统,除了前面硬件支持以外也会提供对应组建 的更新,从而实现性能的优化,例如 IIS 的版本升级。 除了操作系统的更新以外选择合理的操作系统平台也会极大的影响系统性能,我们常见 的操作系统平台一般为 I386 和 X86-X64。I386 通常被用来作为对 Intel(英特尔)32 位微处 理器的统称。而 X86-64 可在同一时间内处理 64 位的整数运算,并兼容 X86-32 架构。通常 为了更好的支持大容量内存(32 位系统只能寻址 4GB 内存),我们都会选择 64 位系统, 但是由于我们使用的额 CPU 都是兼容模式,所以并不会非常明显的体现出 64 位系统在处理 能力上的提升。 所以从性能角度考虑在操作系统的选择上我们一般会尽可能选择最新版本,再选择 64 位系统完成对硬件的支持,但从功能、稳定性、可靠性角度考虑,作为服务器我们却不应该 选择太新没有稳定和广泛使用的操作系统。这也是 2012 年伦敦奥运会会选择 Windows Vista 操作系统作为官方主要操作系统,而不是选择更好的 Win7 操作系统的原因。 而 Linux 或 Unix 作为一个多用户多任务操作系统,强大、稳定的安全机制及高效客户 端,使得选择它作为服务器操作系统成为了更加主流的策略。而 Windows Server 系统为了 弥补自己华丽桌面的开销也提供了只有 Power Shell 端的简化服务器 Core 核心版本,减少桌 面的资源开销。 对于操作系统的性能测试并没有有效的方法,只能通过在系统上进行硬件、软件配置测 试来模拟对比。 3.服务/框架 我们的代码通常都是运行在服务或者框架下,例如 JAVA 语言就需要 JVM 环境作为底 层框架才能运行,而 C#需要.Net 框架。而正是因为框架原因为了兼容平台导致了运行效率 的底下,而 C 语言或者汇编语言由于自身可以直接和硬件交互,从而获得了超强的处理能 力。 但是随着 JAVA 语言的 JVM 版本提升性能已经有了极大的提高。据 IBM 的数据,在同 样的硬件上 2001 年时的 IBM JDK 版本的性能是 1996 年的 JDK 版本的十倍左右。而即使是 在同一时期,不同公司的 JDK 和 JRE 的性能也不一样,比如 SUN、IBM、BEA 等公司都有 自己开发的 JDK 和 JRE。而现在的 JVM 在采用了 Just-In-Time(JIT)编译器后,程序的运 行性能在很多 JVM 下可以和本地编译的程序一争短长,甚至在一些计算比较密集的数值计 算领域也是这样。目前,Java 已经使用更先进的 HotSpot 技术来代替 JIT 技术,Java 的性能 有了更进一步的提升。另外,在使用-server 选项运行 java 程序时,也可以对 java 进行更深 入的优化,比如在运行时将调用较多的方法内联(inline)到程序中来提高运行速度,这就 是所谓的“动态优化”,而本地编译器是无法做到这一点的;这也是一些 java 代码比对应用 C/C++等语言编写的本地代码运行的更快的原因之一。微软的.NET 平台也使用 JIT 编译器, 所以也有类似问题。 而在服务平台我们一般分为表示层、业务逻辑层和数据访问层,每一层服务上又会有不 同的性能区别。 表示层用于显示数据和接收用户输入的数据,为用户提供一种交互式操作的界面,通常 是指我们的 Web 服务器,而最常用的就是 Apache。Apache 是世界使用排名第一的 Web 服 务器软件。它可以运行在几乎所有广泛使用的计算机平台上,由于其跨平台和安全性被广泛 使用,是最流行的 Web 服务器端软件之一,但 是 Apache 也有自己的缺点,所以在行业中会 有针对性的 Lighttpd 和 Nginx 作为替代品出现。Lighttpd 是一个单线程的针对大量持续连接 做出专门优化的 Web 服务器(这正是多数高流量网站和应用程序需要的)而 Nginx 对静态 页面的支持相当出色。而 IIS 由于它只是为了支持微软的 ASP.Net 技术存在,并且包含表示 层和应用层所以相对来说没有多余的选择余地,只有等待微软自身版本更新来获得更好的性 能。 业务逻辑层的关注点主要集中在业务规则的制定、业务流程的实现等与业务需求有关的 系统设计,也即是说它是与系统所应对的领域(Domain)逻辑有关,很多时候,也将业务 逻辑层称为领域层。在业务逻辑层上我们会有比较多的服务选择,包括 PHP、Jboss、Tomcat、 WebLogic、Webshpere 等。PHP 包括两种运行模式 CGI 模式或者是 Apache 整合模式,其中 Apache 模式相对来说更为稳定,再通过 Zend 编译和运行优化可以进一步提升 25 倍的性能。 而对于 JAVA 的运行效率来说一般 WebShpere>weblogic>Jboss>Tomcat。 数据访问层其功能主要是负责数据库的访问,可以访问数据库系统、二进制文件、文本 文档或是 XML 文档。简单的说法就是实现对数据表的 Select,Insert,Update,Delete 的操 作。如果要加入 ORM 的元素,那么就会包括对象和数据表之间的 mapping,以及对象实体 的持久化。常见数据库服务的包括 Oracle、DB2、MS SQL Server、Mysql。从自身的性能角 度考虑 DB2>Oracle> MS SQL Server> Mysql ,但是这些数据库都是关系型数据库。这种数 据库无法满足超巨型数据处理的要求(例如微博关注),所以 NoSQL 非关系型数据库像满 足极高读写性能需求的 Kye-Value 数据库:Redis、Tokyo Cabinet、Flare ;满足海量存储需 求和访问的面向文档的数据库:MongoDB、CouchDB ;满足高可扩展性和可用性的面向分 布式计算的数据库:Cassandra、Voldemort 在各种 SNS 网站中大量应用。 我们可以通过对框架或者服务的配置进行调整来让系统运行的更快,也可以通过负载均 衡(Load Balancing)策略在现有网络结构之上,廉价有效透明的扩展网络设备和服务器的 带宽、增加吞吐量、加强网络数据处理能力、提高网络的灵活性和可用性。 对于框架或服务的性能测试我们可以通过编写某种负载的业务代码来测试获得。一般服 务或框架设计厂商都会提供一定的基准数据。 4.代码 到了代码级别基本上影响性能的只有算法结构了。在表示层上如何合理的使用 JS 及 CSS 可以改变用户渲染页面的开销,在代码中使用合理的语法规则和算法结构可以大幅提升 运算处理能力,而在数据库中我们可以优化 SQL 语句,创建存储过程,设置索引来提升数 据操作性能。 对于代码的性能测试我们一般可以通过静态或动态代码分析软件来实现,例如 DevPartner Studio、Red Gate、Jtest、Jprobe 等。 例如使用 DevPartner Studio 分析代码的执行开销,如图 1.8。 图 1.8 使用 DevPartner 分析定位脚本执行开销 1.3.3 性能测试的注意要点 1.性能测试应尽可能早地进行 和功能测试相同,性能测试进行得越早越容易发现,并修复问题,当系统集成后,想要 从众多模块中分析定位模块瓶颈是十分困难的,但是如果在项目初期就能对每个模块进行性 能测试,问题自然会迎刃而解。 2.性能测试需要团队支持 质量是做出来的,而不是测出来的。性能也是同样,并不是有了一个性能测试部门,发 现并定位了问题就能够提升软件的性能,性能的优化需要开发部门和相关部门的通力合作。 3.性能测试需要独立的测试环境 性能测试的测试环境相对功能测试有着更为严格的要求,需要独立的网络和硬件环境, 来保证被测系统是独立可控的,甚至需要专门的管理员和流程来对被测环境进行控制。 4.测试前定义明确的测试目标 性能测试的执行成本较高,为了确保性能测试执行的有效性,在每一次性能测试前应明 确本次性能测试的目标,并对这个目标进行监控和验证。 5.不要在服务器上进行性能测试 虽然服务器可以用来作为负载生成和被负载的对象,但是如果在服务器上进行这样的操 作,系统资源会被负载消耗,导致得出的性能测试数据脱离实际情况。 6.创建的负载应该是模拟用户最常见、最密集的操作 在进行性能测试时,我们应该模拟用户最常使用的功能,来了解在这种操作下系统的资 源消耗情况以及用户体验。 7.在真正的性能测试前尽可能多地进行预测试 在性能测试前尽可能多地进行预测试,发现负载生成的结果以及负载生成是否存在瓶 颈,由于性能测试执行的成本较高,所以通过多次的预测试,可以降低最终测试的成本开 销。 8.使用同一用户进行长时间大量操作是否存在内存泄漏或者类似的错误 通常这样做会发现系统某些功能设置上的问题。例如:当使用同一用户长期进行负载操 作后,系统可能会出现线程崩溃。
还剩18页未读

继续阅读

下载pdf到电脑,查找使用更方便

pdf的实际排版效果,会与网站的显示效果略有不同!!

需要 8 金币 [ 分享pdf获得金币 ] 5 人已下载

下载pdf

pdf贡献者

wjlopenopen

贡献于2012-04-23

下载需要 8 金币 [金币充值 ]
亲,您也可以通过 分享原创pdf 来获得金币奖励!
下载pdf