Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Message slow to construct for small message #143

Closed
ggggggggg opened this issue Apr 13, 2017 · 2 comments
Closed

Message slow to construct for small message #143

ggggggggg opened this issue Apr 13, 2017 · 2 comments

Comments

@ggggggggg
Copy link
Contributor

See this thread for context. Consider the following code (requires PR #141). message takes about 140 ns, while Message takes 3400 ns. Something like message should be available or the performance of Message should be made comparable for small payloads.

using ZMQ, BenchmarkTools

function message(s)
  b = IOBuffer()
  write(b,s)
  m = Message(b.size)
  m[:]=b.data
  m
end

@benchmark message("1")
@benchmark Message("1")
@ggggggggg
Copy link
Contributor Author

I wrote a version of message with only one copy, which is a bit faster than the previous one. Then I benchmarked all 3 version (my two, plus ZMQ.Message) vs length of string. ZMQ.Message appears to win for strings longer than roughly 250 bytes. But I think there may be something else wrong, when I run the benchmark, it takes much longer to complete the portion for Message than for the other two versions, despite the fact that the sum of minimum times across all benchmarks is lower. Nonetheless, here is the plot I generated, followed by the code I used.

afasfaf

using ZMQ, BenchmarkTools, PyPlot
function Base.setindex!(m::Message, v, i::Integer)
    @boundscheck if i < 1 || i > length(m)
        throw(BoundsError())
    end
    unsafe_store!(pointer(m), v, i)
end
function message(x)
  m = Message(sizeof(x))
  mb = Base.AbstractIOBuffer(m,true,true,true,false,length(m))
  write(mb,x)
  m
end

function message_cp(s)
  b = IOBuffer()
  write(b,s)
  m = Message(b.size)
  m[:]=b.data
  m
end

function benchmark_length(f,l)
  s = randstring(l)
  b=@benchmark $f($s) evals=10
  minimum(b.times)
end
lengths = 2.^(0:24)
message_mtimes = [benchmark_length(message,l) for l in lengths]
message_cp_mtimes = [benchmark_length(message_cp,l) for l in lengths]
Message_mtimes = [benchmark_length(Message,l) for l in lengths]

figure()
plot(lengths, message_mtimes, label="message")
plot(lengths, message_cp_mtimes, label="message_cp")
plot(lengths, Message_mtimes, label="Message")
xlabel("bytes")
ylabel("minimum time to construct (ns)")
legend(loc="best")
xscale("log")
yscale("log")

@JamesWrigley
Copy link
Member

I'm closing this because we now have the internal _MessageRef type that makes a copy and is used by default in Sockets.send():

julia> using ZMQ, BenchmarkTools

julia> @benchmark Message("1")
BenchmarkTools.Trial: 7228 samples with 200 evaluations.
 Range (min … max):  625.230 ns …  6.416 ms  ┊ GC (min … max):  0.00% … 86.68%
 Time  (median):       1.019 μs              ┊ GC (median):     0.00%
 Time  (mean ± σ):     3.423 μs ± 97.551 μs  ┊ GC (mean ± σ):  44.81% ±  1.65%

  ▁█▇▅▄▃▃▂▂▁▁                                                  ▁
  █████████████▆▆▆▆▆▆▆▆▆▄▆▆▄▆▄▄▄▄▄▆▅▄▅▄▅▅▄▃▅▅▄▅▄▁▄▃▃▄▃▄▁▃▃▄▃▃▄ █
  625 ns        Histogram: log(frequency) by time      12.1 μs <

 Memory estimate: 704 bytes, allocs estimate: 10.

julia> @benchmark ZMQ._MessageRef("1")
BenchmarkTools.Trial: 10000 samples with 997 evaluations.
 Range (min … max):  18.201 ns …  10.954 μs  ┊ GC (min … max):  0.00% … 99.47%
 Time  (median):     20.397 ns               ┊ GC (median):     0.00%
 Time  (mean ± σ):   30.878 ns ± 152.317 ns  ┊ GC (mean ± σ):  15.03% ±  4.67%

  ▂▅▅▇█▅▁ ▁▃                               ▂▄▄▄▄▄▂▂▁▂▂▂▃▂▁▁    ▂
  ███████████▆▅▅▆▆▄▃▄▃▄▃▄▃▁▄▁▁▁▄▃▄▁▁▃▃▄▄▃▁▃█████████████████▇▇ █
  18.2 ns       Histogram: log(frequency) by time      47.1 ns <

 Memory estimate: 80 bytes, allocs estimate: 1.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants