From patchwork Mon Aug 17 18:39:49 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719079 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id CD5FA13A4 for ; Mon, 17 Aug 2020 18:40:58 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id A9DEA204EC for ; Mon, 17 Aug 2020 18:40:58 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="afxhTm9m" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org A9DEA204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3h-0006MV-2H; Mon, 17 Aug 2020 18:40:37 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3f-0006K5-KS for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:35 +0000 X-Inumbo-ID: ff0bf0b5-983a-40c0-ae17-e360a2ab2589 Received: from esa5.hc3370-68.iphmx.com (unknown [216.71.155.168]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id ff0bf0b5-983a-40c0-ae17-e360a2ab2589; Mon, 17 Aug 2020 18:40:30 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689630; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=SMCBsmOzak2flXbv7Zo/YlQyvKHgExmZi0mtL3kNGOc=; b=afxhTm9mWzEx2d89NiJyAXts3/Z8KQOOcGflEgWvKGsMvjbDu0k26oLQ jK3GiU8cjeU+aCibj883K1jpsLpQTWVzXdo0uNEKWTn71lChujJrSyxBO igVfAtu5trH1J8O+IYxCheao2awtWZGZMtigcu6X9SlKZvweZbKjklLWr I=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: mhKFR8RnMJvc76G+UaDC07GmXiAY1GpLIXajbdGiZuqySt0lUcrTjJt3TWIck+J5GXZ6l12+Mb d3ItWNEUHP414igvJAUPSymxFE8RQe7l5VCmgvEd67ypqlykwdvR9t2qnu2KdjIwVmCdtJfXeB SfSTRU0CzM2fsG1OfbAaBSe/NGP8eJRV20prGm4h+auBL4pkfb+I27HaEa5z18JJqr2Y/bBQQw w93NtqG3zWZQFA4VMoWx33Y/JkOrNO4bbs0ocs289rr/6YcvHy7xactmtkAYQH8EESOs9+d3xm 6Ow= X-SBRS: 2.7 X-MesageID: 24867841 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24867841" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 1/6] tools/ocaml/libs/xc: Fix ambiguous documentation comment Date: Mon, 17 Aug 2020 19:39:49 +0100 Message-ID: <2ed1526e3f369f843871fcf166bf3e14ced36dfb.1597689211.git.edvin.torok@citrix.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Signed-off-by: Edwin Török --- tools/ocaml/libs/xc/xenctrl.mli | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tools/ocaml/libs/xc/xenctrl.mli b/tools/ocaml/libs/xc/xenctrl.mli index 26ec7e59b1..f7f6ec570d 100644 --- a/tools/ocaml/libs/xc/xenctrl.mli +++ b/tools/ocaml/libs/xc/xenctrl.mli @@ -132,8 +132,10 @@ external interface_close : handle -> unit = "stub_xc_interface_close" * interface_open and interface_close or with_intf although mixing both * is possible *) val with_intf : (handle -> 'a) -> 'a + (** [get_handle] returns the global handle used by [with_intf] *) val get_handle: unit -> handle option + (** [close handle] closes the handle maintained by [with_intf]. This * should only be closed before process exit. It must not be called from * a function called directly or indirectly by with_intf as this From patchwork Mon Aug 17 18:39:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719085 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 5652F109B for ; Mon, 17 Aug 2020 18:42:03 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 30AA1204EC for ; Mon, 17 Aug 2020 18:42:03 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="h5vowcE3" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 30AA1204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3l-0006Ou-MS; Mon, 17 Aug 2020 18:40:41 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3k-0006K5-KR for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:40 +0000 X-Inumbo-ID: fcc229d5-ca6f-41e9-84e3-c5de8102445d Received: from esa5.hc3370-68.iphmx.com (unknown [216.71.155.168]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id fcc229d5-ca6f-41e9-84e3-c5de8102445d; Mon, 17 Aug 2020 18:40:31 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689631; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=YT4HghR0/mQiuB+0ZHbTT8P7/FFGJ4MPWIY1ryiFPUA=; b=h5vowcE3AmbbboBk0fw8JSuGG4cfvyjmQvx6wUzpEiJaTCfoQOBs+mpX F1YhOiEfWXka4Tykjq8mXoh0+ALKILMNvsJ2p3HHZqv41wmkVxWdchTJY SNk5QDUYp8KFO3rKM80jtFYxP6RVMfb1Z4i7TveU2LxosE7dO7HQOP+WL c=; Authentication-Results: esa5.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: VDHxz6P3BjGSpSDtzFGRuqkP0gIMNM1QvMuADnRgT0xS5/FZHGlhxDURPyxgXOE+yfKZCD0oi9 7mC1CqoeuvuQ/NLxe2mjBsPlJ+COekzzi6khj4ADUo8k92XQ0lRWHLEBQp5lLP/eiz4W4wEyRu AJQFlRgsvMtmh2A7n32oTazJo0Vl/DmOQBbtmd6vSP9SNKyKH8bDFM+T48J+kAJRGK0o6Iabm7 kxxvHVMjT5J4sECPWDf1Gy3E4ThRo9Y+CVMPM65KPiqsRTbWP+v1d9K1Oz9/+hYPJCFgCM5b1e FJw= X-SBRS: 2.7 X-MesageID: 24867844 X-Ironport-Server: esa5.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24867844" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 2/6] tools/ocaml/xenstored: fix deprecation warning Date: Mon, 17 Aug 2020 19:39:50 +0100 Message-ID: <334f84f96ccd4adbbb84b6c01b690c9118fbd613.1597689211.git.edvin.torok@citrix.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" ``` File "xenstored/disk.ml", line 33, characters 9-23: 33 | let c = Char.lowercase c in ^^^^^^^^^^^^^^ (alert deprecated): Stdlib.Char.lowercase Use Char.lowercase_ascii instead. ``` Signed-off-by: Edwin Török --- tools/ocaml/xenstored/disk.ml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/ocaml/xenstored/disk.ml b/tools/ocaml/xenstored/disk.ml index 4739967b61..1ca0e2a95e 100644 --- a/tools/ocaml/xenstored/disk.ml +++ b/tools/ocaml/xenstored/disk.ml @@ -30,7 +30,7 @@ let undec c = | _ -> raise (Failure "undecify") let unhex c = - let c = Char.lowercase c in + let c = Char.lowercase_ascii c in match c with | '0' .. '9' -> (Char.code c) - (Char.code '0') | 'a' .. 'f' -> (Char.code c) - (Char.code 'a') + 10 From patchwork Mon Aug 17 18:39:51 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719089 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 7D5C613A4 for ; Mon, 17 Aug 2020 18:42:12 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 58D92204EC for ; Mon, 17 Aug 2020 18:42:12 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="MWE82+IN" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 58D92204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3X-0006KA-2k; Mon, 17 Aug 2020 18:40:27 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3V-0006K5-Qm for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:25 +0000 X-Inumbo-ID: 9bf707cf-6c98-468e-96b8-490889284081 Received: from esa3.hc3370-68.iphmx.com (unknown [216.71.145.155]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 9bf707cf-6c98-468e-96b8-490889284081; Mon, 17 Aug 2020 18:40:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689625; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=r8ehkDegyME6bv9QcJZhEj/RknOtin3F+AcEEK7wbxw=; b=MWE82+INTaJBnRbTe978ZL/23XmkRBS+yJhMWA3U0OBFDtTYOvKRUkwZ AiSvqQ6dE43JrhvYQMNkI+ypILIU+vcNOaKve3vke8MkwMZd8BZ80jjRq VEQ5r3G5rzI8TobVf26w6WsRPxDOJDcRn9K7dz0tT6WnwRbb1dHZ/AOFt E=; Authentication-Results: esa3.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: GEKFl1RY6r9S2WxbaO4GuKaiven2flbz0LjsJ+xRqOL7TeQ1/Mqt9PWyOlFhz8ite47J6VEhBU QToFiF1nv++vaET6ILU6LU1e318XVrDBWGTPWAerbQkSR8uECzQlW+kWaYE8Fjnq05vKaZyuEz aUlN9I8kEodrGTQBHix42ihhqh75wCY2pncrKfhOlfgyCthuRmrSqHPjceW2XEzdUE9jPvD504 pa+opujcYcKhdC4O4svX7iR6BY/RyPbqvjY8/lMminVmGUyxFQOHOv/q0+mBKLBSJu2w7fwN+d fRA= X-SBRS: 2.7 X-MesageID: 24692782 X-Ironport-Server: esa3.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24692782" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 3/6] tools/ocaml/xenstored: replace hand rolled GC with weak GC references Date: Mon, 17 Aug 2020 19:39:51 +0100 Message-ID: <174a56a8d6541e3f908d227c493c52b1fdeb9287.1597689211.git.edvin.torok@citrix.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" The code here is attempting to reduce memory usage by sharing common substrings in the tree: it replaces strings with ints, and keeps a string->int map that gets manually garbage collected using a hand-rolled mark and sweep algorithm. This is unnecessary: OCaml already has a mark-and-sweep Garbage Collector runtime, and sharing of common strings in tree nodes can be achieved through Weak references: if the string hasn't been seen yet it gets added to the Weak reference table, and if it has we use the entry from the table instead, thus storing a string only once. When the string is no longer referenced OCaml's GC will drop it from the weak table: there is no need to manually do a mark-and-sweep, or to tell OCaml when to drop it. Signed-off-by: Edwin Török --- tools/ocaml/xenstored/connection.ml | 3 -- tools/ocaml/xenstored/history.ml | 14 ------ tools/ocaml/xenstored/store.ml | 11 ++--- tools/ocaml/xenstored/symbol.ml | 68 ++++++----------------------- tools/ocaml/xenstored/symbol.mli | 21 ++------- tools/ocaml/xenstored/xenstored.ml | 16 +------ 6 files changed, 24 insertions(+), 109 deletions(-) diff --git a/tools/ocaml/xenstored/connection.ml b/tools/ocaml/xenstored/connection.ml index 24750ada43..aa6dd95501 100644 --- a/tools/ocaml/xenstored/connection.ml +++ b/tools/ocaml/xenstored/connection.ml @@ -271,9 +271,6 @@ let has_more_work con = let incr_ops con = con.stat_nb_ops <- con.stat_nb_ops + 1 -let mark_symbols con = - Hashtbl.iter (fun _ t -> Store.mark_symbols (Transaction.get_store t)) con.transactions - let stats con = Hashtbl.length con.watches, con.stat_nb_ops diff --git a/tools/ocaml/xenstored/history.ml b/tools/ocaml/xenstored/history.ml index f39565bff5..029802bd15 100644 --- a/tools/ocaml/xenstored/history.ml +++ b/tools/ocaml/xenstored/history.ml @@ -22,20 +22,6 @@ type history_record = { let history : history_record list ref = ref [] -(* Called from periodic_ops to ensure we don't discard symbols that are still needed. *) -(* There is scope for optimisation here, since in consecutive commits one commit's `after` - * is the same thing as the next commit's `before`, but not all commits in history are - * consecutive. *) -let mark_symbols () = - (* There are gaps where dom0's commits are missing. Otherwise we could assume that - * each element's `before` is the same thing as the next element's `after` - * since the next element is the previous commit *) - List.iter (fun hist_rec -> - Store.mark_symbols hist_rec.before; - Store.mark_symbols hist_rec.after; - ) - !history - (* Keep only enough commit-history to protect the running transactions that we are still tracking *) (* There is scope for optimisation here, replacing List.filter with something more efficient, * probably on a different list-like structure. *) diff --git a/tools/ocaml/xenstored/store.ml b/tools/ocaml/xenstored/store.ml index f299ec6461..45659a23ee 100644 --- a/tools/ocaml/xenstored/store.ml +++ b/tools/ocaml/xenstored/store.ml @@ -46,18 +46,18 @@ let add_child node child = let exists node childname = let childname = Symbol.of_string childname in - List.exists (fun n -> n.name = childname) node.children + List.exists (fun n -> Symbol.equal n.name childname) node.children let find node childname = let childname = Symbol.of_string childname in - List.find (fun n -> n.name = childname) node.children + List.find (fun n -> Symbol.equal n.name childname) node.children let replace_child node child nchild = (* this is the on-steroid version of the filter one-replace one *) let rec replace_one_in_list l = match l with | [] -> [] - | h :: tl when h.name = child.name -> nchild :: tl + | h :: tl when Symbol.equal h.name child.name -> nchild :: tl | h :: tl -> h :: replace_one_in_list tl in { node with children = (replace_one_in_list node.children) } @@ -67,7 +67,7 @@ let del_childname node childname = let rec delete_one_in_list l = match l with | [] -> raise Not_found - | h :: tl when h.name = sym -> tl + | h :: tl when Symbol.equal h.name sym -> tl | h :: tl -> h :: delete_one_in_list tl in { node with children = (delete_one_in_list node.children) } @@ -463,9 +463,6 @@ let copy store = { quota = Quota.copy store.quota; } -let mark_symbols store = - Node.recurse (fun node -> Symbol.mark_as_used node.Node.name) store.root - let incr_transaction_coalesce store = store.stat_transaction_coalesce <- store.stat_transaction_coalesce + 1 let incr_transaction_abort store = diff --git a/tools/ocaml/xenstored/symbol.ml b/tools/ocaml/xenstored/symbol.ml index 4420c6a4d7..dac6f9f819 100644 --- a/tools/ocaml/xenstored/symbol.ml +++ b/tools/ocaml/xenstored/symbol.ml @@ -14,63 +14,23 @@ * GNU Lesser General Public License for more details. *) -type t = int +module WeakTable = Weak.Make(struct + type t = string + let equal = String.equal + let hash = Hashtbl.hash +end) -type 'a record = { data: 'a; mutable garbage: bool } -let int_string_tbl : (int,string record) Hashtbl.t = Hashtbl.create 1024 -let string_int_tbl : (string,int) Hashtbl.t = Hashtbl.create 1024 +type t = string -let created_counter = ref 0 -let used_counter = ref 0 +let tbl = WeakTable.create 1024 -let count = ref 0 -let rec fresh () = - if Hashtbl.mem int_string_tbl !count - then begin - incr count; - fresh () - end else - !count +let of_string s = WeakTable.merge tbl s +let to_string s = s -let new_record v = { data=v; garbage=false } - -let of_string name = - if Hashtbl.mem string_int_tbl name - then begin - incr used_counter; - Hashtbl.find string_int_tbl name - end else begin - let i = fresh () in - incr created_counter; - Hashtbl.add string_int_tbl name i; - Hashtbl.add int_string_tbl i (new_record name); - i - end - -let to_string i = - (Hashtbl.find int_string_tbl i).data - -let mark_all_as_unused () = - Hashtbl.iter (fun _ v -> v.garbage <- true) int_string_tbl - -let mark_as_used symb = - let record1 = Hashtbl.find int_string_tbl symb in - record1.garbage <- false - -let garbage () = - let records = Hashtbl.fold (fun symb record accu -> - if record.garbage then (symb, record.data) :: accu else accu - ) int_string_tbl [] in - let remove (int,string) = - Hashtbl.remove int_string_tbl int; - Hashtbl.remove string_int_tbl string - in - created_counter := 0; - used_counter := 0; - List.iter remove records +let equal a b = + (* compare using physical equality, both members have to be part of the above weak table *) + a == b let stats () = - Hashtbl.length string_int_tbl - -let created () = !created_counter -let used () = !used_counter + let len, entries, _, _, _, _ = WeakTable.stats tbl in + len, entries diff --git a/tools/ocaml/xenstored/symbol.mli b/tools/ocaml/xenstored/symbol.mli index c3c9f6e2f8..586ab57507 100644 --- a/tools/ocaml/xenstored/symbol.mli +++ b/tools/ocaml/xenstored/symbol.mli @@ -29,24 +29,11 @@ val of_string : string -> t val to_string : t -> string (** Convert a symbol into a string. *) -(** {6 Garbage Collection} *) - -(** Symbols need to be regulary garbage collected. The following steps should be followed: -- mark all the knowns symbols as unused (with [mark_all_as_unused]); -- mark all the symbols really usefull as used (with [mark_as_used]); and -- finally, call [garbage] *) - -val mark_all_as_unused : unit -> unit -val mark_as_used : t -> unit -val garbage : unit -> unit +val equal: t -> t -> bool +(** Compare two symbols for equality *) (** {6 Statistics } *) -val stats : unit -> int -(** Get the number of used symbols. *) +val stats : unit -> int * int +(** Get the table size and number of entries. *) -val created : unit -> int -(** Returns the number of symbols created since the last GC. *) - -val used : unit -> int -(** Returns the number of existing symbols used since the last GC *) diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml index a4466c5b5c..047e093555 100644 --- a/tools/ocaml/xenstored/xenstored.ml +++ b/tools/ocaml/xenstored/xenstored.ml @@ -378,18 +378,6 @@ let _ = let periodic_ops now = debug "periodic_ops starting"; - (* we garbage collect the string->int dictionary after a sizeable amount of operations, - * there's no need to be really fast even if we got loose - * objects since names are often reuse. - *) - if Symbol.created () > 1000 || Symbol.used () > 20000 - then begin - Symbol.mark_all_as_unused (); - Store.mark_symbols store; - Connections.iter cons Connection.mark_symbols; - History.mark_symbols (); - Symbol.garbage () - end; (* scan all the xs rings as a safenet for ill-behaved clients *) if !ring_scan_interval >= 0 && now > (!last_scan_time +. float !ring_scan_interval) then @@ -407,11 +395,11 @@ let _ = let (lanon, lanon_ops, lanon_watchs, ldom, ldom_ops, ldom_watchs) = Connections.stats cons in let store_nodes, store_abort, store_coalesce = Store.stats store in - let symtbl_len = Symbol.stats () in + let symtbl_len, symtbl_entries = Symbol.stats () in info "store stat: nodes(%d) t-abort(%d) t-coalesce(%d)" store_nodes store_abort store_coalesce; - info "sytbl stat: %d" symtbl_len; + info "sytbl stat: length(%d) entries(%d)" symtbl_len symtbl_entries; info " con stat: anonymous(%d, %d o, %d w) domains(%d, %d o, %d w)" lanon lanon_ops lanon_watchs ldom ldom_ops ldom_watchs; info " mem stat: minor(%.0f) promoted(%.0f) major(%.0f) heap(%d w, %d c) live(%d w, %d b) free(%d w, %d b)" From patchwork Mon Aug 17 18:39:52 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719087 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 95B5313A4 for ; Mon, 17 Aug 2020 18:42:09 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 7178F20760 for ; Mon, 17 Aug 2020 18:42:09 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="GLWK0n8W" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 7178F20760 Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3j-0006Nc-Be; Mon, 17 Aug 2020 18:40:39 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3i-0006KG-0W for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:38 +0000 X-Inumbo-ID: 45d39570-92d6-405a-a911-59ef7c0eb7d1 Received: from esa3.hc3370-68.iphmx.com (unknown [216.71.145.155]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 45d39570-92d6-405a-a911-59ef7c0eb7d1; Mon, 17 Aug 2020 18:40:32 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689633; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=Jwr6W7VdvDSBzVBwOidlGCgXyRsM0JTbKS0k1mHOFbY=; b=GLWK0n8WqdONLNI0WjS7tamQI1pT0uIWRf2TrsmdxGH2UEhAKjGbqsS5 W2mASVlWhzaxDHRJnrRXeSYlgFVW9ninHA2uLOY7fPatjEKch0QXiQxq4 rMmjS0xzj4cvh5z6e8oUVApQ3SmCq+BGG1fYHD5MZN5n1mmvNZp9m+p+N 8=; Authentication-Results: esa3.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: EI5h0kvZl45u5ieBNH6sJI44dC0zrqtN/gMp2gs/uBBHfMHQPXkRuG8yZINEaNDl78pAJPImB0 jWYy/R7EsqnNgnNRrMkznFvYzYQSWm01Rf9o5S6HQFvuuSjjmiV7N5ccWayJKGOffxl9n0FK2F o0ySVN02PBnmgW26UsPdNRdBIII11N+mxvg1UZ4QtXrFgb0nmTrtJ5bZJWreBW96mLJFKPM7jW EQC58zW4DmRBdpFcZ7oH6nOx2j2p2DRRcT7MaD39dSwa+yqLtMkZ0VU56MUhSRvpbIP6WO81Ne jTg= X-SBRS: 2.7 X-MesageID: 24692807 X-Ironport-Server: esa3.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24692807" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 4/6] tools/ocaml/xenstored: drop select based socket watching Date: Mon, 17 Aug 2020 19:39:52 +0100 Message-ID: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" Poll has been the default since 2014, I think we can safely say by now that poll() works and we don't need to fall back to select(). This will allow fixing up the way we call poll to be more efficient (and pave the way for introducing epoll support): currently poll wraps the select API, which is inefficient. Signed-off-by: Edwin Török --- Changed since v1: * fix commit title --- tools/ocaml/xenstored/Makefile | 12 ++++++------ tools/ocaml/xenstored/parse_arg.ml | 7 ++----- tools/ocaml/xenstored/{select.ml => poll.ml} | 14 ++------------ tools/ocaml/xenstored/{select.mli => poll.mli} | 12 ++---------- tools/ocaml/xenstored/xenstored.ml | 4 +--- 5 files changed, 13 insertions(+), 36 deletions(-) rename tools/ocaml/xenstored/{select.ml => poll.ml} (85%) rename tools/ocaml/xenstored/{select.mli => poll.mli} (58%) diff --git a/tools/ocaml/xenstored/Makefile b/tools/ocaml/xenstored/Makefile index 68d35c483a..692a62584e 100644 --- a/tools/ocaml/xenstored/Makefile +++ b/tools/ocaml/xenstored/Makefile @@ -18,12 +18,12 @@ OCAMLINCLUDE += \ -I $(OCAML_TOPLEVEL)/libs/xc \ -I $(OCAML_TOPLEVEL)/libs/eventchn -LIBS = syslog.cma syslog.cmxa select.cma select.cmxa +LIBS = syslog.cma syslog.cmxa poll.cma poll.cmxa syslog_OBJS = syslog syslog_C_OBJS = syslog_stubs -select_OBJS = select -select_C_OBJS = select_stubs -OCAML_LIBRARY = syslog select +poll_OBJS = poll +poll_C_OBJS = select_stubs +OCAML_LIBRARY = syslog poll LIBS += systemd.cma systemd.cmxa systemd_OBJS = systemd @@ -58,13 +58,13 @@ OBJS = paths \ process \ xenstored -INTF = symbol.cmi trie.cmi syslog.cmi systemd.cmi select.cmi +INTF = symbol.cmi trie.cmi syslog.cmi systemd.cmi poll.cmi XENSTOREDLIBS = \ unix.cmxa \ -ccopt -L -ccopt . syslog.cmxa \ -ccopt -L -ccopt . systemd.cmxa \ - -ccopt -L -ccopt . select.cmxa \ + -ccopt -L -ccopt . poll.cmxa \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/mmap $(OCAML_TOPLEVEL)/libs/mmap/xenmmap.cmxa \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/eventchn $(OCAML_TOPLEVEL)/libs/eventchn/xeneventchn.cmxa \ -ccopt -L -ccopt $(OCAML_TOPLEVEL)/libs/xc $(OCAML_TOPLEVEL)/libs/xc/xenctrl.cmxa \ diff --git a/tools/ocaml/xenstored/parse_arg.ml b/tools/ocaml/xenstored/parse_arg.ml index 1803c3eda0..2c4b5a8528 100644 --- a/tools/ocaml/xenstored/parse_arg.ml +++ b/tools/ocaml/xenstored/parse_arg.ml @@ -25,7 +25,6 @@ type config = tracefile: string option; (* old xenstored compatibility *) restart: bool; disable_socket: bool; - use_select: bool; } let do_argv = @@ -37,7 +36,7 @@ let do_argv = and config_file = ref "" and restart = ref false and disable_socket = ref false - and use_select = ref false in + in let speclist = [ ("--no-domain-init", Arg.Unit (fun () -> domain_init := false), @@ -54,9 +53,8 @@ let do_argv = ("-T", Arg.Set_string tracefile, ""); (* for compatibility *) ("--restart", Arg.Set restart, "Read database on starting"); ("--disable-socket", Arg.Unit (fun () -> disable_socket := true), "Disable socket"); - ("--use-select", Arg.Unit (fun () -> use_select := true), "Use select instead of poll"); (* for backward compatibility and testing *) ] in - let usage_msg = "usage : xenstored [--config-file ] [--no-domain-init] [--help] [--no-fork] [--reraise-top-level] [--restart] [--disable-socket] [--use-select]" in + let usage_msg = "usage : xenstored [--config-file ] [--no-domain-init] [--help] [--no-fork] [--reraise-top-level] [--restart] [--disable-socket]" in Arg.parse speclist (fun _ -> ()) usage_msg; { domain_init = !domain_init; @@ -68,5 +66,4 @@ let do_argv = tracefile = if !tracefile <> "" then Some !tracefile else None; restart = !restart; disable_socket = !disable_socket; - use_select = !use_select; } diff --git a/tools/ocaml/xenstored/select.ml b/tools/ocaml/xenstored/poll.ml similarity index 85% rename from tools/ocaml/xenstored/select.ml rename to tools/ocaml/xenstored/poll.ml index 0455e163e3..26f8620dfc 100644 --- a/tools/ocaml/xenstored/select.ml +++ b/tools/ocaml/xenstored/poll.ml @@ -63,15 +63,5 @@ let poll_select in_fds out_fds exc_fds timeout = (if event.except then fd :: x else x)) a r -(* If the use_poll function is not called at all, we default to the original Unix.select behavior *) -let select_fun = ref Unix.select - -let use_poll yes = - let sel_fun, max_fd = - if yes then poll_select, get_sys_fs_nr_open () - else Unix.select, 1024 in - select_fun := sel_fun; - set_fd_limit max_fd - -let select in_fds out_fds exc_fds timeout = - (!select_fun) in_fds out_fds exc_fds timeout +let () = + set_fd_limit (get_sys_fs_nr_open ()) diff --git a/tools/ocaml/xenstored/select.mli b/tools/ocaml/xenstored/poll.mli similarity index 58% rename from tools/ocaml/xenstored/select.mli rename to tools/ocaml/xenstored/poll.mli index 3912779172..f73465b99f 100644 --- a/tools/ocaml/xenstored/select.mli +++ b/tools/ocaml/xenstored/poll.mli @@ -13,15 +13,7 @@ *) -(** Same interface and semantics as [Unix.select] but with an extra alternative - implementation based on poll. Switching implementations is done by calling - the [use_poll] function. *) -val select: +(** Same interface and semantics as [Unix.select], implemented using poll(3). *) +val poll_select: Unix.file_descr list -> Unix.file_descr list -> Unix.file_descr list -> float -> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list - -(** [use_poll true] will use poll based select with max fds number limitation - eliminated; [use_poll false] will use standard [Unix.select] with max fd - number set to 1024; not calling this function at all equals to use the - standard [Unix.select] with max fd number setting untouched. *) -val use_poll: bool -> unit diff --git a/tools/ocaml/xenstored/xenstored.ml b/tools/ocaml/xenstored/xenstored.ml index 047e093555..f3e4697dea 100644 --- a/tools/ocaml/xenstored/xenstored.ml +++ b/tools/ocaml/xenstored/xenstored.ml @@ -308,8 +308,6 @@ let _ = ); ); - Select.use_poll (not cf.use_select); - Sys.set_signal Sys.sighup (Sys.Signal_handle sighup_handler); Sys.set_signal Sys.sigterm (Sys.Signal_handle (fun _ -> quit := true)); Sys.set_signal Sys.sigusr1 (Sys.Signal_handle (fun _ -> sigusr1_handler store)); @@ -441,7 +439,7 @@ let _ = let inset, outset = Connections.select ~only_if:is_peaceful cons in let rset, wset, _ = try - Select.select (spec_fds @ inset) outset [] timeout + Poll.poll_select (spec_fds @ inset) outset [] timeout with Unix.Unix_error(Unix.EINTR, _, _) -> [], [], [] in let sfds, cfds = From patchwork Mon Aug 17 18:39:53 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719095 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 0779E13A4 for ; Mon, 17 Aug 2020 18:42:23 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id D7D2C204EC for ; Mon, 17 Aug 2020 18:42:22 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="a1dyxw4G" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org D7D2C204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3b-0006Km-KE; Mon, 17 Aug 2020 18:40:31 +0000 Received: from all-amaz-eas1.inumbo.com ([34.197.232.57] helo=us1-amaz-eas2.inumbo.com) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3a-0006K5-KD for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:30 +0000 X-Inumbo-ID: 24fc1c7c-12be-4305-b72c-bf4614c6342d Received: from esa3.hc3370-68.iphmx.com (unknown [216.71.145.155]) by us1-amaz-eas2.inumbo.com (Halon) with ESMTPS id 24fc1c7c-12be-4305-b72c-bf4614c6342d; Mon, 17 Aug 2020 18:40:25 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689626; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=0Q7mZezmkZDXxgdfVrSnPIVAXJc1OwrHZVcWnmgusxs=; b=a1dyxw4GE8Wf995Ez2H0vLlEs3J4GLY0U76SBA4X+Qc17RP5xs2u5HVw 5bptnd+uK901JILkQNtO5Z4b7hsPhYoJhNf1UIAxLyrtwPw7oB2ARhIFu O8iZRjSZBscWmR18s8/oj9yFISduzhnNU7nT61j8VJi8t12uotKFnRhfo M=; Authentication-Results: esa3.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: GxPWrP2BOYCOvGSr03Wk5mThVW6qeZhMyNISnxgcWieMrs6D2KH+qHF4DxlKlyMODVbEVm/bxL QB46okf0eAGUxukDvva4FtQDqqdsfoyv7Do0AHZgQMaGIidAnL+HHD52EgNWpHqz/n7KqVl8sQ lSFZVtGn6FAm62scy5BGuIqcM7AZYXehjm+dEbwN+4jvtLT9TDMOS9n3MejC4ustRLE/NXfMXo SgehxWYPS/DCku3ee2Fmi/nm3WjPQq+DOSLcBejPca/TNtT2ojabXWQgqkT6Qpg6+doTuUgDpv RQ8= X-SBRS: 2.7 X-MesageID: 24692795 X-Ironport-Server: esa3.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24692795" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 5/6] tools/ocaml/xenstored: use more efficient node trees Date: Mon, 17 Aug 2020 19:39:53 +0100 Message-ID: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" This changes the output of xenstore-ls to be sorted. Previously the keys were listed in the order in which they were inserted in. docs/misc/xenstore.txt doesn't specify in what order keys are listed. Map.update is used to retain semantics with replace_child: only an existing child is replaced, if it wasn't part of the original map we don't add it. Similarly exception behaviour is retained for del_childname and related functions. Entries are stored in reverse sort order, so that upon Map.fold the constructed list is sorted in ascending order and there is no need for a List.rev. Signed-off-by: Edwin Török --- tools/ocaml/xenstored/store.ml | 46 +++++++++++++++----------------- tools/ocaml/xenstored/symbol.ml | 4 +++ tools/ocaml/xenstored/symbol.mli | 3 +++ 3 files changed, 29 insertions(+), 24 deletions(-) diff --git a/tools/ocaml/xenstored/store.ml b/tools/ocaml/xenstored/store.ml index 45659a23ee..d9dfa36045 100644 --- a/tools/ocaml/xenstored/store.ml +++ b/tools/ocaml/xenstored/store.ml @@ -16,17 +16,19 @@ *) open Stdext +module SymbolMap = Map.Make(Symbol) + module Node = struct type t = { name: Symbol.t; perms: Perms.Node.t; value: string; - children: t list; + children: t SymbolMap.t; } let create _name _perms _value = - { name = Symbol.of_string _name; perms = _perms; value = _value; children = []; } + { name = Symbol.of_string _name; perms = _perms; value = _value; children = SymbolMap.empty; } let get_owner node = Perms.Node.get_owner node.perms let get_children node = node.children @@ -42,38 +44,34 @@ let set_value node nvalue = let set_perms node nperms = { node with perms = nperms } let add_child node child = - { node with children = child :: node.children } + let children = SymbolMap.add child.name child node.children in + { node with children } let exists node childname = let childname = Symbol.of_string childname in - List.exists (fun n -> Symbol.equal n.name childname) node.children + SymbolMap.mem childname node.children let find node childname = let childname = Symbol.of_string childname in - List.find (fun n -> Symbol.equal n.name childname) node.children + SymbolMap.find childname node.children let replace_child node child nchild = - (* this is the on-steroid version of the filter one-replace one *) - let rec replace_one_in_list l = - match l with - | [] -> [] - | h :: tl when Symbol.equal h.name child.name -> nchild :: tl - | h :: tl -> h :: replace_one_in_list tl - in - { node with children = (replace_one_in_list node.children) } + { node with + children = SymbolMap.update child.name + (function None -> None | Some _ -> Some nchild) + node.children + } let del_childname node childname = let sym = Symbol.of_string childname in - let rec delete_one_in_list l = - match l with - | [] -> raise Not_found - | h :: tl when Symbol.equal h.name sym -> tl - | h :: tl -> h :: delete_one_in_list tl - in - { node with children = (delete_one_in_list node.children) } + { node with children = + SymbolMap.update sym + (function None -> raise Not_found | Some _ -> None) + node.children + } let del_all_children node = - { node with children = [] } + { node with children = SymbolMap.empty } (* check if the current node can be accessed by the current connection with rperm permissions *) let check_perm node connection request = @@ -87,7 +85,7 @@ let check_owner node connection = raise Define.Permission_denied; end -let rec recurse fct node = fct node; List.iter (recurse fct) node.children +let rec recurse fct node = fct node; SymbolMap.iter (fun _ -> recurse fct) node.children let unpack node = (Symbol.to_string node.name, node.perms, node.value) @@ -321,7 +319,7 @@ let ls store perm path = Node.check_perm cnode perm Perms.READ; cnode.Node.children in Path.apply store.root path do_ls in - List.rev (List.map (fun n -> Symbol.to_string n.Node.name) children) + SymbolMap.fold (fun k _ accu -> Symbol.to_string k :: accu) children [] let getperms store perm path = if path = [] then @@ -350,7 +348,7 @@ let traversal root_node f = let rec _traversal path node = f path node; let node_path = Path.of_path_and_name path (Symbol.to_string node.Node.name) in - List.iter (_traversal node_path) node.Node.children + SymbolMap.iter (fun _ -> _traversal node_path) node.Node.children in _traversal [] root_node diff --git a/tools/ocaml/xenstored/symbol.ml b/tools/ocaml/xenstored/symbol.ml index dac6f9f819..2697915623 100644 --- a/tools/ocaml/xenstored/symbol.ml +++ b/tools/ocaml/xenstored/symbol.ml @@ -31,6 +31,10 @@ let equal a b = (* compare using physical equality, both members have to be part of the above weak table *) a == b +let compare a b = + if equal a b then 0 + else -(String.compare a b) + let stats () = let len, entries, _, _, _, _ = WeakTable.stats tbl in len, entries diff --git a/tools/ocaml/xenstored/symbol.mli b/tools/ocaml/xenstored/symbol.mli index 586ab57507..dd0f014796 100644 --- a/tools/ocaml/xenstored/symbol.mli +++ b/tools/ocaml/xenstored/symbol.mli @@ -32,6 +32,9 @@ val to_string : t -> string val equal: t -> t -> bool (** Compare two symbols for equality *) +val compare: t -> t -> int +(** Compare two symbols *) + (** {6 Statistics } *) val stats : unit -> int * int From patchwork Mon Aug 17 18:39:54 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= X-Patchwork-Id: 11719093 Return-Path: Received: from mail.kernel.org (pdx-korg-mail-1.web.codeaurora.org [172.30.200.123]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 6CF73109B for ; Mon, 17 Aug 2020 18:42:18 +0000 (UTC) Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 47F6C204EC for ; Mon, 17 Aug 2020 18:42:18 +0000 (UTC) Authentication-Results: mail.kernel.org; dkim=fail reason="signature verification failed" (1024-bit key) header.d=citrix.com header.i=@citrix.com header.b="RvK7vF/c" DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 47F6C204EC Authentication-Results: mail.kernel.org; dmarc=fail (p=reject dis=none) header.from=citrix.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=xen-devel-bounces@lists.xenproject.org Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3p-0006QS-09; Mon, 17 Aug 2020 18:40:45 +0000 Received: from us1-rack-iad1.inumbo.com ([172.99.69.81]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1k7k3n-0006KG-0d for xen-devel@lists.xenproject.org; Mon, 17 Aug 2020 18:40:43 +0000 X-Inumbo-ID: 05d78877-7760-4e5c-98de-8822bc0157cd Received: from esa3.hc3370-68.iphmx.com (unknown [216.71.145.155]) by us1-rack-iad1.inumbo.com (Halon) with ESMTPS id 05d78877-7760-4e5c-98de-8822bc0157cd; Mon, 17 Aug 2020 18:40:33 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=simple/simple; d=citrix.com; s=securemail; t=1597689634; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=+Bs+Fxq+yO/S2L4Mgyr+mCqf669K6A0XW3wC71rhZYE=; b=RvK7vF/c05vzQOMJFPE9I+m5RYv5cIlkCoqZJdte07PwiUvVUtG5hgPY 6RHuyrfoxYQbuGP3FJ3Ko5ghYLdw7Zq7TXaq+9C6B07t7ohjZUZWh5Twy v1AZH9oc70DGF+cS3i6cRmrGEAroJ2WmZuCMZAzYipYf302tXz7H71ml6 s=; Authentication-Results: esa3.hc3370-68.iphmx.com; dkim=none (message not signed) header.i=none IronPort-SDR: e3ERQzfQkkqXGDaH6kFPmXuXgtAqi6mQp+1e9NVy1LAEZXyr3LzAqHlvp77HHO7iOLW4vAU7Zo wiJUWkCQtoxZGQlUcVDfbJoir+vvrs8ZqJ2bWuiTBCkoF5C1oJGeCcnrdqSaQ4RBmrFGB+IW4h Vi5rryeyALE4V2VpigYELzoxED4ss4Xsi/p+L0ac9hYrUltFQGuoEtl4AFx5SCpIn9DL7w8dYl pElMnnNs4SHGXNZxygmnWBV+zkvCtgOQ+4MpVtjqFlJhf0fkKNI5xkaJVXHosZMT9EQep74EOP KTs= X-SBRS: 2.7 X-MesageID: 24692808 X-Ironport-Server: esa3.hc3370-68.iphmx.com X-Remote-IP: 162.221.158.21 X-Policy: $RELAYED X-IronPort-AV: E=Sophos;i="5.76,324,1592884800"; d="scan'208";a="24692808" From: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= To: CC: =?utf-8?b?RWR3aW4gVMO2csO2aw==?= , "Christian Lindig" , David Scott , "Ian Jackson" , Wei Liu Subject: [PATCH v2 6/6] tools/ocaml/xenstored: use more efficient tries Date: Mon, 17 Aug 2020 19:39:54 +0100 Message-ID: X-Mailer: git-send-email 2.25.1 In-Reply-To: References: MIME-Version: 1.0 X-BeenThere: xen-devel@lists.xenproject.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Sender: "Xen-devel" No functional change, just an optimization. Signed-off-by: Edwin Török --- Changed since v1: * fix missing 'set_node' in 'set' that got lost in conversion to map * simplify 'compare' function --- tools/ocaml/xenstored/connections.ml | 2 +- tools/ocaml/xenstored/symbol.ml | 6 +-- tools/ocaml/xenstored/trie.ml | 59 ++++++++++++---------------- tools/ocaml/xenstored/trie.mli | 26 ++++++------ 4 files changed, 43 insertions(+), 50 deletions(-) diff --git a/tools/ocaml/xenstored/connections.ml b/tools/ocaml/xenstored/connections.ml index f02ef6b526..4983c7370b 100644 --- a/tools/ocaml/xenstored/connections.ml +++ b/tools/ocaml/xenstored/connections.ml @@ -21,7 +21,7 @@ type t = { anonymous: (Unix.file_descr, Connection.t) Hashtbl.t; domains: (int, Connection.t) Hashtbl.t; ports: (Xeneventchn.t, Connection.t) Hashtbl.t; - mutable watches: (string, Connection.watch list) Trie.t; + mutable watches: Connection.watch list Trie.t; } let create () = { diff --git a/tools/ocaml/xenstored/symbol.ml b/tools/ocaml/xenstored/symbol.ml index 2697915623..85b3f265de 100644 --- a/tools/ocaml/xenstored/symbol.ml +++ b/tools/ocaml/xenstored/symbol.ml @@ -31,9 +31,9 @@ let equal a b = (* compare using physical equality, both members have to be part of the above weak table *) a == b -let compare a b = - if equal a b then 0 - else -(String.compare a b) +(* the sort order is reversed here, so that Map.fold constructs a list + in ascending order *) +let compare a b = String.compare b a let stats () = let len, entries, _, _, _, _ = WeakTable.stats tbl in diff --git a/tools/ocaml/xenstored/trie.ml b/tools/ocaml/xenstored/trie.ml index dc42535092..5b4831cf02 100644 --- a/tools/ocaml/xenstored/trie.ml +++ b/tools/ocaml/xenstored/trie.ml @@ -13,24 +13,26 @@ * GNU Lesser General Public License for more details. *) +module StringMap = Map.Make(String) + module Node = struct - type ('a,'b) t = { - key: 'a; - value: 'b option; - children: ('a,'b) t list; + type 'a t = { + key: string; + value: 'a option; + children: 'a t StringMap.t; } let _create key value = { key = key; value = Some value; - children = []; + children = StringMap.empty; } let empty key = { key = key; value = None; - children = [] + children = StringMap.empty; } let _get_key node = node.key @@ -47,41 +49,31 @@ struct { node with children = children } let _add_child node child = - { node with children = child :: node.children } + { node with children = StringMap.add child.key child node.children } end -type ('a,'b) t = ('a,'b) Node.t list +type 'a t = 'a Node.t StringMap.t let mem_node nodes key = - List.exists (fun n -> n.Node.key = key) nodes + StringMap.mem key nodes let find_node nodes key = - List.find (fun n -> n.Node.key = key) nodes + StringMap.find key nodes let replace_node nodes key node = - let rec aux = function - | [] -> [] - | h :: tl when h.Node.key = key -> node :: tl - | h :: tl -> h :: aux tl - in - aux nodes + StringMap.update key (function None -> None | Some _ -> Some node) nodes let remove_node nodes key = - let rec aux = function - | [] -> raise Not_found - | h :: tl when h.Node.key = key -> tl - | h :: tl -> h :: aux tl - in - aux nodes + StringMap.update key (function None -> raise Not_found | Some _ -> None) nodes -let create () = [] +let create () = StringMap.empty let rec iter f tree = - let aux node = - f node.Node.key node.Node.value; + let aux key node = + f key node.Node.value; iter f node.Node.children in - List.iter aux tree + StringMap.iter aux tree let rec map f tree = let aux node = @@ -92,13 +84,14 @@ let rec map f tree = in { node with Node.value = value; Node.children = map f node.Node.children } in - List.filter (fun n -> n.Node.value <> None || n.Node.children <> []) (List.map aux tree) + tree |> StringMap.map aux + |> StringMap.filter (fun _ n -> n.Node.value <> None || not (StringMap.is_empty n.Node.children) ) let rec fold f tree acc = - let aux accu node = - fold f node.Node.children (f node.Node.key node.Node.value accu) + let aux key node accu = + fold f node.Node.children (f key node.Node.value accu) in - List.fold_left aux acc tree + StringMap.fold aux tree acc (* return a sub-trie *) let rec sub_node tree = function @@ -115,7 +108,7 @@ let rec sub_node tree = function let sub tree path = try (sub_node tree path).Node.children - with Not_found -> [] + with Not_found -> StringMap.empty let find tree path = Node.get_value (sub_node tree path) @@ -159,7 +152,7 @@ and set tree path value = replace_node tree h (set_node node t value) end else begin let node = Node.empty h in - set_node node t value :: tree + StringMap.add node.Node.key (set_node node t value) tree end let rec unset tree = function @@ -174,7 +167,7 @@ let rec unset tree = function then Node.set_children (Node.empty h) children else Node.set_children node children in - if children = [] && new_node.Node.value = None + if StringMap.is_empty children && new_node.Node.value = None then remove_node tree h else replace_node tree h new_node end else diff --git a/tools/ocaml/xenstored/trie.mli b/tools/ocaml/xenstored/trie.mli index 5dc53c1cb1..27785154f5 100644 --- a/tools/ocaml/xenstored/trie.mli +++ b/tools/ocaml/xenstored/trie.mli @@ -15,46 +15,46 @@ (** Basic Implementation of polymorphic tries (ie. prefix trees) *) -type ('a, 'b) t -(** The type of tries. ['a list] is the type of keys, ['b] the type of values. +type 'a t +(** The type of tries. ['a] the type of values. Internally, a trie is represented as a labeled tree, where node contains values - of type ['a * 'b option]. *) + of type [string * 'a option]. *) -val create : unit -> ('a,'b) t +val create : unit -> 'a t (** Creates an empty trie. *) -val mem : ('a,'b) t -> 'a list -> bool +val mem : 'a t -> string list -> bool (** [mem t k] returns true if a value is associated with the key [k] in the trie [t]. Otherwise, it returns false. *) -val find : ('a, 'b) t -> 'a list -> 'b +val find : 'a t -> string list -> 'a (** [find t k] returns the value associated with the key [k] in the trie [t]. Returns [Not_found] if no values are associated with [k] in [t]. *) -val set : ('a, 'b) t -> 'a list -> 'b -> ('a, 'b) t +val set : 'a t -> string list -> 'a -> 'a t (** [set t k v] associates the value [v] with the key [k] in the trie [t]. *) -val unset : ('a, 'b) t -> 'a list -> ('a, 'b) t +val unset : 'a t -> string list -> 'a t (** [unset k v] removes the association of value [v] with the key [k] in the trie [t]. Moreover, it automatically clean the trie, ie. it removes recursively every nodes of [t] containing no values and having no chil. *) -val iter : ('a -> 'b option -> unit) -> ('a, 'b) t -> unit +val iter : (string -> 'a option -> unit) -> 'a t -> unit (** [iter f t] applies the function [f] to every node of the trie [t]. As nodes of the trie [t] do not necessary contains a value, the second argument of [f] is an option type. *) -val iter_path : ('a -> 'b option -> unit) -> ('a, 'b) t -> 'a list -> unit +val iter_path : (string -> 'a option -> unit) -> 'a t -> string list -> unit (** [iter_path f t p] iterates [f] over nodes associated with the path [p] in the trie [t]. If [p] is not a valid path of [t], it iterates on the longest valid prefix of [p]. *) -val fold : ('a -> 'b option -> 'c -> 'c) -> ('a, 'b) t -> 'c -> 'c +val fold : (string -> 'a option -> 'c -> 'c) -> 'a t -> 'c -> 'c (** [fold f t x] fold [f] over every nodes of [t], with [x] as initial value. *) -val map : ('b -> 'c option) -> ('a,'b) t -> ('a,'c) t +val map : ('a -> 'b option) -> 'a t -> 'b t (** [map f t] maps [f] over every values stored in [t]. The return value of [f] is of type 'c option as one may wants to remove value associated to a key. This function is not tail-recursive. *) -val sub : ('a, 'b) t -> 'a list -> ('a,'b) t +val sub : 'a t -> string list -> 'a t (** [sub t p] returns the sub-trie associated with the path [p] in the trie [t]. If [p] is not a valid path of [t], it returns an empty trie. *)