2013-06-18 3 views

Antwort

2

Sie können die history count eines ref beobachten, die anzeigt, dass Streit dort drauf ist:

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 

Die Geschichte Zählung nicht direkt Behauptung vertreten ist. Stattdessen stellt es die Anzahl der vergangenen Werte dar, die beibehalten wurden, um gleichzeitige Lesevorgänge zu bedienen.

Die Größe der Historie ist durch die Werte min und max begrenzt. Standardmäßig sind dies 0 bzw. 10, aber Sie können sie ändern, wenn Sie ref erstellen (siehe oben). Da min-history standardmäßig 0 ist, sehen Sie normalerweise ref-history-count nicht von Null verschiedene Werte, es sei denn, es gibt Streit in der Referenz.

Weitere Diskussion über history count hier: https://groups.google.com/forum/?fromgroups#!topic/clojure/n_MKCoa870o

Ich glaube nicht, gibt es eine Möglichkeit, zur Verfügung gestellt von clojure.core, die Rate der STM-Transaktionen im Moment zu beobachten. Sie können natürlich auch etwas tun, ähnlich dem, was @Chouser tat in seiner history stress test:

(dosync 
    (swap! try-count inc) 
    ...) 

das heißt innerhalb der Transaktion einen Zähler erhöhen. Die Erhöhung erfolgt jedes Mal, wenn die Transaktion versucht wird. Wenn try-count größer als 1 ist, wurde die Transaktion wiederholt.

+0

nie daran gedacht, Verwenden Sie die Geschichte Anzahl oder Atome innerhalb TXS. Danke für die Vorschläge! – vemv

2

von DoSync Blöcke und genannt Einführung begehen zählt (die Zeiten ein benannter DoSync gelungen ist), kann man ganz leicht den Überblick über die Zeiten Threads eine gegebene Transaktion erneut versucht haben.

(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#)) 
    [email protected] 
    (alter commit-number update-in [~tx-name] (fnil inc 0)))) 

das folgende Beispiel gegeben ...

(def foo (ref {})) 

(def bar (ref {})) 

(defn x [] 
    (dosync :x ;; `:x`: the tx-name. 
      (let [r (rand-int 2)] 
      (alter foo assoc r (rand)) 
      (Thread/sleep (rand-int 400)) 
      (alter bar assoc (rand-int 2) (@foo r))))) 

(dotimes [i 4] 
    (future 
    (dotimes [i 10] 
    (x)))) 

... @history ausgewertet:

;; {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}}, ...} 
0

Diese zusätzliche Implementierung wesentlich einfacher ist.

;; {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))) 
    [email protected])) 
Verwandte Themen