Java 并发编程笔记:JMH 性能测试框架

概述

JMH 是一个由 OpenJDK/Oracle 里面那群开发了 Java 编译器的大牛们所开发的 Micro Benchmark Framework 。何谓 Micro Benchmark 呢?简单地说就是在 method 层面上的 benchmark,精度可以精确到微秒级。可以看出 JMH 主要使用在当你已经找出了热点函数,而需要对热点函数进行进一步的优化时,就可以使用 JMH 对优化的效果进行定量的分析。

比较典型的使用场景还有:

  • 想定量地知道某个函数需要执行多长时间,以及执行时间和输入 n 的相关性
  • 一个函数有两种不同实现(例如实现 A 使用了 FixedThreadPool,实现 B 使用了 ForkJoinPool),不知道哪种实现性能更好

尽管 JMH 是一个相当不错的 Micro Benchmark Framework,但很无奈的是网上能够找到的文档比较少,而官方也没有提供比较详细的文档,对使用造成了一定的障碍。但是有个好消息是官方的 [Code Sample][1] 写得非常浅显易懂,推荐在需要详细了解 JMH 的用法时可以通读一遍——本文则会介绍 JMH 最典型的用法和部分常用选项。

Java 并发编程笔记:如何使用 ForkJoinPool 以及原理

前言

Java 1.7 引入了一种新的并发框架—— Fork/Join Framework。

本文的主要目的是介绍 ForkJoinPool 的适用场景,实现原理,以及示例代码。

TLDR; 如果觉得文章太长的话,以下就是结论

  • ForkJoinPool 不是为了替代 ExecutorService,而是它的补充,在某些应用场景下性能比 ExecutorService 更好。(见 Java Tip: When to use ForkJoinPool vs ExecutorService
  • ForkJoinPool 主要用于实现“分而治之”的算法,特别是分治之后递归调用的函数,例如 quick sort 等。
  • ForkJoinPool 最适合的是计算密集型的任务,如果存在 I/O,线程间同步,sleep() 等会造成线程长时间阻塞的情况时,最好配合使用 ManagedBlocker

Java 并发编程笔记:如何让一个线程停下来

前言

这几天趁辞职和下一份工作的间隙,考虑把 Java 的基础再好好补一下。提到 Java 的进阶使用,并发编程自然是无法绕过的一个主题。在上一份工作中初次接触了 Java,但在实际工作中使用到并发编程的次数屈指可数,所以尽管日常的使用或许没有问题,但对实现细节了解不深,还不能做到“知其所以然”。这一系列文章——尽管在写下这句话时还只有这第一篇文章,但我希望自己能够坚持写成一个系列——是我在探索“所以然”过程中的思考和记录,希望对后来人能够有帮助吧。

因为这篇文章的初衷是学习笔记而非教程,所以不会从创建10个 Thread 打印10句 “Hello, world!” 开始,而是在每篇文章中选取一个较小的主题,结合自己阅读 JDK 源代码的心得和网上搜索到的资料写成。由于 Java 是个拥有20年历史的古老项目,而且特别注重向后兼容性,因而有新旧 API 共存、某些设计反直觉、设计思想不统一等不利于后来人理解的因素,我也希望能够尽可能从历史的角度来解释“所以然”。

当然因为止于 Java 我还是初学者,而文章里涉及历史时也包含推测的部分,如果在阅读中发现有错误和缺陷的话,还请大家留言指正。

以上差不多是写下这篇文章的初衷,我们开始吧。

我是如何失去价值50000美元的Twitter用户名的

这是一篇在Twitter上看到的文章,文章的作者因为使用了独立域名的邮箱地址作为网站的登录邮箱,导致在DNS服务器被攻破时失去了很多网站帐号的控制,最终损失了价值50000美刀的Twitter帐号。独立域名邮箱作为提升逼格的一种重要手段,相信还是有不少程序员对此趋之若鹜的XD 特别推荐倒数第二段作者吸取的教训,很值得一看。


我价值50000美元的Twitter用户名被盗了

感谢PayPal和GoDaddy

我有一个很稀有的Twitter用户名,@N。是的,只有一个字母。曾经有人出价50000美元向我购买这个用户名。也有很多人尝试盗我的帐号,密码重置邮件出现在我的邮箱里是一件很稀疏平常的事。然而今天,这个用户名已经不再属于我。我被迫放弃了它。

一次格式化字符串攻击(上)

最近大部分时间都花在做这组题上了(当然还有GTA5,不愧是2.6亿打造出来的游戏啊),题目的类型很丰富,涉及密码破解、反汇编、sql注入、hash碰撞等等,而且大部分都包含提示,搜索一下关键词就能找到破解的线索,或者真不济……还有公司里同事所写的解题报告 :)

今天在这里主要记载一下第四题的解题过程,因为在这题上花费了最多的时间,而且又是我比较喜欢的汇编级别的漏洞利用,当然最重要的是,借由这题了解了一种过去不知道的攻击方式——格式化字符串攻击(format string attack)。

注:本文需要一定程度的汇编知识,虽然尽可能地做到详细解释,不过对汇编和c语言的汇编表示不太熟悉的朋友强烈推荐看一下CSAPP的第三章。

关于滨野纯的访谈

上一篇文章中提到,最近正在阅读《入门Git》,搜索作者滨野纯相关信息的时候搜到了以下这篇著名博客作家小饲弹对滨野纯的访谈,里面提及了滨野纯当初参与Git项目时的轶事,以及他对于开源项目的看法。特别是滨野纯说“Git是他第一次有一定规模地向开源项目提交代码”,很是鼓舞人——对那些想参与开源项目但缺乏信心的同学。所以趁闲把访谈全文翻译了一下,原文请见:

#22 Gitメンテナ 濱野純:小飼弾のアルファギークに逢いたい♥

ps:至于最后的 ♥ 我就不吐槽了……

diff的两个参数

最近在读滨野纯所著的《入门Git》,很有意思,主要集中于书中散见各处的作者提及Git当初的设计思想和实现过程的时候。我一直相信,理解一件事物最好的方式就是理解历史。作者作为在Git尚且只是雏形时(2005年7月末)就从Linus手中接过Git的维护工作,并在接下来的数年中将其发扬光大的关键人物( Linus: “In the last four years under his stewardship, git has flourished and become not just a technically advanced source control manager, but one that is a pleasure to use as well.” ),在书中谈论当初开发时的想法和过程自然是信手拈来——

会这么期待说明我还是太天真了。我可以感受到作者希望让这本书“名符其实”的良苦用心,但事实证明写好入门书的权力永远都只属于入门者,作者从来就不曾是一名“Git入门者”自然不会理解初学者最需要的是什么、最困惑的是什么,一上来就讲 Three-way Merge 的原理这是要闹哪样……

不过还是有这么一章,相对完整地讲述了当初的设计思想,并提到了diff的两个我之前并不知道的参数,让我觉得值得一写。其实对于Git的diff和log命令,日常使用在大多数情况无参数的输出已经足够,就我个人的经验,最常使用的参数也不外乎于-p--name-only,至多再修改一下--pretty。然而这一章告诉我,diff能做的不止于此,或者更确切地说,Git当初的目标就考虑得比这更远。Git试图成为的是一个理解历史的文件系统[^1]。

欧洲人在日本

看到以后笑了很久…… 译自 HN 上的某个帖子作者似乎是一位欧洲友人。

程序员的命名趣味

……孔乙己显出极高兴的样子,将两个指头的长指甲敲着柜台,点头说,“对呀对呀!……exec有六样写法,你知道么?”我愈不耐烦了,努着嘴走远。孔乙己刚用指甲蘸了酒,想在柜上写字,见我毫不热心,便又叹一口气,显出极惋惜的样子。

这自然只是我的杜撰,不过 Unix 系统的 exec 确实有[六种写法][1],想必当年也是害苦了不少系统程序员。其实今天我想说的,正是关于命名的事儿。相信以下已经成为程序员的共识:

好的命名对提高可读性事半功倍,坏的命名则是代码晦涩的一大帮凶。

但取一个好的名字又谈何容易,也无怪乎某朋友开玩笑说“(写代码)瓶颈是取变量名”了。不过凡事,博古大抵可以通今,所以这里就整理一下 *nix 系统中一些有趣的命令以及它们有趣的名字,总结一下所谓的“命名范式”,或许对大家今后的命名之道有用。

走开,Daddy

回头发现,这个新博客的第一周大部分时间是在和GoDaddy的折腾中度过的。虽然过去一直对GoDaddy没有特别好的印象(可能和杂乱的界面以及创始人Bob Parsons的前海军陆战队身份有关),但当决定注册一个新域名时第一个想到的依然是GoDaddy,于是我注册了,付款了,ping通了,一切都显得很顺利。

只是那时的我没想到之后的一周会如此折腾。

Jeff Dean的二三事

最早是某同事发来的链接,结果让我笑了一晚上……看看也不是太长,于是翻译分享一下。注:比较Geek,千茶学姐对不住了!

这是Google 2007年的愚人节笑话,罗列了很多Jeff Dean的“光辉事迹”。大名鼎鼎的Jeff Dean想必不用我介绍了。……好吧,还是介绍一下,Jeff Dean是Google最早的一批员工,本来的研究领域是OOT语言的优化技术,也因此是Google很多基础系统的设计者和实现者,BigTable,MapReduce的作者……介绍什么的还是太麻烦了,直接正文吧。

一个Vim插件

这又是一篇技术博客(千茶学姐对不起了),讲的就是上班无聊的时候,写了一个Vim插件。其实在上篇博客写就的时候,插件也快写完了,然而……就如你所见的又拖了半个月。——写这句话的时候还只是半个月,而接下来的内容又拖了一个星期。

起因是这样的:周末的时候某知名国际五百强企业的同学来镰仓旅游,顺便也就到我所住的宿舍来玩。那天正巧是端午节,嘉兴出身的某知名国际五百……太麻烦了以下简称某同学自己吃了从国内带来的粽子不说,完全没有惦记到我连个粽子都不带空手而来,于是我们开始玩三国杀。可惜宿舍里的中国人满打满算也只有四口人,看来是不能常规打法了,于是我建议要不模仿大逃杀吧,谁活到最后就算赢。然后第二天上班的时候我就开始看大逃杀,因为发现自己原来还没看过这本小说。虽然仗着全是中文字所以用Vim打开了光明正大的在上班时间看小说,不过难免还是有点心虚,虽然谁也不会来看。为了解决上班看小说容易心虚的难题,于是我用接下来两天的上班时间写了下面的这个插件。

说 ruby on rails 很简单什么的都是骗人的!

最近偶然看到这样一篇抱怨 rails 的文章,和《UNIX痛恨者手册》一样的吐槽风格,非常搞笑,今天趁闲于是翻译了过来。特别是在搞笑之余,因为涉及到的技术方面很多,对于 web 开发不是很熟悉的同学或许还能从中学到一些东西,我自己就是在这篇文章中了解了不少过去不知道的概念和软件,然后意识到追赶潮流实在是个无底洞……好吧,这其实没啥关系。