年前一篇blog提过,写了一个stm-profiler用于统计clojure STM的运行状况,放在了github上: STM的事务在遇到写冲突(多个事务写同一个ref的时候)就会回滚事务并重试,通过stm-profiler你可以查看事务的重试次数,重试原因,以及每个reference的使用情况。使用很简单,在lein的project.clj引用stm-profiler: [stm-profiler "1.0.2-SNAPSHOT"] 注意,目前stm profiler仅支持clojure 1.3。 我们写一个简单例子: (use 'stm) (dotimes [_ 100] (future (dosync (alter a + 1) (alter b - 1)))) 定义了两个ref:a和b,然后用future启动100个线程并发地发起同一个事务操作,对a加一,对b减一。最后打印a和b的值,使用stm-stats函数获取stm的统计信息并打印,使用ref-stats获取a和b两个reference的统计信息并打印。 运行这个例子,在启动的时候会有些警告信息,忽略即可(主要是因为stm profiler重新定义了一些跟STM相关的函数和宏,如dosync等,但是仅仅是添加了统计功能,并没有修改他们原本的功能)。 在我机器上的一次输出: 101 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}} 通过stm profiler你可以分析具体每个事务的执行状况,甚至每个reference的运行状况,查找热点事务和热点reference等。stm-profiler还不完善,目前还不支持1.2(1.4测试是可以的)。希望有兴趣的朋友加入进来一起完善。 文章转自庄周梦蝶 ,原文发布时间2012-02-09 |
Clojure世界: STM的统计
时间: 2024-09-17 04:50:12
Clojure世界: STM的统计的相关文章
Clojure世界:如何做性能测试
我们经常需要在程序中测量某段代码的性能,或者某个函数的性能,在Java中,我们可能简单地循环调用某个方法多少次,然后利用System.currentTimeMillis()方法测量下时间.在Ruby中,一般都是用Benchmark module做测试,提供了更详细的报告信息. 同样,在Clojure里你可以做这些事情,你仍然可以使用System.currentTimeMillis()来测量运行时间,例如: user=> (defn sum1 [& args] (reduce +
Clojure世界:静态代码分析
Java世界里有findbugs这样的神器,可以让你避免很多"简单愚蠢"的bug.同样,Clojure世界里也有相应的替代品,这就是今天要介绍的kibit.不过kibit现在还比较年轻,判断的规则较少,但是已经可以使用起来做clojure代码的静态检查. 项目主页:https://github.com/jonase/kibit 使用: 1.安装lein插件: lein plugin install jonase/kibit 0.0.2 2.在项目的根目录运行 lein kibi
Clojure世界:API文档生成
继续Clojure世界之旅,介绍下我今天的探索成果,使用clojure生成clojure项目的API文档.在java里,我们是利用javadoc生成API文档,各种build工具都提供了集成,例如maven和ant都提供了javadoc插件或者task.在Clojure世界里,同样有一系列工具帮助你从源码中自动化生成API文档.今天主要介绍三个工具.不过我不会介绍怎么在clojure里写doc,具体怎么做请看一些开源项目,或者直接看clojure.core的源码. 首先是codo
专家谈我国GDP世界第二:统计方法存在失真
中国GDP增速一年一个台阶.(新华社) 新闻由头 随着日本近日公布上半年和二季度国内生产总值(GDP)数据,中国GDP总量是否超越日本成为世界第二大经济体再度成为议论焦点. 8月16日,日本内阁府公布的数据显示,日本第二季度国内生产总值(GDP)为1.288万亿美元,同期中国GDP总值为1.337万亿美元. 早在8月2日,中国央行副行长.国家外汇管理局局长易纲接受采访时就透露,中国实际上已是世界第二大经济体,这是中国官员首次指出中国经济成为"世界第二". 在很多西方媒体看来,中国GDP
Clojure世界:使用rlwrap增强REPL
Clojure的REPL非常方便,可以随时随地试验你的想法,REPL是read-eval-print-loop的简称.默认clojure.contrib有带一个shell脚本来启动REPL,具体看这里.你也可以用JLine来增强REPL: java -cp "%CLOJURE_DIR%\jline-VERSION.jar;%CLOJURE_JAR%" jline.ConsoleRunner clojure.main 不过,其实你还可以用rlwrap这个GNU库来增强clo
Clojure世界:文件IO
文件读写是日常编程中最经常使用的操作之一.这篇blog将大概介绍下Clojure里对文件操作的常用类库. 首先介绍标准库clojure.java.io,这是最经常用的IO库,定义了常见的IO操作. 首先,直接看一个例子,可以熟悉下大多数常用的函数: (ns io (:use [clojure.java.io])) ;;file函数,获取一个java.io.File对象 (def f (file "a.txt")) ;;拷贝文件使用copy (copy f (f
Clojure世界:利用HouseMD诊断clojure
HouseMD是淘宝的聚石写的一个非常优秀的Java进程运行时诊断和调试工具,如果你接触过btrace,那么HouseMD也许你应该尝试下,它比btrace更易用,不需要写脚本,类似strace的方式attach到jvm进程做跟踪调试. 基本的安装和使用请看这篇文档<UserGuide>,恕不重复.以下内容都假设你正确安装了housemd. 本文主要介绍下怎么用housemd诊断跟踪clojure进程.Clojure的java实现也是跑在JVM里,当然也可以用housemd
Clojure世界:单元测试
单元测试也是一个开发中最常见的需求,在Java里我们用JUnit或者TestNG,在clojure里也内置了单元测试的库.标准库的clojure.test,以及第三方框架midje.这里我将主要介绍clojure.test这个标准库,midje是个更加强大的测试框架,广告下,midje的介绍在第二次cn-clojure聚会上将有个Topic,我就不画蛇添足了.通常来说,clojure.test足够让你对付日常的测试. 首先看一个最简单的例子,定义一个函数square来计算平方,然
Clojure世界:日志管理——clojure.tools.logging
处理日志是任何一个产品级的程序都需要仔细处理的模块.在Java中,我们经常使用的是log4j就是一个日志框架.在clojure里,同样有一套日志框架--clojure.tools.logging,它不仅提供了常用的日志输出功能,还屏蔽了Java各种日志框架之间的差异,如slf4j,commons-logging,log4j,java.util.logging等,让你可以透明地使用这些框架来处理日志. 名称:clojure.tools.logging 主页:https://github.co