博主是一个不是很聪明的码农。完美主义者,强迫症中期。这里会记录一些回忆和点滴,以博为镜。
武器库:
去年是忙碌的一年,今年陆续总结回顾下吧。
我目前所在的项目,使用了Mybatis做ORM,SQL是写到Mapper配置里,所以就导致一个问题,Mapper的语法无法在编译期被检查。而且Mapper错误在运行时的提醒非常晦涩,很难快速定位解决(比如resultType写成了resultMap,服务会不停的重新加载,直到OOM)。特别是开发比较紧张的时期,如果有人写了有问题的Mapper部署到开发服务器上,从发现到解决问题几个回合下来,浪费的不只是一个人的时间,被阻塞的有可能是整个研发团队。
我于是思考能否在发布前发现类似问题。翻了下资料,Mybaits没有相关检查的工具类,没办法,自己动手,丰衣足食。
细细想一下,首先是时机问题,编译期是不用考虑了,那么夹在编译期和运行时中间的只有一个构建期,我们项目用了我厂的omad发布系统,构建脚本是ant写的,想到这思路突然就有了:我在构建期启动一下看报不报错不就齐活了?
于是着手研究错误Mapper导致的异常栈,走读了相关Spring代码,发现第一个DAO方法的调用会触发所有Mapper文件的检查,那么事情就更简单了。
首先是修改构建脚本,在编译打包完成后主动调用一个main函数,启动一下Mybatis相关的部分:
|
|
这里failonerror设置为true ,把这个target放到整个打包的最后一步:
|
|
然后最核心的问题就是这个函数该怎么写:
|
|
如上,短小精悍,写一个Mapper检查专用的Spring配置,启动上下文后主动调用一次DAO访问,然后检查只要不是CannotGetJdbcConnectionException
,就认为必然出了问题,而且极大可能是Mapper的语法不正确。
这里之所以放过CannotGetJdbcConnectionException
是因为omad打包是在独立的打包机执行的,这机器必然没有我们数据库的访问权限,而且只有Mapper检查无误后才会执行真正的DAO操作,也就意味着,它能抛出CannotGetJdbcConnectionException
的话,Mapper的检查就是通过的。
最后看一下专用的Spring配置:
|
|
注意dataSource
的配置,参数的value部分随便填填就好了。
就是这么简单,我只修改了开发环境几个重要工程的打包脚本,添加了这步Mapper文件检查,其他环境也不需要浪费这个时间。后来这几段代码屡立战功,数次把错误的发布挡在运行之前。
原文: http://robsjava.blogspot.com/2014/03/what-is-false-sharing.html
Java8引入了@Contented
这个新的注解来减少伪共享(False Sharing
)的发生。本文介绍了@Contented
注解并解释了为什么False Sharing
是如何影响性能的。
CPU读取内存数据时并非一次只读一个字节,而是会读一段64字节长度的连续的内存块(chunks of memory),这些块我们称之为缓存行(Cache line)。
假设你有两个线程(Thread1和Thread2)都会修改同一个volatile
变量x
:
|
|
如果Thread1先改变x的值,然后Thread2又去读它:
|
|
那么x所在缓存行上的所有64个字节的值都要被重新加载,因为CPU核心间交换数据是以缓存行为最小单位的。当然Thread1和Thread2是有可能在同一个核心上运行的,但我们此处假设两个线程在不同的核心上运行。
已知long类型占8个字节,缓存行长度为64个字节,那么一个缓存行可以保存8个long型变量,我们已经有了一个long型的x,假设x所在缓存行里还有其他7个long型变量,v1到v7:
|
|
这个缓存行可以被许多线程访问。如果其中一个修改了v2,那么会导致Thread1和Thread2都会重新加载整个缓存行。你可能会疑惑为什么修改了v2会导致Thread1和Thread2重新加载该缓存行,毕竟只是修改了v2的值啊。虽然说这些修改逻辑上是互相独立的,但同一缓存行上的数据是统一维护的,一致性的粒度并非体现在单个元素上。这种不必要的数据共享就称之为“伪共享”(False Sharing)。
一个CPU核心在加载一个缓存行时要执行上百条指令。如果一个核心要等待另外一个核心来重新加载缓存行,那么他就必须等在那里,称之为stall
(停止运转)。减少伪共享也就意味着减少了stall
的发生,其中一个手段就是通过填充(Padding)数据的形式,来保证本应有可能位于同一个缓存行的两个变量,在被多线程访问时必定位于不同的缓存行。
在下面这个例子里,我们试图通过填充的方式,使得x
和v1
位于不同的缓存行:
|
|
在你考虑使用填充之前,必须要了解的一点是JVM可能会清除无用字段或重排无用字段的位置,这样的话,可能无形中又会引入伪共享。我们也没有办法指定对象在堆内驻留的位置。
为了避免无用字段被消除,通常我们会用volatile
修饰一下。个人建议只需为处于激烈竞争状态的类进行填充处理,而且一般只有通过对其性能分析才能发现性能上的不同。通常在性能分析时,最好在对其迭代访问10000次之后再去采样,这样可以消除JVM本身的运行时优化策略带来的影响。
除了对字段进行填充之外,还有一个比较清爽的方法,那就是对需要避免陷入伪共享的字段进行注解,这个注解暗示JVM应当将字段放入不同的缓存行,这也正是JEP142的相关内容。
该JEP引入了@Contented
注解。被这个注解修饰的字段应当和其他的字段驻留在不同的位置。
|
|
上面的代码将x和y置于不同的缓存行。@Contented注解将y移动到远离对象头部的地方,(以避免和x一起被加载到同一个缓存行)。
http://openjdk.java.net/projects/jdk8/features
http://beautynbits.blogspot.co.uk/2012/11/the-end-for-false-sharing-in-java.html
http://openjdk.java.net/jeps/142
http://mechanical-sympathy.blogspot.co.uk/2011/08/false-sharing-java-7.html
http://stackoverflow.com/questions/19892322/when-will-jvm-use-intrinsics
https://blogs.oracle.com/dave/entry/java_contented_annotation_to_help
我不是一个喜欢变化的人,但作为一个还算有点追求的技术人,终究要面对的就是变化,转眼离职我店已经三个月了,一直想着在此处稍作总结,没成想也是一拖再拖。
今天不展望未来,只简单回顾下在我店两年多的学习和生活。我12年底拿到我店offer,13年初最终决定离开猪厂,成为了一名所谓的基础架构师。首先感谢一面面试官吴总,问的题目都很适合我,也比较庆幸后面面试我的CJ、HL都比较nice。
入职我店后在大数据团队先混了阵子,和SL一起给Hadoop生态主要成员做了件外皮,后来转到同是架构组的老江手下做消息队列相关研发,终于多年以来对于大并发场景的憧憬成为了现实,激动无比。在SOA团队度过了职业生涯至今最充实的时光,所以其实与其说怀念我店,倒不如说更怀念我们的SOA团队来得准确。
先简单记录下下面几位吧。
80后老码农,资历深,功力更深,SOA团队的导师,伟大的精神领袖,难得的好领导,不鼓励加班,LOL水平一般的重度玩家。常见其手捧英文原版或者打印的英文论文死啃,这其实也是我们工作的一部分内容,不过我是没那个毅力啃完一本大部头的。
此人在杭州有套140方,至于其他城市的房子,我就不多说了。另外其和老江一样,生生抛弃了屙粒粑粑几千股,命运就此转折。
码字是副业,其实是一家公司的二股东,小老板,团队里理论上最富有的人。时政野史的首席发言人,翻大墙师(此处请读者自行调整文字顺序),阿波罗重度用户,故得常委一名。
新上海人,股神,一年只出手若干次,屡次看清大势成功抄底或逃顶,收割起散户无所不用其极,习惯将变量命名为一整句话。
准拆迁富,典型的狗屎运者,刚在闸北买了套又小又旧的拆迁房,就被并入静安区了,最近听说又要拆迁(天理何在?!)。
我见过的唯一的新款MacBook用户,因其极其擅长分析各种线上问题,人送外号人肉detector。
上海土著,旅法学者,CTO校友,似乎是我整个职业生涯中面试过的人里唯一一位成功入职了的。
这几年整个行业的人员流动都很快,这几位是共事比较久的,多事之秋,其中有四位已经另谋出路。其他的如老虎、智红等先不多说。
其他的也随便记录下。
公司附近的一家餐厅,在平时吃饭的地方里算最特别的一个,想来老板应该是旁边艺术学院的老师,装修机具艺术风格,最有意思的是每天只做一套餐,有兴趣的加微信公众号Artaste_yiwei
,可进一步了解其逼格。
周五下午会议室或者必胜客,更新下进度、扯扯淡、吹吹牛、喝喝下午茶。后来加入了一个分享环节,唯一的要求就是分享内容尽量不要与工作内容相关。后来股神一直介绍炒股知识,老江的分享逼格更高,不过我只记得有教怎么看手相,常委主打历史牌,最经典的是详细介绍了古代皇帝的三宫六院建制,我分享过易信的架构以及装修必然被坑的历史教训。
在我店的工作算是比较舒心惬意的,虽然有过几次在高铁上或高速上接到SA电话的黑历史,至于生活,我想,在这个行业,能谈得上有生活,已然算得上不错了。我至今丝毫不避讳对我店的怀念,但人终究是生活在现实中。想记住的太多,反而不知道应该从哪里继续,这里暂时停笔,有缘再补。
合影附上。