Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/clojure/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Clojure 可以监视STM';竞争级别是多少?_Clojure_Stm - Fatal编程技术网

Clojure 可以监视STM';竞争级别是多少?

Clojure 可以监视STM';竞争级别是多少?,clojure,stm,Clojure,Stm,是否有任何方法可以轮询Clojure的STM事务是否正在重试,以及以何种速率重试?您可以观察ref的历史计数,这将表明存在争用: user=> (def my-ref (ref 0 :min-history 1)) #'user/my-ref user=> (ref-history-count my-ref) 0 user=> (dosync (alter my-ref inc)) 1 user=> (ref-history-count my-ref) 1 历史记录计数

是否有任何方法可以轮询Clojure的STM事务是否正在重试,以及以何种速率重试?

您可以观察ref的
历史计数,这将表明存在争用:

user=> (def my-ref (ref 0 :min-history 1))
#'user/my-ref
user=> (ref-history-count my-ref)
0
user=> (dosync (alter my-ref inc))
1
user=> (ref-history-count my-ref)
1
历史记录计数并不直接表示争用。相反,它表示为服务并发读取而维护的过去值的数量

历史记录的大小受
min
max
值的限制。默认情况下,它们分别是
0
10
,但您可以在创建
ref
时更改它们(参见上文)。由于默认情况下
min history
0
,因此通常不会看到
ref history count
返回非零值,除非ref上存在争用

有关
历史记录计数的更多讨论,请参见此处:

我认为目前没有任何方法可以通过
clojure.core
观察STM事务的速率。当然,您可以做一些类似于@Chouser在其

i、 e.在交易中增加一个计数器。每次尝试事务时都会发生增量。如果
try count
大于
1
,则会重试事务。

通过引入命名的dosync块和提交计数(命名的dosync成功的次数),可以很容易地跟踪线程重试给定事务的次数

(def ^{:doc "ThreadLocal<Map<TxName, Map<CommitNumber, TriesCount>>>"}
  local-tries (let [l (ThreadLocal.)]
                (.set l {})
                l))

(def ^{:doc "Map<TxName, Int>"}
  commit-number (ref {}))

(def history ^{:doc "Map<ThreadId, Map<TxName, Map<CommitNumber, TriesCount>>>"}
  (atom {}))

(defn report [_ thread-id tries]
  (swap! history assoc thread-id tries))

(def reporter (agent nil))

(defmacro dosync [tx-name & body]
  `(clojure.core/dosync
    (let [cno# (@commit-number ~tx-name 0)
          tries# (update-in (.get local-tries) [~tx-name] update-in [cno#] (fnil inc 0))]
      (.set local-tries tries#)
      (send reporter report (.getId (Thread/currentThread)) tries#))
    ~@body
    (alter commit-number update-in [~tx-name] (fnil inc 0))))
@history
的计算结果为:

;; {thread-id {tx-name {commit-number tries-count}}}
{40 {:x {3 1, 2 4, 1 3, 0 1}}, 39 {:x {2 1, 1 3, 0 1}}, ...}

这种附加实现实质上更简单

;; {thread-id retries-of-latest-tx}
(def tries (atom {}))

;; The max amount of tries any thread has performed
(def max-tries (atom 0))

(def ninc (fnil inc 0))

(def reporter (agent nil))

(defn report [_ tid]
  (swap! max-tries #(max % (get @tries tid 0)))
  (swap! tries update-in [tid] (constantly 0)))

(defmacro dosync [& body]
  `(clojure.core/dosync
    (swap! tries update-in [(.getId (Thread/currentThread))] ninc)
    (commute commit-id inc)
    (send reporter report (.getId (Thread/currentThread)))
    ~@body))

从未想过使用历史计数或txs中的原子。谢谢你的建议!另见:
;; {thread-id {tx-name {commit-number tries-count}}}
{40 {:x {3 1, 2 4, 1 3, 0 1}}, 39 {:x {2 1, 1 3, 0 1}}, ...}
;; {thread-id retries-of-latest-tx}
(def tries (atom {}))

;; The max amount of tries any thread has performed
(def max-tries (atom 0))

(def ninc (fnil inc 0))

(def reporter (agent nil))

(defn report [_ tid]
  (swap! max-tries #(max % (get @tries tid 0)))
  (swap! tries update-in [tid] (constantly 0)))

(defmacro dosync [& body]
  `(clojure.core/dosync
    (swap! tries update-in [(.getId (Thread/currentThread))] ninc)
    (commute commit-id inc)
    (send reporter report (.getId (Thread/currentThread)))
    ~@body))