diff --git a/benchmark/functions_benchmark.jl b/benchmark/functions_benchmark.jl index 0019189..91324fd 100644 --- a/benchmark/functions_benchmark.jl +++ b/benchmark/functions_benchmark.jl @@ -32,7 +32,7 @@ end """ -Make and get a reference to the server side of HTS-JCE websocket connection. +Make connection and get a reference to the HTS side of HTS-JCE connection. Assumes a server is already running. """ function get_hts_jce() @@ -65,7 +65,7 @@ function get_hts_bce() hts = Union{WebSocket, String}("") browser ="" opened, browser = open_a_browser() - # Launch the next browser in line. + # Launch the next browser in line. if opened zlog(id, "BCE in, ", browser, " will be connecting to HTS. Getting reference...") zflush() @@ -82,17 +82,18 @@ function get_hts_bce() return hts, browser end """ -Collect n (samples) of serverlatency and clientlatency. -Also calculate derived sizes - serverbandwidth, clientbandwidth, serverspeeds, clientspeed -Starts a new JSE-HTS connection for every evaluation (call). +Send n messages of length messagesize HTS-JCE and back. + -> id, serverlatencies, clientlatencies +Starts and closes a new HTS-JCE connection every function call. +In the terminology of BenchmarkTools, a call is a sample +consisting of n evaluations. """ function HTS_JCE(n, messagesize) id = "HTS_JCE" zlog(id, "Warming up, compiling") zflush() hts = get_hts_jce() - if !isa(hts, WebSocket) + if !isa(hts, WebSocket) msg = " could not get websocket reference" clog(id, msg) error(id * msg) @@ -130,7 +131,7 @@ function HTS_JCE(n, messagesize) end # We must read from the websocket in order for it to respond to # a closing message from JCE. It's also nice to yield to the async server - # so it can exit from it's handler. + # so it can exit from it's handler and release the websocket reference. isopen(hts) && read(hts) yield() serverlatencies = receivetimes - sendtimes @@ -138,8 +139,8 @@ function HTS_JCE(n, messagesize) return id, serverlatencies, clientlatencies end """ -Use the next browser in line, starts a new HTS-BCE connection and collects n evaluations. -This is one sample. +Use the next browser in line, start a new HTS-BCE connection and collect n evaluations. +This is one sample. Returns browser name and vectors with n rows: # t1 Send 0, receive 0, measure time interval # t2 Send 0, receive 0 twice, measure time interval @@ -152,9 +153,9 @@ function HTS_BCE(n, x) zflush() msg = "" (hts, browser) = get_hts_bce() - if browser == "" + if browser == "" msg = "Could not find and open more browser types" - elseif !isa(hts, WebSocket) + elseif !isa(hts, WebSocket) msg = " could not get ws reference from " * browser * " via HTS" end if msg != "" @@ -213,16 +214,16 @@ function HTS_BCE(n, x) end " -Measured time interval vectors [ns] -> client and server speeds, bandwidth [ns/b] -x is message size [b]. +Constant message size [b], measured time interval vectors [ns] + -> server and client speeds, server and client bandwidth [ns/b] " -function serverandclientspeeds(x, serverlatencies, clientlatencies) - serverspeeds = serverlatencies / x - clientspeeds = clientlatencies / x +function serverandclientspeeds(messagesize, serverlatencies, clientlatencies) + serverspeeds = serverlatencies / messagesize + clientspeeds = clientlatencies / messagesize n = length(serverspeeds) - serverbandwidth = sum(serverlatencies) / (n * x) - clientbandwidth = sum(clientlatencies) / (n * x) + serverbandwidth = sum(serverlatencies) / (n * messagesize) + clientbandwidth = sum(clientlatencies) / (n * messagesize) serverspeeds, clientspeeds, serverbandwidth, clientbandwidth end @@ -234,20 +235,20 @@ x is message size [b]. function serverandclientspeeds_indirect(x, t1, t2, t3, t4) # assuming a measured time interval consists of # t(x) = t0s + t0c + a*x + b*x - # where + # where # t(x) measured time at the server - # t0s initial serverlatency, for a "zero length" message + # t0s initial serverlatency, for a "zero length" message # t0c initial clientlatency, for a "zero length" message # x message length [b] # a marginal server speed [ns/b] # b marginal client speed [ns/b] # - # + # # t1 = t0s + t0c Send 0, receive 0, measure t1 # t2 = t0s + 2t0c Send 0, receive 0 twice, measure t2 # t3 = t0s + t0c + a*x Send x, receive 0, measure t3 # t4 = t0s + 2t0c + a*x + b*x Send x, receive 0, receive x, measure t4 - # + # # hence, t0s = 2t1 - t2 t0c = -t1 + t2 @@ -259,20 +260,20 @@ function serverandclientspeeds_indirect(x, t1, t2, t3, t4) serverspeeds = t0s / x + a clientspeeds = t0c / x + b n = length(serverspeeds) - serverbandwidth = sum(serverspeeds) / n + serverbandwidth = sum(serverspeeds) / n clientbandwidth = sum(clientspeeds) / n return serverspeeds, clientspeeds, serverbandwidth, clientbandwidth end -## Note these shorthand function require input symbols defined at module-level -## (not in a local scope) +## Note that the shorthand plot functions below require input symbols +## that are defined at module-level (not in a local scope) -"Shorthand for generating a time series lineplot in REPL" +"Generate a time series lineplot" lp(sy::Symbol) = lineplot(collect(1:length(eval(sy))), eval(sy), title = String(sy), width = displaysize(STDOUT)[2]-20, canvas = AsciiCanvas) -"Return multiple time series lineplots with a common title prefix" +"Generate a vector of time series lineplots with a common title prefix" function lp(symbs::Vector{Symbol}, titleprefix) map(symbs) do sy pl = lp(sy) @@ -280,12 +281,13 @@ function lp(symbs::Vector{Symbol}, titleprefix) end end -"Shorthand for generating an x-y lineplot in REPL" -function lp(syx::Symbol, syy::Symbol) +"Generate an x-y lineplot in REPL" +function lp(syx::Symbol, syy::Symbol) lpl = lineplot(eval(syx), eval(syy), title = String(syy), width = displaysize(STDOUT)[2]-20, canvas = AsciiCanvas) xlabel!(lpl, String(syx)) end -"Return multiple x-y lineplots with a common title prefix" + +"Generate a vector of x-y lineplots with a common title prefix" function lp(syxs::Vector{Symbol}, syys::Vector{Symbol}, titleprefix) map(zip(syxs, syys)) do pair pl = lp(pair[1], pair[2]) @@ -293,14 +295,8 @@ function lp(syxs::Vector{Symbol}, syys::Vector{Symbol}, titleprefix) end end -"Shorthand for generating an x-y scatterplot in REPL" -function sp(syx::Symbol, syy::Symbol) +"Generate an x-y scatterplot" +function sp(syx::Symbol, syy::Symbol) spl = scatterplot(eval(syx), eval(syy), title = String(syy), width = displaysize(STDOUT)[2]-15, canvas = DotCanvas) xlabel!(spl, String(syx)) -end - -"Shorthand for generating a densityplot in REPL" -function dp(syx::Symbol, syy::Symbol) - dpl = densityplot(eval(syx), eval(syy), title = String(syy), color = :red, width = displaysize(STDOUT)[2]-15) - xlabel!(dpl, String(syx)) -end +end \ No newline at end of file diff --git a/benchmark/ws_hts.jl b/benchmark/ws_hts.jl index 7ce3b15..c949303 100644 --- a/benchmark/ws_hts.jl +++ b/benchmark/ws_hts.jl @@ -48,6 +48,16 @@ function acceptholdws(http) # If the ugrade is successful, just hold the reference and thread # of execution. Other tasks may do useful things with it. WebSockets.upgrade(http) do ws + if length(WEBSOCKET) > 0 + # unexpected behaviour. + if isclosed(WEBSOCKET[1]) + pop!(WEBSOCKET) + else + msg = " A websocket is already open. Not accepting the attempt at opening more." + clog(id, :red, msg);zflush() + return + end + end push!(WEBSOCKET, ws) zlog(id, ws);zflush() t1 = now() + WSMAXTIME diff --git a/benchmark/ws_jce.jl b/benchmark/ws_jce.jl index f4b193b..52632cd 100644 --- a/benchmark/ws_jce.jl +++ b/benchmark/ws_jce.jl @@ -20,14 +20,20 @@ const SERVER = "ws://127.0.0.1:$(PORT)" const CLOSEAFTER = Base.Dates.Second(30) """ -Opens a client, echoes with optional delay, an integer in milliseconds. +Opens a client, echoes with an optional delay, an integer in milliseconds. Stores time records for received messages and before sending messages. -Specify delay in milliseconds by sending a message on the websocket: +Specify the delay in milliseconds by sending a message on the websocket: send(ws_jce, "delay|15") -Echoes any message except "exit" and "delay" +Echoes any message except "exit" and "delay". -At exit or after CLOSEAFTER, sends one message containing two vectors of -timestamps [ns].AbstractTrees +Delays to reading, in the websocket use situation, would be caused by usefully spent +calculation time between reads. However, they may be interpreted by the underlying protocol +as transmission problems and cause large slowdowns. Hence the interest in testing +with delays. A countermeasure for optimizing speed might be to run a websocket +reading function in a parallel, not asyncronous process, putting messages on an internal queue. + +At exit or after CLOSEAFTER, this function sends one message containing two vectors of +timestamps [ns]. """ function echowithdelay_jce() # This will be run in a worker process. Even so, individual console log @@ -56,7 +62,7 @@ function echowithdelay_jce() end end " -Handler for client websocket, defined by echowithdelay +Handler for client websocket, defined by echowithdelay_jce " function _jce(ws) id = "_jce" @@ -109,8 +115,6 @@ function _jce(ws) clog(id, :green, " Exit, close websocket.") zflush() # Exiting this function starts a closing handshake - # from this side (HTTP.jl:39). The other side must read in - # in order for this to proceed smoothly. nothing end end # module diff --git a/examples/chat_explore.jl b/examples/chat_explore.jl index 0838a70..68f63f7 100644 --- a/examples/chat_explore.jl +++ b/examples/chat_explore.jl @@ -12,7 +12,7 @@ named functions may improve error message readability. =# - +# TODO fix errors and style # Globals, where used in functions will change the type global lastreq = 0 @@ -238,8 +238,14 @@ end info("Start HTTP server on port $(HTTPPORT)") litas_newtype = @schedule HTTP.listen(server_def_newtype, "127.0.0.1", UInt16(HTTPPORT)) -# TODO replace with improvement from 'close websocket'. +""" +This stops the servers using InterruptExceptions. +""" function closefromoutside() + # Throwing exceptions can be slow. This function also + # starts a task which seems to not exit and free up + # its memory properly. HTTP.listen offers an alternative + # method. See HTTP.listen > tcpref if isdefined(:litas_newtype) @schedule Base.throwto(litas_newtype, InterruptException()) end @@ -251,4 +257,6 @@ function closefromoutside() end end end + + nothing \ No newline at end of file