mirror of
https://github.com/c-cube/nanoev.git
synced 2025-12-06 03:05:32 -05:00
add tracing; improve echo
This commit is contained in:
parent
ce7ed336c2
commit
15b39c3541
8 changed files with 76 additions and 34 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
|
|
||||||
(executable
|
(executable
|
||||||
(name echo)
|
(name echo)
|
||||||
(libraries nanoev nanoev.unix moonpool nanoev_tiny_httpd))
|
(libraries nanoev nanoev.unix moonpool moonpool.fib trace trace-tef
|
||||||
|
nanoev_tiny_httpd))
|
||||||
|
|
|
||||||
|
|
@ -80,20 +80,26 @@ let setup_logging () =
|
||||||
Logs.set_level ~all:true (Some Logs.Debug)
|
Logs.set_level ~all:true (Some Logs.Debug)
|
||||||
|
|
||||||
let () =
|
let () =
|
||||||
|
let@ () = Trace_tef.with_setup () in
|
||||||
|
Trace.set_thread_name "main";
|
||||||
|
|
||||||
let port_ = ref 8080 in
|
let port_ = ref 8080 in
|
||||||
let max_conn = ref 1024 in
|
let max_conn = ref 1024 in
|
||||||
|
let j = ref 8 in
|
||||||
Arg.parse
|
Arg.parse
|
||||||
(Arg.align
|
(Arg.align
|
||||||
[
|
[
|
||||||
"--port", Arg.Set_int port_, " set port";
|
"--port", Arg.Set_int port_, " set port";
|
||||||
"-p", Arg.Set_int port_, " set port";
|
"-p", Arg.Set_int port_, " set port";
|
||||||
|
"-j", Arg.Set_int j, " number of threads";
|
||||||
"--debug", Arg.Unit setup_logging, " enable debug";
|
"--debug", Arg.Unit setup_logging, " enable debug";
|
||||||
"--max-conns", Arg.Set_int max_conn, " maximum concurrent connections";
|
"--max-conns", Arg.Set_int max_conn, " maximum concurrent connections";
|
||||||
])
|
])
|
||||||
(fun _ -> raise (Arg.Bad ""))
|
(fun _ -> raise (Arg.Bad ""))
|
||||||
"echo [option]*";
|
"echo [option]*";
|
||||||
|
|
||||||
let@ pool = Moonpool.Ws_pool.with_ () in
|
let@ pool = Moonpool.Ws_pool.with_ ~num_threads:!j () in
|
||||||
|
let@ _runner = Moonpool_fib.main in
|
||||||
|
|
||||||
let ev = Nanoev_unix.create () in
|
let ev = Nanoev_unix.create () in
|
||||||
Nanoev_picos.setup_bg_thread ev;
|
Nanoev_picos.setup_bg_thread ev;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,5 @@
|
||||||
|
|
||||||
(library
|
(library
|
||||||
(name nanoev_picos)
|
(name nanoev_picos)
|
||||||
(public_name nanoev.picos)
|
(public_name nanoev.picos)
|
||||||
(optional) ; picos
|
(optional) ; picos
|
||||||
(libraries threads picos nanoev))
|
(libraries threads picos nanoev))
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,8 @@
|
||||||
let ( let@ ) = ( @@ )
|
open struct
|
||||||
|
module Trace_ = Nanoev.Trace_
|
||||||
|
|
||||||
|
let ( let@ ) = ( @@ )
|
||||||
|
end
|
||||||
|
|
||||||
module Global_ = struct
|
module Global_ = struct
|
||||||
type st =
|
type st =
|
||||||
|
|
@ -23,6 +27,7 @@ module Global_ = struct
|
||||||
x
|
x
|
||||||
|
|
||||||
let bg_thread_ ~active ~evloop () : unit =
|
let bg_thread_ ~active ~evloop () : unit =
|
||||||
|
Trace_.set_thread_name "nanoev.picos.bg-thread";
|
||||||
while Atomic.get active do
|
while Atomic.get active do
|
||||||
Nanoev.step evloop
|
Nanoev.step evloop
|
||||||
done
|
done
|
||||||
|
|
@ -31,12 +36,15 @@ module Global_ = struct
|
||||||
|
|
||||||
let setup_bg_thread (ev : Nanoev.t) : unit =
|
let setup_bg_thread (ev : Nanoev.t) : unit =
|
||||||
let@ () = with_lock lock in
|
let@ () = with_lock lock in
|
||||||
|
(* shutdown existing thread, if any *)
|
||||||
(match Atomic.get st with
|
(match Atomic.get st with
|
||||||
| Some st ->
|
| Some st ->
|
||||||
Atomic.set st.active false;
|
Atomic.set st.active false;
|
||||||
Nanoev.wakeup_from_outside st.nanoev;
|
Nanoev.wakeup_from_outside st.nanoev;
|
||||||
Thread.join st.th
|
Thread.join st.th
|
||||||
| None -> ());
|
| None -> ());
|
||||||
|
|
||||||
|
(* start new bg thread *)
|
||||||
let active = Atomic.make true in
|
let active = Atomic.make true in
|
||||||
Atomic.set st
|
Atomic.set st
|
||||||
@@ Some
|
@@ Some
|
||||||
|
|
@ -61,11 +69,12 @@ let[@inline] unwrap_ = function
|
||||||
|
|
||||||
let retry_read_ fd f =
|
let retry_read_ fd f =
|
||||||
let ev = get_loop_exn_ () in
|
let ev = get_loop_exn_ () in
|
||||||
let rec loop () =
|
let[@unroll 1] rec loop () =
|
||||||
match f () with
|
match f () with
|
||||||
| res -> res
|
| res -> res
|
||||||
| exception
|
| exception
|
||||||
Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK | Unix.EINTR), _, _) ->
|
Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK | Unix.EINTR), _, _) ->
|
||||||
|
Trace_.message "read must wait";
|
||||||
let trigger = Picos.Trigger.create () in
|
let trigger = Picos.Trigger.create () in
|
||||||
Nanoev.on_readable ev fd trigger () (fun trigger () ->
|
Nanoev.on_readable ev fd trigger () (fun trigger () ->
|
||||||
Picos.Trigger.signal trigger);
|
Picos.Trigger.signal trigger);
|
||||||
|
|
@ -81,6 +90,7 @@ let retry_write_ fd f =
|
||||||
| res -> res
|
| res -> res
|
||||||
| exception
|
| exception
|
||||||
Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK | Unix.EINTR), _, _) ->
|
Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK | Unix.EINTR), _, _) ->
|
||||||
|
Trace_.message "write must wait";
|
||||||
let trigger = Picos.Trigger.create () in
|
let trigger = Picos.Trigger.create () in
|
||||||
Nanoev.on_writable ev fd trigger () (fun trigger () ->
|
Nanoev.on_writable ev fd trigger () (fun trigger () ->
|
||||||
Picos.Trigger.signal trigger);
|
Picos.Trigger.signal trigger);
|
||||||
|
|
@ -89,11 +99,20 @@ let retry_write_ fd f =
|
||||||
in
|
in
|
||||||
loop ()
|
loop ()
|
||||||
|
|
||||||
let read fd buf i len : int = retry_read_ fd (fun () -> Unix.read fd buf i len)
|
let read fd buf i len : int =
|
||||||
let accept fd = retry_read_ fd (fun () -> Unix.accept fd)
|
retry_read_ fd (fun () ->
|
||||||
|
Trace_.message "read";
|
||||||
|
Unix.read fd buf i len)
|
||||||
|
|
||||||
|
let accept fd =
|
||||||
|
retry_read_ fd (fun () ->
|
||||||
|
Trace_.message "accept";
|
||||||
|
Unix.accept fd)
|
||||||
|
|
||||||
let write fd buf i len : int =
|
let write fd buf i len : int =
|
||||||
retry_write_ fd (fun () -> Unix.write fd buf i len)
|
retry_write_ fd (fun () ->
|
||||||
|
Trace_.message "write";
|
||||||
|
Unix.write fd buf i len)
|
||||||
|
|
||||||
let connect fd addr = retry_write_ fd (fun () -> Unix.connect fd addr)
|
let connect fd addr = retry_write_ fd (fun () -> Unix.connect fd addr)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,6 +92,7 @@ module In = struct
|
||||||
|
|
||||||
class type t = In_buf.t
|
class type t = In_buf.t
|
||||||
|
|
||||||
|
(* FIXME: closed should be atomic *)
|
||||||
let of_unix_fd ?(close_noerr = false) ~closed ~(buf : Slice.t)
|
let of_unix_fd ?(close_noerr = false) ~closed ~(buf : Slice.t)
|
||||||
(fd : Unix.file_descr) : t =
|
(fd : Unix.file_descr) : t =
|
||||||
let eof = ref false in
|
let eof = ref false in
|
||||||
|
|
@ -197,7 +198,7 @@ module Unix_tcp_server_ = struct
|
||||||
TH.IO.TCP_server.stop = (fun () -> self.running <- false);
|
TH.IO.TCP_server.stop = (fun () -> self.running <- false);
|
||||||
running = (fun () -> self.running);
|
running = (fun () -> self.running);
|
||||||
active_connections =
|
active_connections =
|
||||||
(fun () -> Sem_.num_acquired self.sem_max_connections - 1);
|
(fun () -> Sem_.num_acquired self.sem_max_connections);
|
||||||
endpoint =
|
endpoint =
|
||||||
(fun () ->
|
(fun () ->
|
||||||
let addr, port = get_addr_ sock in
|
let addr, port = get_addr_ sock in
|
||||||
|
|
@ -207,7 +208,7 @@ module Unix_tcp_server_ = struct
|
||||||
after_init tcp_server;
|
after_init tcp_server;
|
||||||
|
|
||||||
(* how to handle a single client *)
|
(* how to handle a single client *)
|
||||||
let handle_client_unix_ (client_sock : Unix.file_descr)
|
let handle_client_ (client_sock : Unix.file_descr)
|
||||||
(client_addr : Unix.sockaddr) : unit =
|
(client_addr : Unix.sockaddr) : unit =
|
||||||
Log.debug (fun k ->
|
Log.debug (fun k ->
|
||||||
k "t[%d]: serving new client on %s"
|
k "t[%d]: serving new client on %s"
|
||||||
|
|
@ -237,7 +238,7 @@ module Unix_tcp_server_ = struct
|
||||||
|
|
||||||
Unix.set_nonblock sock;
|
Unix.set_nonblock sock;
|
||||||
while self.running do
|
while self.running do
|
||||||
match Unix.accept sock with
|
match EV.accept sock with
|
||||||
| client_sock, client_addr ->
|
| client_sock, client_addr ->
|
||||||
(* limit concurrency *)
|
(* limit concurrency *)
|
||||||
Sem_.acquire self.sem_max_connections;
|
Sem_.acquire self.sem_max_connections;
|
||||||
|
|
@ -247,7 +248,7 @@ module Unix_tcp_server_ = struct
|
||||||
ignore Unix.(sigprocmask SIG_BLOCK Sys.[ sigint; sighup ]);
|
ignore Unix.(sigprocmask SIG_BLOCK Sys.[ sigint; sighup ]);
|
||||||
self.new_thread (fun () ->
|
self.new_thread (fun () ->
|
||||||
try
|
try
|
||||||
handle_client_unix_ client_sock client_addr;
|
handle_client_ client_sock client_addr;
|
||||||
Log.debug (fun k ->
|
Log.debug (fun k ->
|
||||||
k "t[%d]: done with client on %s, exiting"
|
k "t[%d]: done with client on %s, exiting"
|
||||||
(Thread.id @@ Thread.self ())
|
(Thread.id @@ Thread.self ())
|
||||||
|
|
@ -269,14 +270,9 @@ module Unix_tcp_server_ = struct
|
||||||
(Printexc.raw_backtrace_to_string bt)));
|
(Printexc.raw_backtrace_to_string bt)));
|
||||||
if not Sys.win32 then
|
if not Sys.win32 then
|
||||||
ignore Unix.(sigprocmask SIG_UNBLOCK Sys.[ sigint; sighup ])
|
ignore Unix.(sigprocmask SIG_UNBLOCK Sys.[ sigint; sighup ])
|
||||||
| exception Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK), _, _)
|
|
||||||
->
|
|
||||||
(* wait for the socket to be ready, and re-enter the loop *)
|
|
||||||
ignore (Unix.select [ sock ] [] [ sock ] 1.0 : _ * _ * _)
|
|
||||||
| exception e ->
|
| exception e ->
|
||||||
Log.error (fun k ->
|
Log.error (fun k ->
|
||||||
k "Unix.accept raised an exception: %s" (Printexc.to_string e));
|
k "Unix.accept raised an exception: %s" (Printexc.to_string e))
|
||||||
Thread.delay 0.01
|
|
||||||
done;
|
done;
|
||||||
|
|
||||||
(* Wait for all threads to be done: this only works if all threads are done. *)
|
(* Wait for all threads to be done: this only works if all threads are done. *)
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,6 @@
|
||||||
(name nanoev_unix)
|
(name nanoev_unix)
|
||||||
(public_name nanoev.unix)
|
(public_name nanoev.unix)
|
||||||
(synopsis "Unix/select backend")
|
(synopsis "Unix/select backend")
|
||||||
(libraries nanoev unix))
|
(libraries
|
||||||
|
nanoev
|
||||||
|
unix))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,9 @@
|
||||||
let ( let@ ) = ( @@ )
|
open struct
|
||||||
let now_ : unit -> float = Unix.gettimeofday
|
module Trace_ = Nanoev.Trace_
|
||||||
|
|
||||||
|
let ( let@ ) = ( @@ )
|
||||||
|
let now_ : unit -> float = Unix.gettimeofday
|
||||||
|
end
|
||||||
|
|
||||||
(** Callback list *)
|
(** Callback list *)
|
||||||
type cbs =
|
type cbs =
|
||||||
|
|
@ -78,10 +82,12 @@ let clear (self : st) =
|
||||||
()
|
()
|
||||||
|
|
||||||
let wakeup_from_outside (self : st) : unit =
|
let wakeup_from_outside (self : st) : unit =
|
||||||
if not (Atomic.exchange self.wakeup_triggered true) then (
|
if not (Atomic.exchange self.wakeup_triggered true) then
|
||||||
|
let@ _sp =
|
||||||
|
Trace_.with_span ~__FILE__ ~__LINE__ "nanoev.wakeup-from-outside"
|
||||||
|
in
|
||||||
let b = Bytes.make 1 '!' in
|
let b = Bytes.make 1 '!' in
|
||||||
ignore (Unix.write self.wakeup_wr b 0 1 : int)
|
ignore (Unix.write self.wakeup_wr b 0 1 : int)
|
||||||
)
|
|
||||||
|
|
||||||
let get_fd_ (self : st) fd : per_fd =
|
let get_fd_ (self : st) fd : per_fd =
|
||||||
match Hashtbl.find self.fds fd with
|
match Hashtbl.find self.fds fd with
|
||||||
|
|
@ -92,6 +98,7 @@ let get_fd_ (self : st) fd : per_fd =
|
||||||
per_fd
|
per_fd
|
||||||
|
|
||||||
let on_readable self fd x y f : unit =
|
let on_readable self fd x y f : unit =
|
||||||
|
let@ _sp = Trace_.with_span ~__FILE__ ~__LINE__ "nanoev.on-readable" in
|
||||||
let@ self = with_lock_ self in
|
let@ self = with_lock_ self in
|
||||||
let per_fd = get_fd_ self fd in
|
let per_fd = get_fd_ self fd in
|
||||||
per_fd.r <- Sub (x, y, f, per_fd.r);
|
per_fd.r <- Sub (x, y, f, per_fd.r);
|
||||||
|
|
@ -99,6 +106,7 @@ let on_readable self fd x y f : unit =
|
||||||
if Atomic.get self.in_select then wakeup_from_outside self
|
if Atomic.get self.in_select then wakeup_from_outside self
|
||||||
|
|
||||||
let on_writable self fd x y f : unit =
|
let on_writable self fd x y f : unit =
|
||||||
|
let@ _sp = Trace_.with_span ~__FILE__ ~__LINE__ "nanoev.on-writable" in
|
||||||
let@ self = with_lock_ self in
|
let@ self = with_lock_ self in
|
||||||
let per_fd = get_fd_ self fd in
|
let per_fd = get_fd_ self fd in
|
||||||
per_fd.w <- Sub (x, y, f, per_fd.w);
|
per_fd.w <- Sub (x, y, f, per_fd.w);
|
||||||
|
|
@ -106,6 +114,7 @@ let on_writable self fd x y f : unit =
|
||||||
if Atomic.get self.in_select then wakeup_from_outside self
|
if Atomic.get self.in_select then wakeup_from_outside self
|
||||||
|
|
||||||
let run_after_s self time x y f : unit =
|
let run_after_s self time x y f : unit =
|
||||||
|
let@ _sp = Trace_.with_span ~__FILE__ ~__LINE__ "nanoev.run-after-s" in
|
||||||
let@ self = with_lock_ self in
|
let@ self = with_lock_ self in
|
||||||
let deadline = now_ () +. time in
|
let deadline = now_ () +. time in
|
||||||
Heap.insert self.timer (Timer { deadline; x; y; f });
|
Heap.insert self.timer (Timer { deadline; x; y; f });
|
||||||
|
|
@ -113,6 +122,7 @@ let run_after_s self time x y f : unit =
|
||||||
|
|
||||||
let recompute_if_needed (self : st) =
|
let recompute_if_needed (self : st) =
|
||||||
if not self.sub_up_to_date then (
|
if not self.sub_up_to_date then (
|
||||||
|
let@ _sp = Trace_.with_span ~__FILE__ ~__LINE__ "recompute-if-needed" in
|
||||||
self.sub_up_to_date <- true;
|
self.sub_up_to_date <- true;
|
||||||
self.sub_r <- [];
|
self.sub_r <- [];
|
||||||
self.sub_w <- [];
|
self.sub_w <- [];
|
||||||
|
|
@ -137,6 +147,7 @@ let rec perform_cbs = function
|
||||||
perform_cbs tail
|
perform_cbs tail
|
||||||
|
|
||||||
let step (self : st) : unit =
|
let step (self : st) : unit =
|
||||||
|
let@ _sp = Trace_.with_span ~__FILE__ ~__LINE__ "nanoev.unix.step" in
|
||||||
(* gather the subscriptions and timeout *)
|
(* gather the subscriptions and timeout *)
|
||||||
let timeout, sub_r, sub_w =
|
let timeout, sub_r, sub_w =
|
||||||
let@ self = with_lock_ self in
|
let@ self = with_lock_ self in
|
||||||
|
|
@ -152,6 +163,14 @@ let step (self : st) : unit =
|
||||||
(* enter [select] *)
|
(* enter [select] *)
|
||||||
Atomic.set self.in_select true;
|
Atomic.set self.in_select true;
|
||||||
let r_reads, r_writes, _ =
|
let r_reads, r_writes, _ =
|
||||||
|
let@ _sp =
|
||||||
|
Trace_.with_span ~__FILE__ ~__LINE__ "select" ~data:(fun () ->
|
||||||
|
[
|
||||||
|
"timeout", `Float timeout;
|
||||||
|
"reads", `Int (List.length sub_r);
|
||||||
|
"writes", `Int (List.length sub_w);
|
||||||
|
])
|
||||||
|
in
|
||||||
Unix.select (self.wakeup_rd :: sub_r) sub_w [] timeout
|
Unix.select (self.wakeup_rd :: sub_r) sub_w [] timeout
|
||||||
in
|
in
|
||||||
Atomic.set self.in_select false;
|
Atomic.set self.in_select false;
|
||||||
|
|
@ -174,8 +193,10 @@ let step (self : st) : unit =
|
||||||
|
|
||||||
List.iter
|
List.iter
|
||||||
(fun fd ->
|
(fun fd ->
|
||||||
let per_fd = Hashtbl.find self.fds fd in
|
if fd != self.wakeup_rd then (
|
||||||
ready_r := per_fd :: !ready_r)
|
let per_fd = Hashtbl.find self.fds fd in
|
||||||
|
ready_r := per_fd :: !ready_r
|
||||||
|
))
|
||||||
r_reads;
|
r_reads;
|
||||||
List.iter
|
List.iter
|
||||||
(fun fd ->
|
(fun fd ->
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
|
|
||||||
(tests
|
(tests
|
||||||
(names t1)
|
(names t1)
|
||||||
(libraries nanoev nanoev.unix threads))
|
(libraries nanoev nanoev.unix threads))
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue