Skip to content

Commit afade3d

Browse files
committed
irmin: Move LRU cache to kcas
1 parent 4562e70 commit afade3d

File tree

6 files changed

+106
-130
lines changed

6 files changed

+106
-130
lines changed

irmin.opam

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ depends: [
2222
"uutf"
2323
"jsonm" {>= "1.0.0"}
2424
"eio" {>= "0.12"}
25+
"kcas" {>= "0.6.1"}
26+
"kcas_data" {>= "0.6.1"}
2527
"lwt" {>= "5.6.1"}
2628
"digestif" {>= "0.9.0"}
2729
"ocamlgraph"
@@ -41,6 +43,8 @@ depends: [
4143
]
4244

4345
pin-depends: [
46+
# Fix segv in kcas
47+
[ "kcas.dev" "git+https://[email protected]/ocaml-multicore/kcas#5f3a39dfc72189e2b83f96c3754d402d5e7d6bc5"]
4448
# Metrics may have been unnecessarily constrained in opam-repository
4549
[ "metrics.dev" "git+https://github.com/mirage/metrics#995eb18d2837df02c8ead719c00fb156cf475ab5"]
4650
[ "metrics-unix.dev" "git+https://github.com/mirage/metrics#995eb18d2837df02c8ead719c00fb156cf475ab5"]

src/irmin-pack/io/lru.ml

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,5 +87,3 @@ let mem { lru; _ } k = Internal.mem lru k
8787
let clear t =
8888
Internal.clear t.lru;
8989
t.total_weight <- 0
90-
91-
let iter { lru; _ } f = Internal.iter lru (fun k wv -> f k (v wv))

src/irmin-pack/io/lru.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,3 @@ val add : t -> int63 -> Irmin_pack.Pack_value.weight -> value -> unit
3636
val find : t -> key -> value
3737
val mem : t -> key -> bool
3838
val clear : t -> unit
39-
val iter : t -> (key -> value -> unit) -> unit

src/irmin/dune

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
logs
1212
logs.fmt
1313
eio
14+
kcas
15+
kcas_data
1416
mtime
1517
ocamlgraph
1618
uri

src/irmin/lru.ml

Lines changed: 100 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -16,174 +16,148 @@
1616

1717
(* Extracted from https://github.com/pqwy/lru *)
1818

19-
module MakeUnsafe (H : Hashtbl.HashedType) = struct
20-
module HT = Hashtbl.Make (H)
19+
open Kcas
20+
21+
module Make (H : Hashtbl.HashedType) = struct
22+
module HT = Kcas_data.Hashtbl
2123

2224
module Q = struct
2325
type 'a node = {
2426
value : 'a;
25-
mutable next : 'a node option;
26-
mutable prev : 'a node option;
27+
next : 'a node option Loc.t;
28+
prev : 'a node option Loc.t;
2729
}
2830

29-
type 'a t = {
30-
mutable first : 'a node option;
31-
mutable last : 'a node option;
32-
}
31+
type 'a t = { tail : 'a node option Loc.t; head : 'a node option Loc.t }
3332

34-
let detach t n =
35-
let np = n.prev and nn = n.next in
33+
let detach ~xt t n =
34+
let np = Xt.get ~xt n.prev and nn = Xt.get ~xt n.next in
3635
(match np with
37-
| None -> t.first <- nn
36+
| None -> Xt.set ~xt t.tail nn
3837
| Some x ->
39-
x.next <- nn;
40-
n.prev <- None);
38+
Xt.set ~xt x.next nn;
39+
Xt.set ~xt n.prev None);
4140
match nn with
42-
| None -> t.last <- np
41+
| None -> Xt.set ~xt t.head np
4342
| Some x ->
44-
x.prev <- np;
45-
n.next <- None
43+
Xt.set ~xt x.prev np;
44+
Xt.set ~xt n.next None
4645

47-
let append t n =
46+
let append ~xt t n =
4847
let on = Some n in
49-
match t.last with
48+
let hd = Xt.get ~xt t.head in
49+
match hd with
5050
| Some x as l ->
51-
x.next <- on;
52-
t.last <- on;
53-
n.prev <- l
51+
Xt.set ~xt x.next on;
52+
Xt.set ~xt t.head on;
53+
Xt.set ~xt n.prev l
5454
| None ->
55-
t.first <- on;
56-
t.last <- on
57-
58-
let node x = { value = x; prev = None; next = None }
59-
let create () = { first = None; last = None }
60-
61-
let iter t f =
62-
let rec aux f = function
63-
| Some n ->
64-
let next = n.next in
65-
f n.value;
66-
aux f next
67-
| _ -> ()
68-
in
69-
aux f t.first
55+
Xt.set ~xt t.tail on;
56+
Xt.set ~xt t.head on
7057

71-
let clear t =
72-
t.first <- None;
73-
t.last <- None
58+
let node x = { value = x; prev = Loc.make None; next = Loc.make None }
59+
let create () = { tail = Loc.make None; head = Loc.make None }
60+
61+
let clear ~xt t =
62+
Xt.set ~xt t.tail None;
63+
Xt.set ~xt t.head None
7464
end
7565

76-
type key = HT.key
66+
type key = H.t
7767

7868
type 'a t = {
79-
ht : (key * 'a) Q.node HT.t;
69+
ht : (key, (key * 'a) Q.node) HT.t;
8070
q : (key * 'a) Q.t;
81-
mutable cap : cap;
82-
mutable w : int;
71+
cap : cap;
72+
w : int Loc.t;
8373
}
8474

8575
and cap = Uncapped | Capped of int
8676

87-
let weight t = t.w
77+
let weight ~xt t = Xt.get ~xt t.w
8878

8979
let create cap =
9080
let cap, ht_cap =
9181
if cap < 0 then (Uncapped, 65536) else (Capped cap, cap)
9282
in
93-
{ cap; w = 0; ht = HT.create ht_cap; q = Q.create () }
83+
{
84+
cap;
85+
w = Loc.make 0;
86+
ht = HT.create ~hashed_type:(module H) ~min_buckets:ht_cap ();
87+
q = Q.create ();
88+
}
9489

95-
let drop t =
96-
match t.q.first with
90+
let drop ~xt t =
91+
let tl = Xt.get ~xt t.q.tail in
92+
match tl with
9793
| None -> None
9894
| Some ({ Q.value = k, v; _ } as n) ->
99-
t.w <- t.w - 1;
100-
HT.remove t.ht k;
101-
Q.detach t.q n;
95+
Xt.modify ~xt t.w (fun tw -> tw - 1);
96+
HT.Xt.remove ~xt t.ht k;
97+
Q.detach ~xt t.q n;
10298
Some v
10399

104-
let remove t k =
105-
try
106-
let n = HT.find t.ht k in
107-
t.w <- t.w - 1;
108-
HT.remove t.ht k;
109-
Q.detach t.q n
110-
with Not_found -> ()
100+
let remove ~xt t k =
101+
match HT.Xt.find_opt ~xt t.ht k with
102+
| None -> ()
103+
| Some n ->
104+
Xt.modify ~xt t.w (fun tw -> tw - 1);
105+
HT.Xt.remove ~xt t.ht k;
106+
Q.detach ~xt t.q n
111107

112108
let add t k v =
113-
let add t k v =
114-
remove t k;
115-
let n = Q.node (k, v) in
116-
t.w <- t.w + 1;
117-
HT.add t.ht k n;
118-
Q.append t.q n
109+
let tx ~xt =
110+
let add t k v =
111+
remove ~xt t k;
112+
let n = Q.node (k, v) in
113+
Xt.modify ~xt t.w (fun tw -> tw + 1);
114+
HT.Xt.replace ~xt t.ht k n;
115+
Q.append ~xt t.q n
116+
in
117+
match t.cap with
118+
| Capped c when c = 0 -> ()
119+
| Uncapped -> add t k v
120+
| Capped c ->
121+
add t k v;
122+
if weight ~xt t > c then
123+
let _ = drop ~xt t in
124+
()
119125
in
120-
match t.cap with
121-
| Capped c when c = 0 -> ()
122-
| Uncapped -> add t k v
123-
| Capped c ->
124-
add t k v;
125-
if weight t > c then
126-
let _ = drop t in
127-
()
128-
129-
let promote t k =
130-
try
131-
let n = HT.find t.ht k in
132-
Q.(
133-
detach t.q n;
134-
append t.q n)
135-
with Not_found -> ()
136-
137-
let find_opt t k =
138-
match HT.find_opt t.ht k with
139-
| Some v ->
140-
promote t k;
141-
Some (snd v.value)
142-
| None -> None
143-
144-
let mem t k =
145-
match HT.mem t.ht k with
146-
| false -> false
147-
| true ->
148-
promote t k;
149-
true
150-
151-
let iter t f = Q.iter t.q (fun (k, v) -> f k v)
152-
153-
let clear t =
154-
t.w <- 0;
155-
HT.clear t.ht;
156-
Q.clear t.q
157-
end
158-
159-
(** Safe but might be incredibly slow. *)
160-
module Make (H : Hashtbl.HashedType) = struct
161-
module Unsafe = MakeUnsafe (H)
162-
163-
type 'a t = { lock : Eio.Mutex.t; data : 'a Unsafe.t }
164-
165-
let create cap =
166-
let lock = Eio.Mutex.create () in
167-
let data = Unsafe.create cap in
168-
{ lock; data }
169-
170-
let add { lock; data } k v =
171-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.add data k v
126+
Xt.commit { tx }
172127

173-
let find_opt { lock; data } k =
174-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.find_opt data k
128+
let drop t = Xt.commit { tx = drop t }
175129

176-
let find t k = match find_opt t k with Some v -> v | None -> raise Not_found
130+
let promote ~xt t n =
131+
Q.detach ~xt t.q n;
132+
Q.append ~xt t.q n
177133

178-
let mem { lock; data } k =
179-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.mem data k
134+
let find t k =
135+
let tx ~xt =
136+
match HT.Xt.find_opt ~xt t.ht k with
137+
| Some v ->
138+
promote ~xt t v;
139+
snd v.value
140+
| None ->
141+
raise Not_found
142+
in
143+
Xt.commit { tx }
180144

181-
let iter { lock; data } f =
182-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.iter data f
145+
let mem t k =
146+
let tx ~xt =
147+
match HT.Xt.find_opt ~xt t.ht k with
148+
| None -> false
149+
| Some v ->
150+
promote ~xt t v;
151+
true
152+
in
153+
Xt.commit { tx }
183154

184-
let clear { lock; data } =
185-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.clear data
155+
let clear t =
156+
let tx ~xt =
157+
Xt.set ~xt t.w 0;
158+
HT.Xt.clear ~xt t.ht;
159+
Q.clear ~xt t.q
160+
in
161+
Xt.commit { tx }
186162

187-
let drop { lock; data } =
188-
Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.drop data
189163
end

src/irmin/lru.mli

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,5 @@ module Make (H : Hashtbl.HashedType) : sig
2323
val find : 'a t -> H.t -> 'a
2424
val mem : 'a t -> H.t -> bool
2525
val clear : 'a t -> unit
26-
val iter : 'a t -> (H.t -> 'a -> unit) -> unit
2726
val drop : 'a t -> 'a option
2827
end

0 commit comments

Comments
 (0)