Skip to content

Commit bac8dcf

Browse files
authored
CP-307933: avoid serializing/deserializing database fields all the time (#6462)
Builds on top of #6461 Benchmark results are on individual commits. The most significant one: `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) ```
2 parents 418b610 + b9082a8 commit bac8dcf

31 files changed

+695
-188
lines changed

ocaml/database/database_server_main.ml

+2-1
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,9 @@ let remote_database_access_handler_v2 req bio =
3333
flush stdout ;
3434
raise e
3535

36+
open Xapi_database
3637
module Local_tests =
37-
Xapi_database.Database_test.Tests (Xapi_database.Db_cache_impl)
38+
Database_test.Tests (Db_interface_compat.OfCached (Db_cache_impl))
3839

3940
let schema = Test_schemas.schema
4041

ocaml/database/database_test.ml

+10-7
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,13 @@ functor
205205
let db =
206206
db
207207
|> add_row "bar" "bar:1"
208-
(Row.add 0L Db_names.ref (String "bar:1")
208+
(Row.add 0L Db_names.ref
209+
(Schema.Value.string "bar:1")
209210
(Row.add 0L "foos" (Set []) Row.empty)
210211
)
211212
|> add_row "foo" "foo:1"
212-
(Row.add 0L Db_names.ref (String "foo:1")
213+
(Row.add 0L Db_names.ref
214+
(Schema.Value.string "foo:1")
213215
(Row.add 0L "bars" (Set []) Row.empty)
214216
)
215217
|> set_field "foo" "foo:1" "bars" (add_to_set "bar:1" (Set []))
@@ -219,7 +221,7 @@ functor
219221
Table.find "bar:1" (TableSet.find "bar" (Database.tableset db))
220222
in
221223
let bar_foos = Row.find "foos" bar_1 in
222-
if bar_foos <> Set ["foo:1"] then
224+
if bar_foos <> Schema.Value.set ["foo:1"] then
223225
failwith_fmt
224226
"check_many_to_many: bar(bar:1).foos expected ('foo:1') got %s"
225227
(Schema.Value.marshal bar_foos) ;
@@ -235,13 +237,13 @@ functor
235237
failwith_fmt "check_many_to_many: bar(bar:1).foos expected () got %s"
236238
(Schema.Value.marshal bar_foos) ;
237239
(* add 'bar' to foo.bars *)
238-
let db = set_field "foo" "foo:1" "bars" (Set ["bar:1"]) db in
240+
let db = set_field "foo" "foo:1" "bars" (Schema.Value.set ["bar:1"]) db in
239241
(* check that 'bar.foos' includes 'foo' *)
240242
let bar_1 =
241243
Table.find "bar:1" (TableSet.find "bar" (Database.tableset db))
242244
in
243245
let bar_foos = Row.find "foos" bar_1 in
244-
if bar_foos <> Set ["foo:1"] then
246+
if bar_foos <> Schema.Value.set ["foo:1"] then
245247
failwith_fmt
246248
"check_many_to_many: bar(bar:1).foos expected ('foo:1') got %s - 2"
247249
(Schema.Value.marshal bar_foos) ;
@@ -269,8 +271,9 @@ functor
269271
let row = Db_cache_types.Table.find r table in
270272
let s =
271273
Db_cache_types.Row.fold_over_recent g
272-
(fun k _ (_, cached) acc ->
273-
Printf.sprintf "%s %s=%s" acc k cached
274+
(fun k _ cached acc ->
275+
Printf.sprintf "%s %s=%s" acc k
276+
(Schema.CachedValue.string_of cached)
274277
)
275278
row ""
276279
in

ocaml/database/db_backend.ml

+5-2
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,15 @@ let blow_away_non_persistent_fields (schema : Schema.t) db =
3838
(* Generate a new row given a table schema *)
3939
let row schema row : Row.t * int64 =
4040
Row.fold
41-
(fun name {Stat.created; modified; _} (v, _) (acc, max_upd) ->
41+
(fun name {Stat.created; modified; _} v (acc, max_upd) ->
4242
try
4343
let col = Schema.Table.find name schema in
4444
let empty = col.Schema.Column.empty in
4545
let v', modified' =
46-
if col.Schema.Column.persistent then (v, modified) else (empty, g)
46+
if col.Schema.Column.persistent then
47+
(Schema.CachedValue.value_of v, modified)
48+
else
49+
(empty, g)
4750
in
4851
( Row.update modified' name empty
4952
(fun _ -> v')

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_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

0 commit comments

Comments
 (0)