Clojure世界: STM的统计
年前一篇blog提过,写了一个stm-profiler用于统计clojure STM的运行状况,放在了github上:
https://github.com/killme2008/stm-profiler STM的事务在遇到写冲突(多个事务写同一个ref的时候)就会回滚事务并重试,通过stm-profiler你可以查看事务的重试次数,重试原因,以及每个reference的使用情况。使用很简单,在lein的project.clj引用stm-profiler:
[stm-profiler "1.0.2-SNAPSHOT"]
注意,目前stm profiler仅支持clojure 1.3。 我们写一个简单例子:
(use 'stm)
(def a (ref 1)) (def b (ref 2)) (dotimes [_ 100] (future (dosync (alter a + 1) (alter b - 1)))) (Thread/sleep 1000) (prn @a) (prn @b) (Thread/sleep 1000) (prn "stm statistics" (stm-stats)) (prn "reference a statistics" (ref-stats a)) (prn "reference b statistics" (ref-stats b)) 定义了两个ref:a和b,然后用future启动100个线程并发地发起同一个事务操作,对a加一,对b减一。最后打印a和b的值,使用stm-stats函数获取stm的统计信息并打印,使用ref-stats获取a和b两个reference的统计信息并打印。 运行这个例子,在启动的时候会有些警告信息,忽略即可(主要是因为stm profiler重新定义了一些跟STM相关的函数和宏,如dosync等,但是仅仅是添加了统计功能,并没有修改他们原本的功能)。 在我机器上的一次输出:
101
-98 "stm statistics" {"(alter a + 1)(alter b - 1)" {:not-running 11, :average-retry 5, :total-cost 1233, :get-fault 44, :barge-fail 224, :change-committed 227, :total-times 100, :average-cost 12}} "reference a statistics" {"(alter a + 1)(alter b - 1)" {:alter 609, :get-fault 44, :barge-fail 224, :change-committed 227}} "reference b statistics" {"(alter a + 1)(alter b - 1)" {:alter 114, :not-running 11}} a和b的结果都没问题。重点看打印的统计信息,(stm-stats)的输出结果是:
{"(alter a + 1)(alter b - 1)" {:not-running 11, :average-retry 5, :total-cost 1233, :get-fault 44, :barge-fail 224, :change-committed 227, :total-times 100, :average-cost 12}}
这个结果是一个map,key是事务的form,而value就是该form的统计信息,也是一个map,具体各项的含义如下:
从输出结果来看,这么简单的一个事务操作,每次事务要成功平均都需要经过5次的重试,最大的原因是因为ref的值在事务中被其他事务更改了,或者尝试打断其他正在运行的事务失败而重试。关于clojure STM的具体原理推荐看这篇文章《Software transactional memory》。STM不是完美的,事务重试和保存每个reference的历史版本的代价都不低。 再看(ref-stats a)的输出:
{"(alter a + 1)(alter b - 1)" {:alter 609, :get-fault 44, :barge-fail 224, :change-committed 227}}
可以看到a在所有事务中的统计信息,返回的结果同样是个map,key是使用了a的事务,value是具体的统计信息。各项的含义类似上表,不过这里精确到了具体的reference。其中alter项是指对a调用alter函数了609次。ref-stats会输出所有在事务中调用了a的函数的调用次数。通过stm profiler你可以分析具体每个事务的执行状况,甚至每个reference的运行状况,查找热点事务和热点reference等。stm-profiler还不完善,目前还不支持1.2(1.4测试是可以的)。希望有兴趣的朋友加入进来一起完善。 文章转自庄周梦蝶 ,原文发布时间2012-02-09
|
最后更新:2017-05-18 20:36:04