Skip to content

Commit 7ecc609

Browse files
author
Andrii Sultanov
committed
fixup! CP-52225 - poll: Reduce unnecessary allocations
1 parent cc72b95 commit 7ecc609

File tree

4 files changed

+64
-25
lines changed

4 files changed

+64
-25
lines changed

oxenstored/connections.ml

Lines changed: 40 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ let debug fmt = Logging.debug "connections" fmt
2222
type t = {
2323
anonymous: (Unix.file_descr, Connection.t * int) Hashtbl.t
2424
(* (fd -> Connection.t, index) where index maps to the poll_status array *)
25-
; mutable poll_status: (Unix.file_descr * Poll.event) array
25+
; mutable poll_status: Poll.poll_status_t array
2626
; domains: (int, Connection.t) Hashtbl.t
2727
; ports: (Xeneventchn.t, Connection.t) Hashtbl.t
2828
; mutable watches: Connection.watch list Trie.t
@@ -46,7 +46,15 @@ let get_capacity () =
4646
; maxwatchevents= !Define.maxwatchevents
4747
}
4848

49-
let default_poll_status () = (Unix.stdin, Poll.init_event ())
49+
let default_poll_status () = Poll.{fd= Unix.stdin; event= init_event ()}
50+
51+
let spec_poll_status_new () = Poll.{read= true; write= false; except= false}
52+
53+
let spec_poll_status event =
54+
let open Poll in
55+
event.read <- true ;
56+
event.write <- false ;
57+
event.except <- false
5058

5159
let add_anonymous cons fd =
5260
let capacity = get_capacity () in
@@ -67,20 +75,23 @@ let add_domain cons dom =
6775
Hashtbl.replace cons.domains (Domain.get_id dom) con ;
6876
Hashtbl.replace cons.ports (Domain.get_local_port dom) con
6977

70-
let refresh_poll_status ?(only_if = fun _ -> true) cons =
78+
let refresh_poll_status ?(only_if = fun _ -> true) cons spec_fds =
79+
(* special fds are always read=true, but get overwritten by select_stubs, so we
80+
need to reset the event we are polling for *)
81+
List.iteri
82+
(fun index fd ->
83+
cons.poll_status.(index).fd <- fd ;
84+
spec_poll_status cons.poll_status.(index).event
85+
)
86+
spec_fds ;
7187
Hashtbl.iter
7288
(fun _ (con, index) ->
7389
let only = only_if con in
74-
let fd = Connection.get_fd con in
90+
cons.poll_status.(index).fd <- Connection.get_fd con ;
7591
let open Poll in
76-
let event =
77-
{
78-
read= only && Connection.can_input con
79-
; write= only && Connection.has_output con
80-
; except= false
81-
}
82-
in
83-
cons.poll_status.(index) <- (fd, event)
92+
cons.poll_status.(index).event.read <- only && Connection.can_input con ;
93+
cons.poll_status.(index).event.write <- only && Connection.has_output con ;
94+
cons.poll_status.(index).event.except <- false
8495
)
8596
cons.anonymous
8697
@@ -107,19 +118,33 @@ let del_watches cons con =
107118
|> Connection.Watch.Set.filter @@ fun w -> Connection.get_con w != con
108119
)
109120
110-
let del_anonymous cons con =
121+
let del_anonymous cons con spec_fds =
111122
try
112123
Hashtbl.remove cons.anonymous (Connection.get_fd con) ;
113124
(* Reallocate the poll_status array, update indices pointing to it *)
114125
cons.poll_status <-
115-
Array.make (Hashtbl.length cons.anonymous) (default_poll_status ()) ;
126+
Array.make
127+
(Hashtbl.length cons.anonymous + List.length spec_fds)
128+
(default_poll_status ()) ;
129+
130+
(* Keep the special fds at the beginning *)
131+
let i =
132+
List.fold_left
133+
(fun index fd ->
134+
cons.poll_status.(index).fd <- fd ;
135+
spec_poll_status cons.poll_status.(index).event ;
136+
index + 1
137+
)
138+
0 spec_fds
139+
in
140+
116141
let _ =
117142
Hashtbl.fold
118143
(fun key (con, _) i ->
119144
Hashtbl.replace cons.anonymous key (con, i) ;
120145
i + 1
121146
)
122-
cons.anonymous 0
147+
cons.anonymous i
123148
in
124149
125150
del_watches cons con ; Connection.close con

oxenstored/poll.ml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,11 @@
1717
readfds, writefds, exceptfds concept as in select. *)
1818
type event = {mutable read: bool; mutable write: bool; mutable except: bool}
1919

20+
type poll_status_t = {mutable fd: Unix.file_descr; event: event}
21+
2022
let init_event () = {read= false; write= false; except= false}
2123

22-
external select_on_poll : (Unix.file_descr * event) array -> int -> int
24+
external select_on_poll : poll_status_t array -> int -> int
2325
= "stub_select_on_poll"
2426

2527
external set_fd_limit : int -> unit = "stub_set_fd_limit"
@@ -33,14 +35,14 @@ let get_sys_fs_nr_open () =
3335
close_in_noerr ch ; v
3436
with _ -> 1024 * 1024
3537

36-
let poll_select fdarr timeout =
38+
let poll_select (fdarr : poll_status_t array) timeout =
3739
let n = select_on_poll fdarr (int_of_float (timeout *. 1000.)) in
3840
let r = ([], [], []) in
3941
if n = 0 then
4042
r
4143
else
4244
Array.fold_right
43-
(fun (fd, event) (r, w, x) ->
45+
(fun {fd; event} (r, w, x) ->
4446
( (if event.read then fd :: r else r)
4547
, (if event.write then fd :: w else w)
4648
, if event.except then fd :: x else x

oxenstored/poll.mli

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,11 @@
1414

1515
type event = {mutable read: bool; mutable write: bool; mutable except: bool}
1616

17+
type poll_status_t = {mutable fd: Unix.file_descr; event: event}
18+
1719
val init_event : unit -> event
1820

1921
val poll_select :
20-
(Unix.file_descr * event) array
22+
poll_status_t array
2123
-> float
2224
-> Unix.file_descr list * Unix.file_descr list * Unix.file_descr list

oxenstored/xenstored.ml

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,20 +29,20 @@ let debug fmt = Logging.debug "xenstored" fmt
2929
let info fmt = Logging.info "xenstored" fmt
3030

3131
(*------------ event klass processors --------------*)
32-
let process_connection_fds store cons domains rset wset =
32+
let process_connection_fds store cons domains rset wset spec_fds =
3333
let try_fct fct c =
3434
try fct store cons domains c with
3535
| Unix.Unix_error (err, "write", _) ->
36-
Connections.del_anonymous cons c ;
36+
Connections.del_anonymous cons c spec_fds ;
3737
error "closing socket connection: write error: %s"
3838
(Unix.error_message err)
3939
| Unix.Unix_error (err, "read", _) ->
40-
Connections.del_anonymous cons c ;
40+
Connections.del_anonymous cons c spec_fds ;
4141
if err <> Unix.ECONNRESET then
4242
error "closing socket connection: read error: %s"
4343
(Unix.error_message err)
4444
| Xenbus.Xb.End_of_file ->
45-
Connections.del_anonymous cons c ;
45+
Connections.del_anonymous cons c spec_fds ;
4646
debug "closing socket connection"
4747
in
4848
let process_fdset_with fds fct =
@@ -528,6 +528,16 @@ let () =
528528
(match rw_sock with None -> [] | Some x -> [x])
529529
@ if cf.domain_init then [Event.fd eventchn] else []
530530
in
531+
(* Always positioned at the start of cons.poll_status, maintained during
532+
reallocations *)
533+
cons.poll_status <-
534+
Array.append cons.poll_status
535+
(Array.of_list
536+
(List.map
537+
Connections.(fun fd -> Poll.{fd; event= spec_poll_status_new ()})
538+
spec_fds
539+
)
540+
) ;
531541

532542
let process_special_fds rset =
533543
let accept_connection fd =
@@ -681,7 +691,7 @@ let () =
681691
in
682692
if peaceful_mw <> [] then 0. else until_next_activity
683693
in
684-
Connections.refresh_poll_status ~only_if:is_peaceful cons ;
694+
Connections.refresh_poll_status ~only_if:is_peaceful cons spec_fds ;
685695
let rset, wset, _ =
686696
try Poll.poll_select cons.poll_status timeout
687697
with Unix.Unix_error (Unix.EINTR, _, _) -> ([], [], [])
@@ -691,7 +701,7 @@ let () =
691701
process_special_fds sfds ;
692702

693703
if cfds <> [] || wset <> [] then
694-
process_connection_fds store cons domains cfds wset ;
704+
process_connection_fds store cons domains cfds wset spec_fds ;
695705
( if timeout <> 0. then
696706
let now = Unix.gettimeofday () in
697707
if now > !period_start +. period_ops_interval then (

0 commit comments

Comments
 (0)