小海's profileFlier's SkyPhotosBlogListsMore ![]() | Help |
|
|
October 24 Java 线程锁定优化策略Brian Goetz 最近在其 dw Java theory and practice 专栏 里发表了几篇有趣的文章,介绍了 Sun HotSpot JVM 在以后几个版本中,对锁定等性能优化的思路。 Synchronization optimizations in Mustang 其中核心的思路是将锁分为 contended 和 uncontended 两类来分别优化。根据 80/20 经验原则和一些实测数据,大多数的线程锁实际上都只是预防性的。例如被广泛使用的 Vector 类中,绝大多数方法都被缺省加上 synchronized 修饰符以避免多线程问题,虽然这能够最大限度降低潜在的问题,但相应付出的代价也是巨大的。因为大量的实际使用都是局部或者不会涉及线程同步情况的,例如下面这种情况:
要缓解此问题,一方面可以从使用者角度通过库的选择来避免无效锁定,另一方面则可以由 JVM 根据行为进行锁定优化。 对前者来说,随着 JDK 的发展可以说灵活性大大增强。例如选择性使用 ArrayList 和 Collections.synchronizedList 可以获得类似的能力,但并不用付出不必要的代价;同时也可以使用已成为 JDK 1.5 标准库的 concurrent 库,根据多线程的使用情况进行锁定优化。这方面 C/C++ 库的设计理念非常优秀,那就是决不为用不到的东西付出代价。 对后者来说,则可以发挥 JVM 与传统静态编译相比最大的优势,根据运行时行为进行优化。 Lock elision 的思路,就是通过 escape 分析找出根本不存在多线程引用可能性的锁。对这种情况 Java 语言规范中明确允许进行优化,直接去掉不必要的锁定语义。而最大的问题则在于如何进行 escape 分析,并找到锁的可优化范围。因为相对于基于栈的 C/C++ 来说,Java 内存模型目前是完全基于堆的,每个对象都在全局堆中可以由任何外部线程访问。 有兴趣深入研究的话,可以看看下面这两篇文章 http://www.research.ibm.com/people/g/gupta/toplas03.pdf http://www.research.ibm.com/people/j/jdchoi/escape-pointsto.html Adaptive locking 的思路,则是将 contended 的锁定按锁定时间进一步细分。因为对大多数锁定来说,锁定的时间都是非常短的,例如很多 get/set 方法,以及简单的内存操作。对这些方法来说,如果要完成一个完整的锁定流程,需要涉及到对象锁状态更新、等待线程对象构建、甚至与操作系统一级的线程调度打交道。相对于实际要工作所耗费的时间来说,锁定这个操作自身消耗的资源可能反而是大头。对这些情况而言,与其建立一个完整的锁上下文,不如直接用 spin 锁机制进行等待:
如果一定时间或尝试次数后还是无法获得锁,则 JVM 可以将此锁的类型转换为长时间的锁,然后构造完整的锁上下文进行管理。而这种优化方法,最能够体现动态 JIT 相对于传统静态编译器的优势,因为这些执行行为的信息是无法静态获取的。 Lock coarsening 的思路,则是通过将临近的几个相同锁定进行合并,以减少不必要的重复锁定操作。这种优化的原理是基于重复方法往往同时出现的模式,例如下面这种常见情况
对这种情况来说,每次调用 add 方法进行锁定和解锁是没必要的,JVM 可以根据运行时信息选择性合并同类型锁。随着现在机器自动代码生成的广泛引用,可以预期这种基于行为对锁进行合并的思路会非常有用。 此外 David Dagastine 在其 blog 上也对 Java 同步锁优化进行了讨论 关于 Escape 分析 Brian Goetz 还在另外一篇讨论 Java 性能问题误解的文章中有所提及。 Urban performance legends Urban performance legends, revisited 文中讨论了一些对 Java 性能问题的常见误解,其中很多问题是旧版本 JVM 和 Java 库中存在的,随着 JDK 的不断更新已经不同程度上得到缓解,例如下述等等问题。 Synchronization is really slow Declaring classes or methods final makes them faster Immutable objects are bad for performance 这些问题的出现,往往是因为使用者对 JVM 的实现和优化思路不熟悉导致的。实际上 HotSpot 自从 JDK 1.3 版本以后,实际上有了非常大的进步,无论是从功能还是性能上,都已经远远超出了某些人的预期。而在可以预见的 Mustang 和 Dolphin 中,更高级和动态的优化还会不断加入进来,并从 JVM 一级对应用产生透明的性能提升。 例如基于 Escape 分析的栈分配优化,有可能一改 JVM 只从堆中建立对象的传统,直接将动态分析得到的仅由线程自身使用的对象,以类似 C/C++ 的方式直接在栈中分配。这一改进如果能够成熟,对 JVM 性能的提升将是非常可观的。因为对现代 CPU 架构来说,提升性能的一个关键问题就在于 Cache 的使用。相对于位置离散的堆来说,栈一般都能确保在缓存中的命中率;而在堆中分配内存,哪怕分配性能很高,但因为缓存往往无法命中,带来的性能缺失会非常大。而且使用基于栈的内存管理模式,还可以享受到析构对象的快捷性,函数调用完成后,只需要将原函数的栈顶指针弹出即可释放所有临时对象。 如果对此方面有兴趣,可以看看 Brian Goetz 这个非常不错的 Java theory and practice 专栏 ,下面是其中关于性能优化的其他文章 Performance management -- do you have a plan? Is that your final answer? To mutate or not to mutate? September 15 企业级信息搜索服务 前几天部门开会讨论知识管理,其中提到一个很重要的问题,就是如何对企业内部各种积累下来的信息,提供统一、方便且安全的检索支持。虽然大部分现有机制,例如 SPS、论坛、邮件、IM 等等,基本上都提供了一定程度的检索支持。但从企业知识管理这个层面,并没有一个很好的现存解决方案。
而要解决这个问题,基本上是一个非常复杂的系统工程,需要涉及很多方面:
虽然看起来非常复杂,但技术上还是可以通过对现有工具的重用,达到最大限度降低二次开发工作量的。 首先,可以通过模拟 GDS/SPS 的相关检索插件运行环境,重用这些针对特定格式的分析器。这样一来直接就可以提供大部分常用文档格式的支持,且以后的扩展和升级余地较大。 其次,可以通过分布式代理,将检索插件的分析结构,汇总到中央服务器统一进行存储。通过 lucene 等现成检索支持工具,完成基于关键字的存储和检索支持,并可以获得现成的使用界面和管理支持。 此外,可以在存储分析后内容时,通过预定义树型结构来区分内容。以便于在实际使用时,根据可定义的权限系统来保护机密内容。 最后,可以针对不同的客户端和业务应用,开发相应的检索界面和检索代理,以完成实际的工作。
Seems funny……回头整个原型出来 :D 此外还可以类似 google 的企业级搜索那样,弄个基于网络流量监听的检索支持服务,可以把 snort 之类的 ids 引擎改改,做一些简单的协议如 http, smtp, pop3 的解码,并针对其内容进行检索和存储。
感觉这块如果能做好,市场潜力应该还是挺大的,毕竟知识管理和检索是绝大多数企业所关心,也能够给其迅速带来切身利益的。 August 26 声明性事务的粒度 最近大概看了一下几个平台的事务处理机制,感觉 .NET 在这方面目前大大落后于 Java 阵营,追赶和改进的余地还非常大。
首先因为 .NET 实际上是通过 COM+ 来完成声明性事务的支持,而一直到 Win2003 的 COM+ 1.5 版,COM+ 都只支持在对象一级定义事务隔离性。也就是说,在定义 COM+ 组件的事务性时,我必须使用最高一级的事务隔离性需求来限定组件。例如在一个 Service 对象中,调用两个不同 DAO 对象实现域对象的读写,虽然读操作只需要 ReadUncommitted 隔离级别,但因为写操作需要 Serializable 级别,我就得将整个对象设置为 Serializable 级别。而实际上 99% 的操作可能都只是调用需要 ReadUncommitted 隔离级别的读功能,因此会产生大量不必要的数据锁定。
在现有架构下优化效率的方法,大概就只能手工将不同隔离级别的功能,拆分为多个类来实现并分头定义隔离性。而这样一来就违背了声名性事务的初衷,也大大增加了开发者的负担。
而 Java 在这方面就相对好些,通过容器(J2EE/Spring)管理的声明性事务,可以细到方法一级定义事务的隔离性和超时时间等细节。而且在隔离性的细分上,也提供了更多的选择。
.NET 2.0 这方面似乎也没有做太大的改进,只是在隔离性级别上细分出 Snapshot,毕竟根结在于 COM+ 声明性事务的粒度选择问题。
最好的解决方法莫过于微软出手,在 COM+ 新版本中提供方法一级的事务定义能力,毕竟 COM+ 有在方法一级定义安全性的先例,实现起来不会存在太大问题。
另一种解决方法,是在 COM+ 组件和实际事务使用对象之间,建立一个事务声明隔离层。也就是说通过 IoC 容器和 AOP 植入的思路,将事务的声明从与 COM+ 对象的前期绑定,挪到运行时由事务隔离层在方法一级指定。这种思路的缺陷在于无法提供 COM+ 管理工具的透明性,而只能依赖于隔离层的配置工具。但带来的优点是,事务使用的对象可以与事务支持彻底解耦,只需要定义一个普通的 .NET 对象,然后在隔离层进行配置即可。而 COM+ 1.5 新增的动态 Context 定义的能力(CoEnterServiceDomain/CoLeaveServiceDomain),则使的这种机制甚至能够完全脱离 COM+ 的声明性事务,而改用事务隔离层的声明性事务动态完成。
回头整个原型出来,估计会很有意思。 :D
August 21 关注企业级服务自身的可管理性 《Enterprise Services with the .NET Framework》一书实际上漏掉了一个非常重要的议题,那就是对企业级服务自身的可管理性支持。JSE 5 中一个非常重要的改进,就是直接集成了对 JMX 标准的支持,这一特性的运用能大大增强服务的可用性。JBoss 的设计人员就曾评价说,JBoss 4 之所以能够成功,很大程度上依赖于基于 JMX 的微内核结构的设计,而 JMX 在 JBoss 实现上也起到了事实上的服务容器与管理机制的作用。虽然普通的企业级应用,没有必要灵活到全部通过 JMX 类似的机制管理,但基于 JMX 机制提供服务自身的监控和管理支持确实非常必要的选择。而 Java 阵营的绝大多数引擎和服务,都陆续提供了 JMX 支持和集成;MS 自身的几乎所有服务器端产品,也都内嵌了 WMI 和性能监视器的支持。
Windows 平台下与 JMX 对应的是 WMI 架构,它在底层通过类似 SNMP MIB 表的机制定义自己的 Metadata 模型,在上层则通过类似 LDAP 的机制提供访问和查询。并且也提供了非常灵活的事件通知机制,以及各种辅助开发工具。
WMI 的概念和应用可以参考:
.NET 在这方面提供了非常易于使用的封装和支持
不过 WMI 在针对分布式系统的监控上,相对于 JMX 缺乏良好的支持。不知是不是因为 MS 将这块的特性,准备放到单独的 MOM ( Microsoft Operations Manager ) 产品中销售,因此故意不去增加支持 :S
不过总体上 MS 给人的感觉是,在企业级应用层面想的不太明白,往往看到 JEE 阵营有什么好东东,就抄过来实现之。但却始终没有想明白一个问题,有功能和能将功能用起来,对于企业级应用来说是完全两码事。毕竟指望每个 MS 架构下的设计师都通晓其所有的技术,这本身就不太现实。而通过种种看似方便,实际上分散且繁琐的封装和工具,虽然可以缓解这一问题,但长期来说只会导致大家都偷懒用缺省配置,虽然效率低但好歹能工作,知其然而不知其所以然。Windows 下的企业级应用,从 DNA 开始扯到现在,仍是个半死不活的状况(起码就国内来说如此),MS 应该好好检讨一下自己的相关策略了。 August 18 又一届 xcon 直到坐在xcon的会场,才恍然察觉到又过了一年。只不过去年的这个时候还在辛苦的赶演讲稿件,而今年却可以心安理得坐在会场里面打瞌睡,呵呵。 揭幕的议题是小许的 Hacks Windows CE,把 WinCE 的内核与组织结构剖析了一把后,提出了一些传统 shellcode 手法在 WinCE 上的实现方法。虽然在技术上的解决并没有很完美,但毕竟已是业内较为领先的探索,这种勇于探索新领域的精神还是非常不错的。感觉小许真是挺不容易的,从无到有在缺少参考资料、缺少实验条件的情况下,折腾到这个程度。还成功打入国外“黑”社会,去拉斯维加斯宣讲了一把,呵呵,总算没苦练几年英语。 第二场因为原定主讲一老外要调时差,改由江海客讲他们的网络防毒。不过感觉 seak 现在不知是进化还是退化,已经完全变成一售前。通篇大谈各种宏观数据和技术方向,却一点实在的信息都不舍得给。偶只好看看杂志打打瞌睡了 :S 不过说起病毒技术领域,一段时间以来都是平淡的很,有的只是一些厂商的商业抄做,和一些莫名其妙的半调子病毒。有时也觉得他们挺可怜的,满腹的高深知识,却每每要跟那些 script kidding 写的,技术巨烂却行之有效的蠕虫和木马做搏斗。 中午的午休是意外的收获,从乌烟瘴气的都市丛林出来,能脱了鞋走在保养良好的大片草坪上,看着小桥边盛开的荷花,躺在柳树下的草堆里,在熟悉又陌生的草香中,吃饱饭幸福的睡午觉,哈哈,真是惬意之极啊。 下午先是一马来西亚的华裔讲《可编程信号同步》,一堆一堆的波形图、电路图,一个又一个似曾相识的数学符号,听得我云里雾里,似乎回到了大学硬件课程全挂的时候。最后问了几个人,才弄明白这个是用来对未知的电器接口进行攻击的,不知现实中的可行性到底有多强。反正他老兄的英文和中文,我是都没怎么听懂。 接下来的 tk 则是做了一个全面的无线知识科普讲座,听完我唯一的感觉是实在tmd太麻烦了,我是不会再去碰这块的东西了,等 tk 弄出 total solution 我等直接 copy 算了。感觉 tk 可以到淘宝上,开个各种 bt 无线装备的专卖店,顺便承接来料加工等服务。 最不爽的是回来的时候,从那个该死的北京会议中心,在烈日下步行了一两公里,才找到可以打车的地方。 总的来说 xcon 是越来越成功了,无论是规模还是影响力都是与日俱增。但不知这样发展下去,xcon 是否还可以保持一颗平常心,坚持其技术峰会的定位。毕竟各种商业和政治上的诱惑是巨大的,而会议的定位直接决定参会的人数和能拉到的赞助。而就此次的议题来说,也有务虚比例逐渐增高的趋势,而且纯技术层面的广度也在增加,开始有我听不懂的议题了,也不知是好事还是坏事 :S 希望 xcon 能越来越成功,xfocus 能越来越成功! August 16 享受 .NET 时代的 COM+ 开发 等明天看完 Queue Component 和 Loosely Coupled Events 两章,这本《Enterprise Services with the .NET Framework: Developing Distributed Business Solutions with .NET Enterprise Services》就基本上快结束了。虽然是工具书类型的,但也算让我重新系统的了解了一把 .NET 时代的 COM+ 开发。 虽然本质上还是换汤不换药,但 CLR 对COM+功能的封装能力,绝对能让经历过用 ATL 编写 COM+ 组件的人,流下一大滩口水,呵呵。COM+组件的集成调试和 DCOM 的发布配置,是为数不多曾让我能感受到抓狂感觉的技术,以至于当年有一段时间给别人出的方案,都是能关的安全设置就关,所有应用服务器和web服务都用相同密码的admin帐号,呵呵,这大概就是绝望下的垂死挣扎吧。 而与 Delphi 支持思路一脉相承的 CLR 在这方面,则将 RTTI/Metadata 的威力发挥的淋漓尽致,大量的底层薄记工作丢到 CCW/RCW 以及相关辅助工具中。但要全面了解这些强大的attributes和一堆辅助工具,缺了这样一本书还真是不行。虽说以前有些COM+的底子,也看过并实际用过System.EnterpriseServices,居然还能在此书中找到20%强的新知识,感觉实在是非常不错。结合前段刚刚看的 Trans COM+ 一书,偶的 COM+ 了解在三个代表的指引下又 level up 了。 不过此书的不足之处也是很明显的,就是非常明确的工具书定位,基本上很少涉及原理性和实践性的知识。稍好一点的是在一些可互相替代技术或选项之间,提供了一个纯技术层面的对比。不过相对于以前那几本号称 .NET 下企业级编程的书来说,已经强过太多了。 但就算如此,感觉 .NET 下的企业级开发的改进余地仍然很大,MS 在技术连贯性、互通性和合作能力方面,距离 java 阵营还是挺远的。就连出的半官方企业开发支持库,都取一个不怎么合时宜的 Enterprise Library 做名字,跟 Java 阵营满天非的 Framework, Architecture, Infrastructure 相比太厚道了一点,呵呵。希望 MS 不要在这方面落得太远,毕竟只有 Library 层面支持的开发环境,是无法被称之为企业级开发环境的。而寄希望于使用者能自行了解并整合分散技术点,在一段相当长时间内也是不现实的。 August 07 感受 COM+ 事务性 陆陆续续花了一个多月时间,总算把《 事务性COM+编程——创建可伸缩应用系统 》看完一遍。虽说其间仍是七八本书并行在看,中间还得刨去休假的一周多时间,但以我啃中文书的速度来说可以算比较慢了。归根结底原因可以总结为两条:书写的实在是太好;翻译的人可以直接拖出去砍了。:S
虽说书是2001年才出版2003年才翻译过来的,但即使到现在仍是我看过的关于COM+的十余本著作中唯一能将问题说清楚的,其重要性不亚于 COM 领域的 <Inside COM> 一书。而从其名字中的 Transactional 一词就可以看出,作者决不是那种拿着 MSDN 边琢磨边攒稿件的人,因为此书的书名一语道破了 COM+ 的真谛,那就是 Transactional。
如果说 COM 演变七八年来还在底层的二进制互通性上穷折腾的话,从 MTS 发展而来的 COM+ 则一开始就站在企业级开发的高度上,名字虽只差一个 "+",但所面向的领域和目标相差千里。就算 .NET 如日中天,但在企业级应用领域还是得建构在 COM+ 的基础之上, 只不过提供了一个更为友好和强大的集成开发环境罢了。
此书正是站在这样一个高度,针对企业级开发中的事务性编程所需要面对和解决的问题,结合 COM+ 的思想和实现娓娓道来。从 Context 到 Apartment,从 Causatiy 到 Activity,从 Object Pool 到 JITA,作者将 COM/COM+ 的底层机制分析得透彻淋漓,更能跳出技术谈技术,从 how 到 what 到 why 逐步提升层次。而其后的事务和隔离性两章更是难得的能就事论事讨论事务处理利弊,而不像很多书籍里面只是不疼不痒的描述一番如何如何使用,却大言不惭的猛吹一番美好前景。美中不足的是最后关于设计层面的介绍稍显薄弱,仅仅针对几个特定场景做了局部分析,如果能有一个全局性的蓝图就更完美了。
在文笔上 Tim 虽然没有非常出众的才华,但在整体结构的把握上还是不错的,而且还算图文并茂,也不吝于示例。可惜有些关键技术点的描述,不知是原文如此还是翻译太烂,过于拖沓冗长而且说不清楚。不过说起翻译水平,绝对可以直接拖出去砍了,居然还有多处明显的机器翻译痕迹 :S 搞得偶每次只能先猜测英文是怎么说,再翻译回来尝试理解。
|
|
|