乐趣区

关于客户端:时间都去哪儿了性能调优分析方法与案例详解

原创 侯龙

一个好的软件,性能和性能都至关重要,这当然离不开产品同学的开光脑瓜、研发同学的乖巧小手,也离不开测试同学的金晶火眼。说到测试,可能大家就会想到页面点点点呀,接口验证呀,业务联调呀等等,其实还有一个很重要的环节,那就是性能测试。

那么,什么是性能测试?如何掂量零碎性能?零碎响应工夫是怎么计算的?如何进行性能调优?带着这些问题,咱们明天就来简略地聊一聊性能调优那些事儿。

1. 性能测试是什么

性能测试就是通过特定的形式,对被测系统依照肯定的测试策略施加压力,获取该零碎的响应工夫、吞吐量、资源利用率等性能指标,来测验零碎上线后是否满足用户需要的过程,次要包含测试需要 / 目标、测试环境 / 工具、测试计划、测试执行、测试后果与剖析。

2. 掂量零碎的四大指标

掂量一个零碎的性能,次要有以下四大指标:

响应工夫

指利用执行一个操作所需的工夫,包含从发出请求开始到最初收到响应所须要的工夫。响应工夫是零碎最重要的性能指标,直观的反映了零碎的快慢。

吞吐量

指单位工夫内零碎解决的申请数,体现零碎的整体解决能力。TPS(Transaction per second) 是吞吐量的一个罕用量化指标,此外还有 HPS(Hits per second)、QPS(Query per second) 等。

资源利用率

指应用服务器、数据库服务器及被测系统蕴含的中间件服务器的 CPU、内存、磁盘、网络等系统资源的应用状况。

并发数

指的是同时提交申请的用户数目。这四个指标之间的关系如图 1。

图 1

吞吐量 = 并发数 / 均匀响应工夫吞吐量 = 并发数 / 均匀响应工夫。

从图 1 咱们能够看到:

  • 当零碎压力较小时,响应工夫简直无变动,吞吐量和系统资源随并发数的减少呈线性增长趋势;
  • 当零碎压力较大时,随着并发数减少,响应工夫也逐步减少,系统资源达到极限,吞吐量不再增长;
  • 持续减少并发数,响应工夫快速增长,系统资源依然在极限状态,吞吐量迅速降落。

个别状况下,咱们心愿零碎可能反对更大的并发和更大的吞吐量。然而,从下面的剖析咱们能够看到,并发数的增长不会始终带来吞吐量的增长,因为系统资源使用率达到极限后,响应工夫将会是决定吞吐量的更大因素,那么,工夫都去哪儿了呢?

3. 工夫都去哪儿了

图 2

一个申请从收回到接管响应,如图 2 所示。大抵流程如下:

  1. 客户端发送申请报文。客户端发送申请报文,通过网络传输后达到服务端;
  2. 服务端解决。服务端接管到申请报文后,进行业务逻辑解决和必要的数据读写操作;
  3. 服务端返回响应报文。服务端解决完后,将响应报文发送到客户端。

咱们通常说的响应工夫是第 1 步、第 2 步、第 3 步耗费的总工夫。第 1 步次要是客户端申请耗时和网络耗时;第 2 步次要是业务逻辑、数据读写和网络耗时;第 3 步次要是客户端渲染和网络耗时。

第 1、2、3 步每一步都有可能存在性能问题,导致响应工夫变长。第 1 步中如客户端主机配置低,反馈慢等,第二步中如业务线程阻塞、数据库查问慢;第 3 步中如网络传输提早。依据各种问题的类型,咱们又能够把问题归为硬件问题、网络问题、代码问题、中间件问题等。不同问题也有不同的调优办法,上面咱们简略聊一聊性能调优。

4. 抓住工夫的小偷 - 性能调优

罕用的调优办法有:

  • 空间换工夫。如数据缓存,提前从磁盘上读取数据缓存到内存中,CPU 申请数据间接从内存中获取,从而达到更高的效率;
  • 工夫换空间,如上传大附件,将数据分批次解决,用更少的空间实现工作解决;
  • 分而治之,把工作切分,离开执行,也不便并行执行来提高效率;
  • 异步解决,如互联网利用最常见的 MQ 音讯队列,将业务链路上比拟耗时的业务拆分进去,通过异步解决缩小阻塞影响;
  • 并行,多个过程或者线程同时解决业务,缩短业务解决工夫;
  • 离用户更近一点,如 CDN 技术,把用户申请的动态资源放在离用户更近的中央;
  • 所有可扩大,业务模块化、服务化(同时无状态化)、良好的程度扩大能力。

上面咱们举几个案例进行阐明。

案例 1

问题形容: 压测某接口时,随着压测执行,响应工夫越来越长。

问题剖析:

  1. 打印线程堆栈,比照线程堆栈信息,发现线程堆栈中 FailoverEvent 的线程数越来越多,最终内存溢出;
  2. 查看代码发现,程序中未判断 FailoverEvent 线程队列是否曾经存在,导致 FailoverEvent 线程队列反复创立。

解决方案 :创立 FailoverEvent 线程队列前,判断其是否存在,如果不存在则创立,如果存在,则应用现有对象。

优化后果 :内存溢出问题解决,响应工夫失常。

调优倡议

  1. 尽早开释无用对象的援用;
  2. 程序进行字符串解决时,尽量避免应用 String,而应应用 StringBuffer;
  3. 尽量少用动态变量;
  4. 防止集中创建对象尤其是大对象;
  5. 尽量使用对象池技术以进步零碎性能;
  6. 不要在常常调用的办法中创建对象,尤其是禁忌在循环中创建对象。

案例 2

问题形容: 某批量解决接口,无积压的状况下,10000 订单,4500sku 品种解决工夫耗时 433 秒。

问题剖析: 接口中采纳单线程形式调用上游服务,查问次数 =sku 品种数 /11,4500sku 品种约 410 次,且每次调用耗时约 519ms。

解决方案 :调用上游服务改用多线程形式。

优化后果 :TP99 由 212 秒降落到 33 秒,TPS 由 87 笔 / 秒晋升到 127 笔 / 秒。

调优倡议 :本案例采纳多线程升高了响应工夫,但并不是说多线程肯定比单线程快,因为干活的是 CPU,不是线程。咱们能够通过确认零碎有无磁盘 / 网络 IO 来进行抉择,有,多线程;无,单线程。并且采纳多线程时,肯定要应用线程池。

案例 3

问题形容: 数据查问接口,TP99=727ms,加大并发,吞吐量无奈晋升,应用服务器 CPU 使用率始终不到 40%。

问题剖析: 通过调用链分析咱们发现,一次申请,调用了 11 次 selectList 办法,导致接口总耗时飙升。

解决方案 :去掉冗余调用,一次申请调用一次 selectList 办法。

优化后果 :TP99 由 727ms 降落到 19ms,晋升 38 倍,TPS 由 17.5 笔 / 秒晋升至 163.4 笔 / 秒,晋升 9 倍。

调优倡议

  1. 设计先于代码;
  2. 根本准则:把数据库操作放在循环之外;
  3. 如果是查问,应用 IN 查问替换 for 循环 (空间换工夫);
  4. 如果是新增,应用批量插入。

案例 4

问题形容: 某接口提交数据库操作,更新数据时产生死锁。

问题剖析: 产生死锁的事务如表 1:

解决方案 :将事务 1 拆分,先查问,而后依据查问的后果批量删除。

优化后果 :死锁问题解决。

调优倡议

  1. 防止大事务;
  2. 按同一程序拜访数据对;
  3. 防止编写蕴含用户交互的事务;
  4. 酌情应用低隔离级别,如 RC;
  5. 为表增加正当的索引,如果不走索引将会为表的每一行记录加锁,死锁的概率就会大大增大;
  6. 防止在同一时间点运行多个对同一表进行读写的脚本,特地留神加锁且操作数据量比拟大的语句;
  7. 设置锁期待超时参数,innodb_lock_wait_timeout。

5. 总结

响应工夫通常只是问题的体现,根本原因在于各种资源的利用是否正当,这里的资源是指狭义的资源,包含硬件 / 软件资源、零碎 / 线程 / 数据等不同级别的资源。调优自身,就是对各种资源进行更正当的配置。调优的目标通常也是为了满足业务需要,因而咱们不用谋求过早和适度优化,并且咱们应该意识到,性能调优不可能一劳永逸,随着业务的迭代,总会有新的问题呈现,因而咱们应该具备打持久战的共识和能力。

举荐浏览

  • 咱们是如何将 ToB 服务的交付能力优化 75%?
  • 干货 | 如何对京东云 GPU 云主机进行 TensorFlow Benchmark 测试
  • 运维大规模 ES 集群的思考和实际

欢送点击【 京东科技 】,理解开发者社区

更多精彩技术实际与独家干货解析

欢送关注【京东科技开发者】公众号

退出移动版