Skip to content

Commit 9760637

Browse files
committed
CP-307933: Start using DB_ACCESS2
`ministat` confirms a speedup: ``` Db.Pool.get_all_records : N Min Max Median Avg Stddev x 432 54115.256 493532.78 56048.42 57937.384 24117.68 + 524 22642.778 333257.36 23595.495 24679.258 15206.708 Difference at 95.0% confidence -33258.1 +/- 2513.99 -57.4036% +/- 2.90374% (Student's t, pooled s = 19737.2) >>>> Db.VM.set_NVRAM : N Min Max Median Avg Stddev x 132 36794 2355369.4 1095736.6 1107222.1 298247.5 + 168 49167.417 1485278.1 678231.31 685636.89 161480.92 Difference at 95.0% confidence -421585 +/- 52835.6 -38.0759% +/- 3.54275% (Student's t, pooled s = 231767) ``` Signed-off-by: Edwin Török <[email protected]>
1 parent 4912c21 commit 9760637

File tree

10 files changed

+146
-33
lines changed

10 files changed

+146
-33
lines changed

ocaml/database/db_cache.ml

+8-6
Original file line numberDiff line numberDiff line change
@@ -19,30 +19,32 @@ module D = Debug.Make (struct let name = "db_cache" end)
1919
open D
2020

2121
(** Masters will use this to modify the in-memory cache directly *)
22-
module Local_db : DB_ACCESS = Db_interface_compat.OfCached (Db_cache_impl)
22+
module Local_db : DB_ACCESS2 = Db_cache_impl
2323

2424
(** Slaves will use this to call the master by XMLRPC *)
25-
module Remote_db : DB_ACCESS = Db_rpc_client_v1.Make (struct
25+
module Remote_db : DB_ACCESS2 =
26+
Db_interface_compat.OfCompat (Db_rpc_client_v1.Make (struct
2627
let initialise () =
2728
ignore (Master_connection.start_master_connection_watchdog ()) ;
2829
ignore (Master_connection.open_secure_connection ())
2930

3031
let rpc request = Master_connection.execute_remote_fn request
31-
end)
32+
end))
3233

3334
let get = function
3435
| Db_ref.In_memory _ ->
35-
(module Local_db : DB_ACCESS)
36+
(module Local_db : DB_ACCESS2)
3637
| Db_ref.Remote ->
37-
(module Remote_db : DB_ACCESS)
38+
(module Remote_db : DB_ACCESS2)
3839

3940
let lifecycle_state_of ~obj fld =
4041
let open Datamodel in
4142
let {fld_states; _} = StringMap.find obj all_lifecycles in
4243
StringMap.find fld fld_states
4344

45+
module DB = Db_interface_compat.OfCached (Local_db)
46+
4447
let apply_delta_to_cache entry db_ref =
45-
let module DB : DB_ACCESS = Local_db in
4648
match entry with
4749
| Redo_log.CreateRow (tblname, objref, kvs) ->
4850
debug "Redoing create_row %s (%s)" tblname objref ;

ocaml/database/db_cache.mli

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,6 @@
1212
* GNU Lesser General Public License for more details.
1313
*)
1414

15-
val get : Db_ref.t -> (module Db_interface.DB_ACCESS)
15+
val get : Db_ref.t -> (module Db_interface.DB_ACCESS2)
1616

1717
val apply_delta_to_cache : Redo_log.t -> Db_ref.t -> unit

ocaml/idl/ocaml_backend/gen_api.ml

+2
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,9 @@ let gen_db_actions _config highapi =
484484
(toposort_types highapi only_records)
485485
; (* NB record types are ignored by dm_to_string and string_to_dm *)
486486
O.Module.strings_of (dm_to_string all_types_in_db)
487+
; O.Module.strings_of (dm_to_field all_types_in_db)
487488
; O.Module.strings_of (string_to_dm all_types_in_db)
489+
; O.Module.strings_of (field_to_dm all_types_in_db)
488490
; O.Module.strings_of (db_action highapi_in_db)
489491
]
490492
@ List.map O.Module.strings_of (Gen_db_check.all highapi_in_db)

ocaml/idl/ocaml_backend/gen_db_actions.ml

+118-17
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,12 @@ open DT
2525
(* Names of the modules we're going to generate (use these to prevent typos) *)
2626
let _dm_to_string = "DM_to_String"
2727

28+
let _dm_to_field = "DM_to_Field"
29+
2830
let _string_to_dm = "String_to_DM"
2931

32+
let _field_to_dm = "Field_to_DM"
33+
3034
let _db_action = "DB_Action"
3135

3236
let _db_defaults = "DB_DEFAULTS"
@@ -109,6 +113,44 @@ let dm_to_string tys : O.Module.t =
109113
~elements:(List.map (fun ty -> O.Module.Let (ty_fun ty)) tys)
110114
()
111115

116+
let dm_to_field tys : O.Module.t =
117+
let tys = List.filter type_marshalled_in_db tys in
118+
(* For every type, we create a single function *)
119+
let ty_fun ty =
120+
let body =
121+
match ty with
122+
| DT.Map (String, String) ->
123+
"Schema.Value.pairs"
124+
| DT.Map (key, value) ->
125+
Printf.sprintf
126+
"fun s -> s |> List.map (fun (k, v) -> %s.%s k, %s.%s v) |> \
127+
Schema.Value.pairs"
128+
_dm_to_string (OU.alias_of_ty key) _dm_to_string
129+
(OU.alias_of_ty value)
130+
| DT.Set String ->
131+
"Schema.Value.set"
132+
| DT.Set ty ->
133+
Printf.sprintf "fun s -> s |> List.map %s.%s |> Schema.Value.set"
134+
_dm_to_string (OU.alias_of_ty ty)
135+
| DT.String ->
136+
"Schema.Value.string"
137+
| _ ->
138+
Printf.sprintf "fun s -> s |> %s.%s |> Schema.Value.string"
139+
_dm_to_string (OU.alias_of_ty ty)
140+
in
141+
O.Let.make ~name:(OU.alias_of_ty ty) ~params:[] ~ty:"Db_interface.field_in"
142+
~body:[body] ()
143+
in
144+
O.Module.make ~name:_dm_to_field
145+
~preamble:
146+
[
147+
"exception StringEnumTypeError of string"
148+
; "exception DateTimeError of string"
149+
]
150+
~letrec:true
151+
~elements:(List.map (fun ty -> O.Module.Let (ty_fun ty)) tys)
152+
()
153+
112154
(** Generate a module of string to datamodel type unmarshalling functions *)
113155
let string_to_dm tys : O.Module.t =
114156
let tys = List.filter type_marshalled_in_db tys in
@@ -171,6 +213,53 @@ let string_to_dm tys : O.Module.t =
171213
~elements:(List.map (fun ty -> O.Module.Let (ty_fun ty)) tys)
172214
()
173215

216+
let field_to_dm tys : O.Module.t =
217+
let tys = List.filter type_marshalled_in_db tys in
218+
(* For every type, we create a single function *)
219+
let ty_fun ty =
220+
let name = OU.alias_of_ty ty in
221+
let body =
222+
match ty with
223+
| DT.Map (key, value) ->
224+
let conv =
225+
match (key, value) with
226+
| DT.String, DT.String ->
227+
""
228+
| _ ->
229+
Printf.sprintf " |> List.map (fun (k, v) -> %s.%s k, %s.%s v)"
230+
_string_to_dm (OU.alias_of_ty key) _string_to_dm
231+
(OU.alias_of_ty value)
232+
in
233+
"fun s -> s |> Schema.CachedValue.maybe_unmarshal Schema.Type.Pairs \
234+
|> Schema.CachedValue.value_of |> Schema.Value.Unsafe_cast.pairs"
235+
^ conv
236+
| DT.Set ty ->
237+
let conv =
238+
match ty with
239+
| DT.String ->
240+
""
241+
| _ ->
242+
Printf.sprintf " |> List.map %s.%s" _string_to_dm
243+
(OU.alias_of_ty ty)
244+
in
245+
"fun s -> s |> Schema.CachedValue.maybe_unmarshal Schema.Type.Set |> \
246+
Schema.CachedValue.value_of |> Schema.Value.Unsafe_cast.set"
247+
^ conv
248+
| DT.String ->
249+
"fun s -> s |> Schema.CachedValue.maybe_unmarshal Schema.Type.String \
250+
|> Schema.CachedValue.value_of |> Schema.Value.Unsafe_cast.string"
251+
| _ ->
252+
Printf.sprintf "fun f -> f |> Schema.CachedValue.string_of |> %s.%s"
253+
_string_to_dm name
254+
in
255+
O.Let.make ~name ~params:[] ~ty:(OU.alias_of_ty ty) ~body:[body] ()
256+
in
257+
O.Module.make ~name:_field_to_dm
258+
~preamble:["exception StringEnumTypeError of string"]
259+
~letrec:true
260+
~elements:(List.map (fun ty -> O.Module.Let (ty_fun ty)) tys)
261+
()
262+
174263
(** True if a field is actually in this table, false if stored elsewhere
175264
(ie Set(Ref _) are stored in foreign tables *)
176265
let field_in_this_table = function
@@ -283,7 +372,7 @@ let open_db_module =
283372
[
284373
"let __t = Context.database_of __context in"
285374
; "let module DB = (val (Xapi_database.Db_cache.get __t) : \
286-
Xapi_database.Db_interface.DB_ACCESS) in"
375+
Xapi_database.Db_interface.DB_ACCESS2) in"
287376
]
288377

289378
let db_action api : O.Module.t =
@@ -331,7 +420,7 @@ let db_action api : O.Module.t =
331420
let ty_alias = OU.alias_of_ty f.DT.ty in
332421
let accessor = "find_regular" in
333422
let field_name = Escaping.escape_id f.full_name in
334-
Printf.sprintf {|%s.%s (%s "%s")|} _string_to_dm ty_alias accessor
423+
Printf.sprintf {|%s.%s (%s "%s")|} _field_to_dm ty_alias accessor
335424
field_name
336425
in
337426
let make_field f =
@@ -433,8 +522,13 @@ let db_action api : O.Module.t =
433522
let to_string arg =
434523
let binding = O.string_of_param arg in
435524
let converter = O.type_of_param arg in
436-
Printf.sprintf "let %s = %s.%s %s in" binding _dm_to_string converter
437-
binding
525+
Printf.sprintf "let %s = %s.%s %s in" binding
526+
( if binding = Client._self || binding = "ref" then
527+
_dm_to_string
528+
else
529+
_dm_to_field
530+
)
531+
converter binding
438532
in
439533
let body =
440534
match tag with
@@ -445,37 +539,38 @@ let db_action api : O.Module.t =
445539
(Escaping.escape_id fld.DT.full_name)
446540
| FromField (Getter, {DT.ty; full_name; _}) ->
447541
Printf.sprintf "%s.%s (DB.read_field __t \"%s\" \"%s\" %s)"
448-
_string_to_dm (OU.alias_of_ty ty)
542+
_field_to_dm (OU.alias_of_ty ty)
449543
(Escaping.escape_obj obj.DT.name)
450544
(Escaping.escape_id full_name)
451545
Client._self
452546
| FromField (Add, {DT.ty= DT.Map (_, _); full_name; _}) ->
453547
Printf.sprintf
454-
"DB.process_structured_field __t (%s,%s) \"%s\" \"%s\" %s \
455-
AddMapLegacy"
548+
"DB.process_structured_field __t (Schema.Value.marshal %s, \
549+
Schema.Value.marshal %s) \"%s\" \"%s\" %s AddMapLegacy"
456550
Client._key Client._value
457551
(Escaping.escape_obj obj.DT.name)
458552
(Escaping.escape_id full_name)
459553
Client._self
460554
| FromField (Add, {DT.ty= DT.Set _; full_name; _}) ->
461555
Printf.sprintf
462-
"DB.process_structured_field __t (%s,\"\") \"%s\" \"%s\" %s AddSet"
556+
"DB.process_structured_field __t (Schema.Value.marshal %s,\"\") \
557+
\"%s\" \"%s\" %s AddSet"
463558
Client._value
464559
(Escaping.escape_obj obj.DT.name)
465560
(Escaping.escape_id full_name)
466561
Client._self
467562
| FromField (Remove, {DT.ty= DT.Map (_, _); full_name; _}) ->
468563
Printf.sprintf
469-
"DB.process_structured_field __t (%s,\"\") \"%s\" \"%s\" %s \
470-
RemoveMap"
564+
"DB.process_structured_field __t (Schema.Value.marshal %s,\"\") \
565+
\"%s\" \"%s\" %s RemoveMap"
471566
Client._key
472567
(Escaping.escape_obj obj.DT.name)
473568
(Escaping.escape_id full_name)
474569
Client._self
475570
| FromField (Remove, {DT.ty= DT.Set _; full_name; _}) ->
476571
Printf.sprintf
477-
"DB.process_structured_field __t (%s,\"\") \"%s\" \"%s\" %s \
478-
RemoveSet"
572+
"DB.process_structured_field __t (Schema.Value.marshal %s,\"\") \
573+
\"%s\" \"%s\" %s RemoveSet"
479574
Client._value
480575
(Escaping.escape_obj obj.DT.name)
481576
(Escaping.escape_id full_name)
@@ -517,7 +612,9 @@ let db_action api : O.Module.t =
517612
match (x.msg_params, x.msg_result) with
518613
| [{param_name= name; _}], Some (result_ty, _) ->
519614
let query =
520-
Printf.sprintf "DB.db_get_by_uuid __t \"%s\" %s"
615+
Printf.sprintf
616+
"DB.db_get_by_uuid __t \"%s\" (Schema.Value.Unsafe_cast.string \
617+
%s)"
521618
(Escaping.escape_obj obj.DT.name)
522619
(OU.escape name)
523620
in
@@ -530,7 +627,7 @@ let db_action api : O.Module.t =
530627
^ ")"
531628
in
532629
let query_opt =
533-
Printf.sprintf "DB.db_get_by_uuid_opt __t \"%s\" %s"
630+
Printf.sprintf "DB.db_get_by_uuid_opt __t \"%s\" (%s)"
534631
(Escaping.escape_obj obj.DT.name)
535632
(OU.escape name)
536633
in
@@ -555,7 +652,9 @@ let db_action api : O.Module.t =
555652
match (x.msg_params, x.msg_result) with
556653
| [{param_name= name; _}], Some (Set result_ty, _) ->
557654
let query =
558-
Printf.sprintf "DB.db_get_by_name_label __t \"%s\" %s"
655+
Printf.sprintf
656+
"DB.db_get_by_name_label __t \"%s\" \
657+
(Schema.Value.Unsafe_cast.string %s)"
559658
(Escaping.escape_obj obj.DT.name)
560659
(OU.escape name)
561660
in
@@ -606,13 +705,15 @@ let db_action api : O.Module.t =
606705
| FromObject GetAllRecordsWhere ->
607706
String.concat "\n"
608707
[
609-
"let expr' = Xapi_database.Db_filter.expr_of_string expr in"
708+
"let expr' = Xapi_database.Db_filter.expr_of_string \
709+
(Schema.Value.Unsafe_cast.string expr) in"
610710
; "get_records_where ~" ^ Gen_common.context ^ " ~expr:expr'"
611711
]
612712
| FromObject GetAllWhere ->
613713
String.concat "\n"
614714
[
615-
"let expr' = Xapi_database.Db_filter.expr_of_string expr in"
715+
"let expr' = Xapi_database.Db_filter.expr_of_string \
716+
(Schema.Value.Unsafe_cast.string expr) in"
616717
; "get_refs_where ~" ^ Gen_common.context ^ " ~expr:expr'"
617718
]
618719
| _ ->

ocaml/xapi/console.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ let console_of_request __context req =
185185
let db = Context.database_of __context in
186186
let is_vm, _ =
187187
let module DB =
188-
(val Xapi_database.Db_cache.get db : Xapi_database.Db_interface.DB_ACCESS)
188+
(val Xapi_database.Db_cache.get db : Xapi_database.Db_interface.DB_ACCESS2)
189189
in
190190
match DB.get_table_from_ref db _ref with
191191
| Some c when c = Db_names.vm ->

ocaml/xapi/db.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,5 @@ let is_valid_ref __context r =
2323
false
2424
else
2525
let t = Context.database_of __context in
26-
let module DB = (val Db_cache.get t : Db_interface.DB_ACCESS) in
26+
let module DB = (val Db_cache.get t : Db_interface.DB_ACCESS2) in
2727
DB.is_valid_ref t (Ref.string_of r)

ocaml/xapi/db_gc_util.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ let gc_connector ~__context get_all get_record valid_ref1 valid_ref2
2828
delete_record =
2929
let db = Context.database_of __context in
3030
let module DB =
31-
(val Xapi_database.Db_cache.get db : Xapi_database.Db_interface.DB_ACCESS)
31+
(val Xapi_database.Db_cache.get db : Xapi_database.Db_interface.DB_ACCESS2)
3232
in
3333
let all_refs = get_all ~__context in
3434
let do_gc ref =

ocaml/xapi/eventgen.ml

+1-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ open Xapi_database.Db_action_helper
107107
let is_valid_ref db = function
108108
| Schema.Value.String r -> (
109109
try
110-
ignore (Database.table_of_ref r db) ;
110+
ignore (Database.table_of_ref (r :> string) db) ;
111111
true
112112
with _ -> false
113113
)

ocaml/xapi/helpers.ml

+9-3
Original file line numberDiff line numberDiff line change
@@ -1349,13 +1349,19 @@ let vm_to_string __context vm =
13491349
raise (Api_errors.Server_error (Api_errors.invalid_value, [str])) ;
13501350
let t = Context.database_of __context in
13511351
let module DB =
1352-
(val Xapi_database.Db_cache.get t : Xapi_database.Db_interface.DB_ACCESS)
1352+
(val Xapi_database.Db_cache.get t : Xapi_database.Db_interface.DB_ACCESS2)
13531353
in
1354-
let fields = fst (DB.read_record t Db_names.vm str) in
1354+
let fields, _ = DB.read_record t Db_names.vm str in
13551355
let sexpr =
13561356
SExpr.Node
13571357
(List.map
1358-
(fun (key, value) -> SExpr.Node [SExpr.String key; SExpr.String value])
1358+
(fun (key, value) ->
1359+
SExpr.Node
1360+
[
1361+
SExpr.String key
1362+
; SExpr.String (Schema.CachedValue.string_of value)
1363+
]
1364+
)
13591365
fields
13601366
)
13611367
in

ocaml/xapi/xapi_vm_snapshot.ml

+4-2
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,10 @@ let copy_vm_fields ~__context ~metadata ~dst ~do_not_copy ~overrides =
167167
debug "copying metadata into %s" (Ref.string_of dst) ;
168168
let db = Context.database_of __context in
169169
let module DB =
170-
(val Xapi_database.Db_cache.get db : Xapi_database.Db_interface.DB_ACCESS)
171-
in
170+
Xapi_database.Db_interface_compat.OfCached
171+
(( val Xapi_database.Db_cache.get db
172+
: Xapi_database.Db_interface.DB_ACCESS2
173+
)) in
172174
List.iter
173175
(fun (key, value) ->
174176
let value = Option.value ~default:value (List.assoc_opt key overrides) in

0 commit comments

Comments
 (0)