From 3e9fc3cb230a220e87f3d5611bc7e7491d2a34bf Mon Sep 17 00:00:00 2001 From: Marcus Granado Date: Thu, 18 Aug 2016 16:51:48 +0100 Subject: [PATCH 1/4] CAR-2259: use ocaml-sha instead of sha1sum during vm-export This saves an enormous amount of time because the sha1 hash can be computed without forking a new process for each 1MiB chunk of data. Signed-off-by: Marcus Granado --- ocaml/test/OMakefile | 2 +- ocaml/xapi/OMakefile | 2 +- ocaml/xapi/stream_vdi.ml | 7 ++----- opam | 1 + 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/ocaml/test/OMakefile b/ocaml/test/OMakefile index 777c996755d..53623d3afa2 100644 --- a/ocaml/test/OMakefile +++ b/ocaml/test/OMakefile @@ -1,6 +1,6 @@ OCAMLPACKS = oUnit sexpr xcp xmlm stunnel xml-light2 http-svr uuid \ netdev tapctl xenctrl xenctrlext xenstore-compat \ - pciutil oclock gzip sha1 xcp.network xcp.rrd xcp.storage \ + pciutil oclock gzip sha1 sha.sha1 xcp.network xcp.rrd xcp.storage \ xcp.xen xcp.memory tar tar.unix oPasswd xcp-inventory \ rrdd-plugin pci xapi-test-utils diff --git a/ocaml/xapi/OMakefile b/ocaml/xapi/OMakefile index 9e4101b0c2d..46951a3ea4c 100644 --- a/ocaml/xapi/OMakefile +++ b/ocaml/xapi/OMakefile @@ -1,6 +1,6 @@ OCAMLPACKS = oclock xml-light2 cdrom pciutil sexpr xcp stunnel \ http-svr netdev tapctl rpclib xenstore-compat \ - uuid gzip sha1 xcp.network xcp.rrd xcp.storage \ + uuid gzip sha1 sha.sha1 xcp.network xcp.rrd xcp.storage \ xcp.xen xcp.memory tar tar.unix oPasswd xcp-inventory \ rrdd-plugin pci diff --git a/ocaml/xapi/stream_vdi.ml b/ocaml/xapi/stream_vdi.ml index 151110e56ee..9ed7877c61e 100644 --- a/ocaml/xapi/stream_vdi.ml +++ b/ocaml/xapi/stream_vdi.ml @@ -94,11 +94,8 @@ let write_block ~__context filename buffer ofd len = let hdr = Tar_unix.Header.make filename (Int64.of_int len) in try - let csum = Sha1sum.sha1sum - (fun checksumfd -> - Tar_unix.write_block hdr (fun ofd -> Tar_unix.Archive.multicast_n_string buffer - [ ofd; checksumfd ] len) ofd - ) in + let csum = Sha1.to_hex (Sha1.string buffer) in + Tar_unix.write_block hdr (fun ofd -> Tar_unix.Archive.multicast_n_string buffer [ ofd ] len ) ofd; (* Write the checksum as a separate file *) let hdr' = Tar_unix.Header.make (filename ^ checksum_extension) (Int64.of_int (String.length csum)) in Tar_unix.write_block hdr' (fun ofd -> ignore(Unix.write ofd csum 0 (String.length csum))) ofd diff --git a/opam b/opam index ecb5a63ace8..cda68ac8169 100644 --- a/opam +++ b/opam @@ -32,6 +32,7 @@ depends: [ "opasswd" {>= "0.9.3"} "xapi-rrdd-plugin" "pci" {>= "0.2.0"} + "sha" ] depexts: [ [["centos"] ["pam-devel"]] From b05a0ca92fe11a4bd898e4f2c2ece9d1a8bc60a4 Mon Sep 17 00:00:00 2001 From: Marcus Granado Date: Mon, 15 Aug 2016 17:32:07 +0100 Subject: [PATCH 2/4] CAR-2259: reuse chunk buffer during vm-export This reduces the vm-export time in about 20%. Signed-off-by: Marcus Granado --- ocaml/xapi/stream_vdi.ml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/ocaml/xapi/stream_vdi.ml b/ocaml/xapi/stream_vdi.ml index 9ed7877c61e..ff43005fcea 100644 --- a/ocaml/xapi/stream_vdi.ml +++ b/ocaml/xapi/stream_vdi.ml @@ -123,6 +123,7 @@ let send_all refresh_session ofd ~__context rpc session_id (prefix_vdis: vdi lis with_open_vdi __context rpc session_id vdi_ref `RO [Unix.O_RDONLY] 0o644 (fun ifd -> + let reusable_buffer = String.make (Int64.to_int chunk_size) '\000' in (* NB. It used to be that chunks could be larger than a native int *) (* could handle, but this is no longer the case! Ensure all chunks *) @@ -150,7 +151,10 @@ let send_all refresh_session ofd ~__context rpc session_id (prefix_vdis: vdi lis (* no progress has been made *) stream_from (chunk_no + 1) offset end else begin - let buffer = String.make this_chunk '\000' in + let buffer = if (Int64.of_int this_chunk) = chunk_size + then reusable_buffer + else String.make this_chunk '\000' + in Unixext.really_read ifd buffer 0 this_chunk; if not (Zerocheck.is_all_zeros buffer this_chunk) || first_or_last then begin last_transmission_time := now; From e2b144294ef12fb167c459c85f80cf0ae93ecfba Mon Sep 17 00:00:00 2001 From: Marcus Granado Date: Wed, 17 Aug 2016 13:53:15 +0100 Subject: [PATCH 3/4] CAR-2259: use ocaml-sha instead of sha1sum during vm-import By using really_read, we can use Tar_unix.multicast_n_string instead of Tar_unix.multicast_n and at the same time extract the buffer from inside Tar_unix.multicast_n_string, so that it can be reused to improve performance. The exception behaviour is the same: really_read also checks if Unix.read returns 0 and raises the same End_of_file exception in this case, compare https://github.com/xapi-project/xen-api-libs/blob/master/stdext/unixext.ml#L426 and https://github.com/mirage/ocaml-tar/blob/master/lib/tar_unix.ml#L123 Signed-off-by: Marcus Granado --- ocaml/xapi/stream_vdi.ml | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/ocaml/xapi/stream_vdi.ml b/ocaml/xapi/stream_vdi.ml index ff43005fcea..dbc2b23ae90 100644 --- a/ocaml/xapi/stream_vdi.ml +++ b/ocaml/xapi/stream_vdi.ml @@ -262,10 +262,11 @@ let recv_all refresh_session ifd (__context:Context.t) rpc session_id vsn force done end; - let csum = Sha1sum.sha1sum - (fun checksumfd -> - Tar_unix.Archive.multicast_n ifd [ ofd; checksumfd ] length) in - + let buffer = String.make (Int64.to_int length) '\000' in + Unixext.really_read ifd buffer 0 (Int64.to_int length); + Tar_unix.Archive.multicast_n_string buffer [ ofd ] (Int64.to_int length); + let csum = Sha1.to_hex (Sha1.string buffer) in + checksum_table := (file_name, csum) :: !checksum_table; Tar_unix.Archive.skip ifd (Tar_unix.Header.compute_zero_padding_length hdr); From 47c46d4f73a4ef0a46976914120eb4a7f8d1de1d Mon Sep 17 00:00:00 2001 From: Marcus Granado Date: Wed, 17 Aug 2016 15:04:20 +0100 Subject: [PATCH 4/4] CAR-2259: reuse chunk buffer during vm-import This reduces the vm-import time slightly as in vm-export. Signed-off-by: Marcus Granado --- ocaml/xapi/stream_vdi.ml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/ocaml/xapi/stream_vdi.ml b/ocaml/xapi/stream_vdi.ml index dbc2b23ae90..f5bd95d7706 100644 --- a/ocaml/xapi/stream_vdi.ml +++ b/ocaml/xapi/stream_vdi.ml @@ -215,6 +215,8 @@ let recv_all refresh_session ifd (__context:Context.t) rpc session_id vsn force with_open_vdi __context rpc session_id vdi_ref `RW [Unix.O_WRONLY] 0o644 (fun ofd -> + let reusable_buffer = String.make (Int64.to_int chunk_size) '\000' in + let rec stream_from (last_suffix: string) (offset: int64) = refresh_session (); @@ -262,7 +264,10 @@ let recv_all refresh_session ifd (__context:Context.t) rpc session_id vsn force done end; - let buffer = String.make (Int64.to_int length) '\000' in + let buffer = if length = chunk_size + then reusable_buffer + else String.make (Int64.to_int length) '\000' + in Unixext.really_read ifd buffer 0 (Int64.to_int length); Tar_unix.Archive.multicast_n_string buffer [ ofd ] (Int64.to_int length); let csum = Sha1.to_hex (Sha1.string buffer) in