Skip to content

Commit d765faf

Browse files
committed
Use records table & layer hints to avoid unneeded mst traversal
1 parent b39e41c commit d765faf

File tree

3 files changed

+68
-64
lines changed

3 files changed

+68
-64
lines changed

mist/lib/mst.ml

Lines changed: 41 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -207,11 +207,12 @@ module type Intf = sig
207207

208208
val retrieve_node_raw : t -> Cid.t -> node_raw option Lwt.t
209209

210-
val retrieve_node : t -> Cid.t -> node option Lwt.t
210+
val retrieve_node : ?layer_hint:int -> t -> Cid.t -> node option Lwt.t
211211

212-
val retrieve_node_lazy : t -> Cid.t -> node option Lwt.t lazy_t
212+
val retrieve_node_lazy :
213+
layer_hint:int -> t -> Cid.t -> node option Lwt.t lazy_t
213214

214-
val get_node_height : t -> node_raw -> int Lwt.t
215+
val get_node_height : ?layer_hint:int -> t -> node_raw -> int Lwt.t
215216

216217
val traverse : t -> (string -> Cid.t -> unit) -> unit Lwt.t
217218

@@ -271,27 +272,40 @@ struct
271272
| None ->
272273
Lwt.return_none
273274

274-
(* retrieves & hydrates a node by cid *)
275-
let rec retrieve_node t cid : node option Lwt.t =
276-
match%lwt retrieve_node_raw t cid with
277-
| Some raw ->
278-
hydrate_node t raw |> Lwt.map Option.some
279-
| None ->
280-
Lwt.return_none
281-
282-
(* lazy version of retrieve_node *)
283-
and retrieve_node_lazy t cid = lazy (retrieve_node t cid)
275+
(* returns the layer of a node, using hint if provided *)
276+
let rec get_node_height ?layer_hint t node : int Lwt.t =
277+
match layer_hint with
278+
| Some layer ->
279+
Lwt.return layer
280+
| None -> (
281+
match (node.l, node.e) with
282+
| None, [] ->
283+
Lwt.return 0
284+
| Some left, [] -> (
285+
match%lwt retrieve_node_raw t left with
286+
| Some node ->
287+
let%lwt height = get_node_height t node in
288+
Lwt.return (height + 1)
289+
| None ->
290+
failwith ("couldn't find node " ^ Cid.to_string left) )
291+
| _, leaf :: _ -> (
292+
match leaf.p with
293+
| 0 ->
294+
Lwt.return (Util.leading_zeros_on_hash (Bytes.to_string leaf.k))
295+
| _ ->
296+
failwith "first node entry has nonzero p value" ) )
284297

285298
(* hydrates a raw node *)
286-
and hydrate_node t node_raw : node Lwt.t =
299+
let rec hydrate_node ?layer_hint t node_raw : node Lwt.t =
300+
let%lwt layer = get_node_height ?layer_hint t node_raw in
301+
let child_layer = layer - 1 in
287302
let left =
288303
match node_raw.l with
289304
| Some l ->
290-
retrieve_node_lazy t l
305+
retrieve_node_lazy ~layer_hint:child_layer t l
291306
| None ->
292307
lazy Lwt.return_none
293308
in
294-
let%lwt layer = get_node_height t node_raw in
295309
let entries =
296310
List.fold_left
297311
(fun (entries : entry list) entry ->
@@ -307,7 +321,7 @@ struct
307321
let right =
308322
match entry.t with
309323
| Some r ->
310-
retrieve_node_lazy t r
324+
retrieve_node_lazy ~layer_hint:child_layer t r
311325
| None ->
312326
lazy Lwt.return_none
313327
in
@@ -316,24 +330,16 @@ struct
316330
in
317331
Lwt.return {layer; left; entries}
318332

319-
(* returns the layer of a node *)
320-
and get_node_height t node : int Lwt.t =
321-
match (node.l, node.e) with
322-
| None, [] ->
323-
Lwt.return 0
324-
| Some left, [] -> (
325-
match%lwt retrieve_node_raw t left with
326-
| Some node ->
327-
let%lwt height = get_node_height t node in
328-
Lwt.return (height + 1)
329-
| None ->
330-
failwith ("couldn't find node " ^ Cid.to_string left) )
331-
| _, leaf :: _ -> (
332-
match leaf.p with
333-
| 0 ->
334-
Lwt.return (Util.leading_zeros_on_hash (Bytes.to_string leaf.k))
335-
| _ ->
336-
failwith "first node entry has nonzero p value" )
333+
(* retrieves & hydrates a node by cid *)
334+
and retrieve_node ?layer_hint t cid : node option Lwt.t =
335+
match%lwt retrieve_node_raw t cid with
336+
| Some raw ->
337+
hydrate_node ?layer_hint t raw |> Lwt.map Option.some
338+
| None ->
339+
Lwt.return_none
340+
341+
and retrieve_node_lazy ~layer_hint t cid =
342+
lazy (retrieve_node ~layer_hint t cid)
337343

338344
(* calls fn with each entry's key and cid *)
339345
let traverse t fn : unit Lwt.t =

pegasus/lib/repository.ml

Lines changed: 12 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,6 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
263263
: write_result Lwt.t =
264264
with_write_lock t.did (fun () ->
265265
let open Sequencer.Types in
266-
let module Inductive = Mist.Mst.Inductive (Mst) in
267266
let%lwt prev_commit =
268267
match%lwt User_store.get_commit t.db with
269268
| Some (_, commit) ->
@@ -280,11 +279,11 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
280279
Cid.to_string c
281280
| None ->
282281
"null" ) ) ;
283-
let%lwt block_map = Lwt.map ref (get_map t) in
284282
let cached_store = Cached_store.create t.db in
285283
let mst : Cached_mst.t ref =
286284
ref (Cached_mst.create cached_store prev_commit.data)
287285
in
286+
t.block_map <- None ;
288287
(* ops to emit, built in loop because prev_data (previous cid) is otherwise inaccessible *)
289288
let commit_ops : commit_evt_op list ref = ref [] in
290289
let added_leaves = ref Block_map.empty in
@@ -297,7 +296,7 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
297296
let path = Format.sprintf "%s/%s" collection rkey in
298297
let uri = Format.sprintf "at://%s/%s" t.did path in
299298
let%lwt () =
300-
match String_map.find_opt path !block_map with
299+
match%lwt User_store.get_record_cid t.db path with
301300
| Some cid ->
302301
Errors.invalid_request ~name:"InvalidSwap"
303302
(Format.sprintf
@@ -314,7 +313,6 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
314313
let%lwt cid, block =
315314
User_store.put_record t.db (`LexMap record_with_type) path
316315
in
317-
block_map := String_map.add path cid !block_map ;
318316
added_leaves := Block_map.set cid block !added_leaves ;
319317
commit_ops :=
320318
!commit_ops
@@ -340,7 +338,7 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
340338
| Update {collection; rkey; value; swap_record; _} ->
341339
let path = Format.sprintf "%s/%s" collection rkey in
342340
let uri = Format.sprintf "at://%s/%s" t.did path in
343-
let old_cid = String_map.find_opt path !block_map in
341+
let%lwt old_cid = User_store.get_record_cid t.db path in
344342
( if
345343
(swap_record <> None && swap_record <> old_cid)
346344
|| (swap_record = None && old_cid = None)
@@ -385,7 +383,6 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
385383
User_store.put_record t.db (`LexMap record_with_type) path
386384
in
387385
added_leaves := Block_map.set new_cid new_block !added_leaves ;
388-
block_map := String_map.add path new_cid !block_map ;
389386
commit_ops :=
390387
!commit_ops
391388
@ [{action= `Update; path; cid= Some new_cid; prev= old_cid}] ;
@@ -409,7 +406,7 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
409406
; cid= new_cid } )
410407
| Delete {collection; rkey; swap_record; _} ->
411408
let path = Format.sprintf "%s/%s" collection rkey in
412-
let cid = String_map.find_opt path !block_map in
409+
let%lwt cid = User_store.get_record_cid t.db path in
413410
( if cid = None || (swap_record <> None && swap_record <> cid)
414411
then
415412
let cid_str =
@@ -441,7 +438,6 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
441438
Lwt.return_unit
442439
in
443440
let%lwt () = User_store.delete_record t.db path in
444-
block_map := String_map.remove path !block_map ;
445441
commit_ops :=
446442
!commit_ops @ [{action= `Delete; path; cid= None; prev= cid}] ;
447443
let%lwt new_mst = Cached_mst.delete !mst path in
@@ -458,29 +454,16 @@ let apply_writes (t : t) (writes : repo_write list) (swap_commit : Cid.t option)
458454
let commit_block =
459455
new_commit_signed |> signed_commit_to_yojson |> Dag_cbor.encode_yojson
460456
in
461-
let diff : Inductive.diff list =
462-
List.fold_left
463-
(fun (acc : Inductive.diff list)
464-
({action; path; cid; prev} : commit_evt_op) ->
465-
match action with
466-
| `Create ->
467-
acc @ [Add {key= path; cid= Option.get cid}]
468-
| `Update ->
469-
acc @ [Update {key= path; cid= Option.get cid; prev}]
470-
| `Delete ->
471-
acc @ [Delete {key= path; prev= Option.get prev}] )
472-
[] !commit_ops
473-
in
474457
let%lwt proof_blocks =
475-
match%lwt
476-
Inductive.generate_proof !block_map diff ~new_root:new_mst.root
477-
~prev_root:prev_commit.data
478-
with
479-
| Ok blocks ->
480-
Lwt.return (Block_map.merge blocks !added_leaves)
481-
| Error err ->
482-
raise err
458+
Lwt_list.fold_left_s
459+
(fun acc ({path; _} : commit_evt_op) ->
460+
let%lwt key_proof =
461+
Cached_mst.proof_for_key new_mst new_mst.root path
462+
in
463+
Lwt.return (Block_map.merge acc key_proof) )
464+
Block_map.empty !commit_ops
483465
in
466+
let proof_blocks = Block_map.merge proof_blocks !added_leaves in
484467
let block_stream =
485468
proof_blocks |> Block_map.entries |> Lwt_seq.of_list
486469
|> Lwt_seq.cons (new_commit_cid, commit_block)

pegasus/lib/user_store.ml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,15 @@ module Queries = struct
129129
~cid ~data
130130
131131
(* record storage *)
132+
let get_record_cid =
133+
[%rapper
134+
get_opt
135+
{sql| SELECT @CID{cid} FROM records WHERE path = %string{path} |sql}]
136+
137+
let get_all_record_cids =
138+
[%rapper get_many {sql| SELECT @string{path}, @CID{cid} FROM records |sql}]
139+
()
140+
132141
let get_record =
133142
[%rapper
134143
get_opt
@@ -391,6 +400,12 @@ let get_record t path : record option Lwt.t =
391400
>|= Option.map (fun (cid, data, since) ->
392401
{path; cid; value= Lex.of_cbor data; since} )
393402
403+
let get_record_cid t path : Cid.t option Lwt.t =
404+
Util.use_pool t.db @@ Queries.get_record_cid ~path
405+
406+
let get_all_record_cids t : (string * Cid.t) list Lwt.t =
407+
Util.use_pool t.db Queries.get_all_record_cids
408+
394409
let get_records_by_cids t cids : (Cid.t * Blob.t) list Lwt.t =
395410
if List.is_empty cids then Lwt.return []
396411
else

0 commit comments

Comments
 (0)