- 浏览: 169752 次
- 性别:
- 来自: 杭州
最新评论
文章列表
原文:《Dynamic Compilation and performance measurement》
动态编译与性能测量
前言
这个月我着手写一篇文章,剖析一个写得非常糟糕的微基准测试。毕竟我们都是痴迷于性能的程序员,而且我们都喜欢了解我们所编写、使用或批 ...
如何保证微基准测试的正确性(避坑)
在实际应用中,微基准测试的适用性可能并不高。因为微基准测试的测试对象往往比较小。如,两个数据结构、两套算法、某个服务的两种不同实现方式。而为了尽量使测试结果对实际应用有更好的借鉴意义,我们不得不尽量将测试环境模拟得非常像真实环境。但这种费时蹩脚的模拟很可能不如直接将测试对象应用到真实环境中,然后对整个系统进行性能测试,所得结果就是真实环境的性能数据,而不用靠实验性的数据去“推测”真实环境性能。当然,在真实环境执行测试的成本与风险也不低。但通常总好过在满是漏洞的模拟环境中挣扎得出一个不靠谱的结果(完全浪费)。
(《解剖一个有缺陷的微基准测试》)
...
原文:《Anatomy of a flawed microbenchmark》
解剖一个有缺陷的微基准测试
前言
即使“良好的性能”不是一个项目的关键需求,甚至不是需求之一,你也很难忽略性能方面的考虑。因为你可能会认为不考虑性能的程序员不是好工程师。在通往编写高性能代码的过程中,开发人员经常会编写基准测试程序来测量对比不同实现方式的性能。不幸的是,正如《Dynamic compilation and performance measurement》所说,与其它静态编译语言相比,评估 Java 中一段代码或数据结构的性能要困难得多。
一个有缺陷的微基准测试
我十月份的文章 ...
简述
JMH 是 java 平台中用于构建、运行并分析 微基准测试 的工具(语言不限于java)。
其原理是:通过字节码处理器与注解生成合成的基准测试代码。
虽然 JMH 可以帮助我们减少构建为基准测试时犯错,但并不能完全避免犯错。所以同行评审还是很有必要的。
JMH 的使用方法
1. 创建测试工程
推荐通过 Maven 创建一个专用的 standalone 工程。这样便于减少无关程序逻辑的影响,所得结果更准确。
示例:
mvn archetype:generate \
-DinteractiveMode=false \
-DarchetypeGrou ...
1. JVM 对代码执行的两类优化
1.1 运行时优化
主要是针对解释执行和动态编译的一些通用机制的优化。如,锁(包括偏斜锁)和内存分配(如 TLAB)。
还包括一些专门优化解释执行效率的机制。如,模板解释器、内联缓存(优化虚方法调用的动态绑定)。
1.2 JIT优化
JVM根据运行时统计信息(Profile),动态决定部分方法(热点代码)被编译成机器码,直接运行在底层硬件上。
JIT 编译器的技术有 方法计数器、循环展开(Loop unrolling)、方法内联、无效代码消除(Dead Code Elimination)、逃逸分析、分支预测(Branch Predicti ...
【Java核心-性能基础】诊断后台服务明显变慢
- 博客分类:
- Java
详细描述问题现象
服务变慢的具体表现形式往往可以提供一些思路,帮我们缩小排查范围。如:
服务时突然变慢 还是 长时间运行后变慢?
该现象是否重复出现?
(
虽然以下开发人员的回答经常会被谴责,甚至认为政 ...
分布式ID方案的要求
分布式 ID 生成方案首先要满足ID的唯一性。
在此基础上再优化,从而为业务提供更好的支持。如:
ID有意义
如果ID是有序的,或其本身就包含了相关业务的时间等其它应用系统本身的业务信息,那就有利于提高处理业务的效率。
提高数据查找效率就是最常见的好处。
服务高可用
生成ID的机器(服务)应该是高可用的,以满足分布式系统整体的高可用目标。
这可以通过主从备份或真正的分布式多服务实例来实现。
ID紧凑
过长的ID处理起来比较耗费资源。在数据库存储与索引性能方面,长ID都不如短ID表现得好。
设计ID时也需要考虑编程语言中基本数据类型 ...
1. Docker ≠ VM
从某些角度看,Docker 与 虚拟机 有些类似。
如:自己的 shell、能独立安装软件包、运行时与其它容器互不干扰。
但 Docker 的虚拟化远没有虚拟机彻底。Docker 是一种更轻量化的隔离技术。如:
-> 用 namespace ...
【Java垃圾回收】G1 GC
- 博客分类:
- Java
1. G1 GC 的堆内存划分
# G1 采用的多个 Region 的方式划分堆内存,而不是简单的条带状划分方式;但它也有“年代”的概念。
也就是说“年代”在 G1 中是逻辑概念。部分 Region 会标记为属于 Eden,部分属于 Survivor,部分属于老年代。
# 每个 Region 大小相同;
最小值为 1MB,最大值为 32MB;但字节数必须是2的幂。
也可以通过 JVM 启动参数进行设置。如:
-XX:G1HeapRegionSize=16M
# JVM 会尽量划分出 2048 个 Region
class HeapRegionBounds : publi ...
简述
happen-before 简化的字面意思就是“某事件在另一事件之前发生”。
happen-before 关系是 Java 内存模型中保证多线程操作可见性的机制。
它可以保证语句的执行顺序,及对内存读写的操作顺序。
为了提高效率,计算机中存在编译器指令重排和CPU乱序执行等优化方式;
这类优化方式在多线程场景中可能会导致多线程存取共享数据时数据状态不一致的问题。
线程内执行的每个操作都被保证在各自后续操作之前被执行——也就是程序会照着我们在编码时写定的先后顺序执行。
synchronized、volatile、lock 等相关代码的操作顺序都属于该机制的一部分。
...
UUID(Universally Unique Identifier)也称为GUID(Globally Unique Identifier),是一个128比特位的数字。它用于唯一的标示一段信息。
UUID的唯一性保障机制与其它一般的编号方案不同,它的唯一性不依赖于一个中心化的注册机构,也不需要在多个UUID生成器之间做协调。
理论上,UUID是有可能重复的。但是在实际合适的应用场景中,其重复几率低到可以忽略。
UUID的历史
UUID最初被应用于NCS(Apollo Network Computing System)。
之后又被应用到OSF(Open Software Fou ...
【Java核心-进阶】GC 调优思路
- 博客分类:
- Java
GC 调优的目标
GC 调优一般是为了:
降低内存占用
降低延迟
增加吞吐量
当然,很难三者都兼顾;一般只能侧重其中一两个。
有时候 GC 参数不合理会导致 OOM,这时候也需要调优。
GC 调优的一般思路
1. 根据实际应用 ...
【Java核心-进阶】常见垃圾收集器
- 博客分类:
- Java
垃圾收集器(GC, Garbage Collector)与具体 JVM 实现有关。不同厂商,不同版本的 JVM,其所提供的 GC 也不同。
1. 常见GC
1.1 Serial GC
它是 JVM 在 client 模式下的默认设置。
“serial”体现在其收集活动是单线程的,且会进入 STW(St ...
以前我们构建 Web 服务的方法是将程序打包后交给 Web 容器,让容器启动服务进程,加载程序包,然后对外提供进程。
现在我们有更方便快捷的方法来构建 Web 服务:用一些轻量级的 Web 框架,让我们的程序包内嵌 Web 服务能力,直接运行一个 main 方法就能启动进程提供 Web 服务。
这类轻量级的 Web 框架有很多。如,Spring Boot、Dropwizard、Vert.x、Grails、Play Framework 等。其中 Spring Boot 最常见。
这类框架工具的特点如下:
优点
1. 容易部署
Web 容器的安装、配置、部署都是巨麻烦的事 ...
Java 远程调试原理
- 博客分类:
- Java
调试器通过debug协议(JDWP, Java Debug Wire Protocol)与被调程序进行通信,实现远程调试。
IDEA,Eclipse 等 IDE 已经提供了比较方便的配置说明和调试器启动方式,我们可以按照提示实现相关配置。
通常,我们是配置被调程序的启动参数,将其先启动,然后在调试器端连接到该被调程序。
《入门科普,围绕 JVM 的各种外挂技术》