CPU Flame Graphs

http://www.brendangregg.com/FlameGraphs/cpuflamegraphs.html

java里可以很方便的通过jvisualvm来采样性能数据,然后分析每个线程栈中比较费时的cpu操作.java以外的程序,通过cpu火焰图来分析性能问题,很直观(比较起来,jvisualvm的cpu sample report没有cpu火焰图直观).

生成的svg报告中,y轴可以理解为调用栈层次,越大调用层次越深.x轴中的长度是调用占用时间比.

CPU Flame Graphs生成过程需要三步:

  1. 采样性能数据(perf, DTrace, SystemTap, and ktap)
  2. 转换性能数据
  3. 利用性能数据生成svg报告

协程

http://niusmallnan.github.io/_build/html/_templates/openstack/coroutine_usage.html http://www.dongliu.net/post/5906310176440320

协程是纯软件实现的多任务调度,在软件层面实现任务的保持和恢复.传统的用多线程的方式来实现任务调度,在高并发场景下,CPU创建开销和CPU上下文切换的开销太大.使用协程,任务调度有程序来调度,不涉及到cpu线程切换和cpu大量创建线程,性能会快不少.

在使用协程时,所有的I/O都需要使用异步I/O,不然性能会大打折扣.

在协程中,不同的执行单元之间通信可以采用共享内存或者消息机制.由于共享内存又会引入共享资源的同步,推荐采用消息机制.

基于线程与基于事件的并发编程之争

http://www.jdon.com/46921

基于线程的并发变成带来了很多问题,很难写出高性能的程序。协程和Actor模型也许可以考虑用来降低CS的开销。

Linux Troubleshooting, Part I: High Load

http://www.linuxjournal.com/magazine/hack-and-linux-troubleshooting-part-i-high-load

10月25(This is my big day)日凌晨线上某系统出现load很高的问题,我当时排查问题的思路和这篇文章类似.简单总结下:

load,系统负载,可以理解为现在等待cpu处理的任务数.如何衡量high呢?这个和cpu核心数有关系,8核cpu,load为8,这个也不能称之为high.

造成high load的原因一般有:

  • CPU-bound load

    某些任务太耗cpu了,导致high load.这个通过看top就能看出来.如果top命令中的xx%wa很高,说明这些任务都在等待去了.

  • load caused by out of memory issues

    由于内存不足,linux在使用swap了,导致high load.这个通过free很容易看出来.

  • I/O-bound load

    iostat/iotop(需安装)都很容易发现原因所在.

我偏向于使用vmstat,用了它,什么都可以看到了.很悲剧的是,这台线上服务器一切正常.服务器重启后,负载一直很低.服务器重启后,一切都正常了.

The Best Plugins for Sublime Text

http://ipestov.com/the-best-plugins-for-sublime-text/

可以把sublime武装成ide的插件.

ibatis和mybatis共存

如果先加载ibatis的jar,会遇到java.lang.reflect.MalformedParameterizedTypeException异常.需要让ibatis后加载.可以修改ibatis依赖的artifactId,比如改为zibatis

MySQL 加锁处理分析

http://hedengcheng.com/?p=771

这篇文章从mysql数据库原理角度来分析锁,很透彻,很深刻.

比如对于一条简单的sql语句:

delete from test where id = ?;

如果id是主键/非空的唯一索引,不会出现gap锁.如果是非索引列,直接锁表(这个太恶心了,因为server和存储引擎分离导致的);如果是非唯一的索引,事务隔离级别是read commit,锁定选取的数据.如果是repeatable read,为了防止幻读,gap lock出现了)

##面向程序员的数据库访问性能优化法则 http://blog.csdn.net/yzsind/article/details/6059209

这篇文章很系统的介绍了程序员应该掌握的数据库优化知识. 首先根据硬件相关知识介绍各种硬件的访问延时/带宽指标:

通过对上面的指标分析,自然得出优化的层次:

  1. 减少数据访问(减少磁盘访问)

    • 正确创建/使用索引
    • 只通过索引访问数据(索引节点中存有数据,通过索引就能拿到数据最高效)
    • 根据查询计划优化索引
    • 一个表上的索引不能太多,会增加修改操作IO.
  2. 返回更少数据(减少网络传输或磁盘访问)

    • 分页(通过rowid分页的方式减少IO,前提是where/order子句都要在索引上)
    • 只返回需要的字段(别使用select *,带来各种问题,对于我们来说,最头痛的是sql版本兼容性问题.)
  3. 减少交互次数(减少网络传输)

    • batch DML(批量操作走jdbc批量接口)
    • In List(多操作合并,依稀记得mysql驱动里也有这样的做法)
    • 设置Fetch Size(默认fetch size可能不是最优的,需要根据实际情况调整,比如分页查询,一次查询100条,在不OOM的前提下增大此值,减少网络io)
    • 使用存储过程(这个得看场景)
    • 使用ResultSet游标处理记录(这一点往往被忽略掉,使用mybatis的RowHandler来解决问题)
  4. 减少服务器CPU开销(减少CPU及内存开销)

    • 使用绑定变量(mysql仅仅支持硬解析,参考)
    • 合理使用排序
  5. 利用更多资源(增加资源)

Why does my Java process consume more memory than Xmx?

https://plumbr.eu/blog/why-does-my-java-process-consume-more-memory-than-xmx

java进程内存消耗会大于我们在-Xmx中指定的值.-Xmx仅仅限制了应用程序使用的heap大小.java进的内存消耗主要包括下面的东东:

Max memory = [-Xmx] + [-XX:MaxPermSize] + number_of_threads * [-Xss]+Other

Other:

  • Garbage collection(GC自己需要消耗内存来记录数据)
  • JIT optimization(JIT优化需要记录代码执行行为,Code cache-JIT编译完成后存放机器码)
  • Off-heap allocations(NIO/DirectMemory之类的东东)
  • JNI code(程序使用第三方JNI代码占用的内存)
  • Metaspace(jdk8使用它取代了permgen)

Understanding the OutOfMemoryError

https://plumbr.eu/blog/understanding-java-lang-outofmemoryerror

  • java.lang.OutOfMemoryError: Java heap space

    heap空间不足.一般加大-Xmx.如果还不足就有可能是内存泄漏了.

  • java.lang.OutOfMemoryError: PermGen space

    permgen空间不足,默认的jvm配置得比较小,需要通过-XX:MaxPermSize加大.动态代码生成技术和容器redeploy资源泄漏也会导致permgen不足

  • java.lang.OutOfMemoryError: GC overhead limit exceeded

    jvm gc行为中超过98%以上的时间去释放小于2%的堆空间时会报这个错误

  • java.lang.OutOfMemoryError: unable to create new native thread

    java没创建一个线程,会占用-Xss大小空间.这个异常有可能是系统内存不足导致.如果系统内存充足,往往是ulimit -u限制了一个用户创建最大线程数造成的.

  • java.lang.OutOfMemoryError: Requested array size exceeds VM limit

    申请的数组大小超过jvm定义的阀值.

  • java.lang.OutOfMemoryError: request bytes for . Out of swap space?
  • java.lang.OutOfMemoryError: (Native method)

20 Obstacles to Scalability

本文罗列了20个影响伸缩性的瓶颈

10 Obstacles to Scaling Performance

  1. Two-Phase Commit

    两阶段提交需要等待参与方确认,延时太大.所以我们基本上使用best-effort 1pc+业务上的重试.

  2. Insufficient Caching

    各个层次都需要引入缓存机制,现在我们对browser cache/page cache还做得比较少.

  3. Slow Disk I/O, RAID 5, Multitenant Storage

    数据库服务起I/O很关键.如果只做raid建议做raid10.当然加上fushion io之类的加速卡更好.

  4. Serial Processing

    服务并行处理我们也还思考得比较少.比如对远程服务进行合理并行处理(可以考虑下java8中的CompletableFuture).对于缓存数据的获取,可以考虑批量获取.

  5. Missing Feature Flags

    特性开关,说大点就是服务降级,我们需要却分不同服务的重要等级,适当时候关闭某些服务,保证核心业务正常运行.

  6. Single Copy of the Database
  7. Using Your Database for Queuing
  8. Using a Database for Full-Text Searching
  9. Object Relational Models(orm很好用,但是缺少能hold住他的人)
  10. Missing Instrumentation(需要监控/profile工具)

10 Obstacles to Scaling Beyond Optimization Speed

  1. Lack of a Code Repository and Version Control
  2. Single Points of Failure
  3. Lack of Browse-Only Mode(对于内容型的网站,此功能非常重要)
  4. Weak Communication
  5. Lack of Documentation
  6. Lack of Fire Drills(却分演练,特别是大的运维调整,此项非常必要)
  7. Insufficient Monitoring and Metrics
  8. Cowboy Operations
  9. Growing Technical Debt
  10. Insufficient Logging