From 9881a08068a9f1773c16d1de27ac9109044809e8 Mon Sep 17 00:00:00 2001 From: captchanjack Date: Sun, 30 Jan 2022 12:35:49 +1100 Subject: [PATCH] [REFACTOR] Speed up bulk string parser and flush! using readbytes!, rename internal functions --- Project.toml | 2 +- src/client.jl | 6 +++--- src/protocol.jl | 48 ++++++++++++++++++++++++++---------------------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/Project.toml b/Project.toml index 0ddd9c7..2c171a5 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "Jedis" uuid = "b89ccfe0-2c5f-46f6-b89b-da3e1c2e286f" authors = ["Jack Chan "] -version = "0.2.8" +version = "0.2.9" [deps] MbedTLS = "739be429-bea8-5141-9913-cc70e7f3736d" diff --git a/src/client.jl b/src/client.jl index e0b4855..891ee65 100644 --- a/src/client.jl +++ b/src/client.jl @@ -237,9 +237,9 @@ end Reads and discards any bytes that remain unread in the client socket. """ function flush!(client::Client) - while bytesavailable(client.socket) > 0 - recv(client.socket) - end + nb = bytesavailable(client.socket) + buffer = Vector{UInt8}(undef, nb) + readbytes!(client.socket, buffer, nb) end """ diff --git a/src/protocol.jl b/src/protocol.jl index 623c06b..e5537b5 100644 --- a/src/protocol.jl +++ b/src/protocol.jl @@ -39,48 +39,52 @@ function resp(command::AbstractArray) return "$(RedisType.array)$(n)$(CRLF)" * r end -function handle_simple_string(_, x) +function parse_simple_string(_, x) return x end -function handle_integer(_, x) +function parse_integer(_, x) return parse(Int64, x) end -function handle_error(_, x) +function parse_error(_, x) err_type, err_msg = split(x, ' '; limit=2) return RedisError(err_type, err_msg) end -function handle_bulk_string(io, x) +function parse_bulk_string(io, x) if x == "-1" return nothing end - x = parse(Int, x) - r = "" - - while length(r) < x + 2 - r *= readline(io; keep=true) - end - - return r[1:end-2] + x = parse(Int, x) + 2 + buffer = Vector{UInt8}(undef, x) + readbytes!(io, buffer, x) + return String(buffer[1:end-2]) end -function handle_array(io, x) +function parse_array(io, x) if x == "0" return [] end return [recv(io) for _ in 1:parse(Int64, x)] end -const RESPHandler = Dict{Char,Function}( - '+' => handle_simple_string, - '-' => handle_error, - ':' => handle_integer, - '$' => handle_bulk_string, - '*' => handle_array -) +function resp_parser(b::Char)::Function + if b == '+' + return parse_simple_string + elseif b == '-' + return parse_error + elseif b == ':' + return parse_integer + elseif b == '$' + return parse_bulk_string + elseif b == '*' + return parse_array + else + throw(RedisError("INVALIDBYTE", "Parser for byte '$b' does not exist.")) + end +end """ recv(io::Union{TCPSocket,Base.GenericIOBuffer}) @@ -94,8 +98,8 @@ function recv(io::Union{TCPSocket,Base.GenericIOBuffer}) return nothing end - handler = RESPHandler[line[1]] - return handler(io, line[2:end]) + parser = resp_parser(line[1]) + return parser(io, line[2:end]) end """