Commit 0f697fe2 authored by Martin Sustrik's avatar Martin Sustrik

ZMQII-56: Avoid allocation of chunk in yqueue.hpp by keeping a spare one

parent 72bbc92b
...@@ -11,6 +11,7 @@ Erich Heine ...@@ -11,6 +11,7 @@ Erich Heine
Erik Rigtorp Erik Rigtorp
Frank Denis Frank Denis
George Neill George Neill
Joe Thornber
Jon Dyte Jon Dyte
Kamil Shakirov Kamil Shakirov
Martin Hurton Martin Hurton
......
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
#include <stddef.h> #include <stddef.h>
#include "err.hpp" #include "err.hpp"
#include "atomic_ptr.hpp"
namespace zmq namespace zmq
{ {
...@@ -37,9 +38,9 @@ namespace zmq ...@@ -37,9 +38,9 @@ namespace zmq
// pop on the empty queue and that both threads don't access the same // pop on the empty queue and that both threads don't access the same
// element in unsynchronised manner. // element in unsynchronised manner.
// //
// T is the type of the object in the queue // T is the type of the object in the queue.
// N is granularity of the queue (how many pushes have to be done till // N is granularity of the queue (how many pushes have to be done till
// actual memory allocation is required) // actual memory allocation is required).
template <typename T, int N> class yqueue_t template <typename T, int N> class yqueue_t
{ {
...@@ -69,6 +70,10 @@ namespace zmq ...@@ -69,6 +70,10 @@ namespace zmq
begin_chunk = begin_chunk->next; begin_chunk = begin_chunk->next;
delete o; delete o;
} }
chunk_t *sc = spare_chunk.xchg (NULL);
if (sc)
delete sc;
} }
// Returns reference to the front element of the queue. // Returns reference to the front element of the queue.
...@@ -94,8 +99,13 @@ namespace zmq ...@@ -94,8 +99,13 @@ namespace zmq
if (++end_pos != N) if (++end_pos != N)
return; return;
end_chunk->next = new (std::nothrow) chunk_t; chunk_t *sc = spare_chunk.xchg (NULL);
zmq_assert (end_chunk->next); if (sc) {
end_chunk->next = sc;
} else {
end_chunk->next = new (std::nothrow) chunk_t;
zmq_assert (end_chunk->next);
}
end_chunk = end_chunk->next; end_chunk = end_chunk->next;
end_pos = 0; end_pos = 0;
} }
...@@ -107,7 +117,13 @@ namespace zmq ...@@ -107,7 +117,13 @@ namespace zmq
chunk_t *o = begin_chunk; chunk_t *o = begin_chunk;
begin_chunk = begin_chunk->next; begin_chunk = begin_chunk->next;
begin_pos = 0; begin_pos = 0;
delete o;
// 'o' has been more recently used than spare_chunk,
// so for cache reasons we'll get rid of the spare and
// use 'o' as the spare.
chunk_t *cs = spare_chunk.xchg (o);
if (cs)
delete cs;
} }
} }
...@@ -131,6 +147,11 @@ namespace zmq ...@@ -131,6 +147,11 @@ namespace zmq
chunk_t *end_chunk; chunk_t *end_chunk;
int end_pos; int end_pos;
// People are likely to produce and consume at similar rates. In
// this scenario holding onto the most recently freed chunk saves
// us from having to call new/delete.
atomic_ptr_t<chunk_t> spare_chunk;
// Disable copying of yqueue. // Disable copying of yqueue.
yqueue_t (const yqueue_t&); yqueue_t (const yqueue_t&);
void operator = (const yqueue_t&); void operator = (const yqueue_t&);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment