{"action":"created","issue":{"url":"https://api.github.com/repos/zeromq/libzmq/issues/1417","labels_url":"https://api.github.com/repos/zeromq/libzmq/issues/1417/labels{/name}","comments_url":"https://api.github.com/repos/zeromq/libzmq/issues/1417/comments","events_url":"https://api.github.com/repos/zeromq/libzmq/issues/1417/events","html_url":"https://github.com/zeromq/libzmq/pull/1417","id":84770971,"number":1417,"title":"Zero copy message receive in v2_decoder","user":{"login":"jens-auer","id":9391718,"avatar_url":"https://avatars.githubusercontent.com/u/9391718?v=3","gravatar_id":"","url":"https://api.github.com/users/jens-auer","html_url":"https://github.com/jens-auer","followers_url":"https://api.github.com/users/jens-auer/followers","following_url":"https://api.github.com/users/jens-auer/following{/other_user}","gists_url":"https://api.github.com/users/jens-auer/gists{/gist_id}","starred_url":"https://api.github.com/users/jens-auer/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jens-auer/subscriptions","organizations_url":"https://api.github.com/users/jens-auer/orgs","repos_url":"https://api.github.com/users/jens-auer/repos","events_url":"https://api.github.com/users/jens-auer/events{/privacy}","received_events_url":"https://api.github.com/users/jens-auer/received_events","type":"User","site_admin":false},"labels":[],"state":"closed","locked":false,"assignee":null,"milestone":null,"comments":6,"created_at":"2015-06-03T21:04:19Z","updated_at":"2015-06-09T11:58:04Z","closed_at":"2015-06-03T21:09:03Z","pull_request":{"url":"https://api.github.com/repos/zeromq/libzmq/pulls/1417","html_url":"https://github.com/zeromq/libzmq/pull/1417","diff_url":"https://github.com/zeromq/libzmq/pull/1417.diff","patch_url":"https://github.com/zeromq/libzmq/pull/1417.patch"},"body":"This patch utilizes the zero-copy constructor of msg_t to construct message directly using the memory from the reception buffer. This trades a small increase in memory consumption for reduced allocations and memcopy operations.\r\n\r\nThe main idea of the patch is to use a reference-counted buffer allocated for every reception operation and then let messages use this buffer directly as their storage, increasing the reference count. When a msg_t object is destructed, it decreases the reference count and deletes the buffer if it reaches zero. To completely skip malloc calls, msg_t needs to be changed to not allocate a content_t object in msg_t::init_data, but store the members of content_t itself.\r\n\r\nIn order to not reimplement the decoder_t hierarchy completely, the buffer allocation is implemented as policy class which has to be a base-class of v2_decoder because decoder_t allocates the buffer in its constructor.\r\n\r\nThe result of these changes can be seen with a profiler. Prior to the change, receiving a message > 64 bytes needs 3 memcopy calls (flags, size and message data) and one malloc call per message. With the patch, this reduces to 2 memcopy calls (flags and size) and one malloc call per reception block of 8192 bytes. In the throughput test receiving 100,000 messages, malloc calls reduced from ~100,000 to 2,500. Throughput values increased by ~40%.\r\n\r\nHowever, since this is a delicate change, I would hope that somebody with a good test library can validate it. I only have basic test setup which sends messages to a reactor and checks the content. Also make check passed all tests."},"comment":{"url":"https://api.github.com/repos/zeromq/libzmq/issues/comments/110330979","html_url":"https://github.com/zeromq/libzmq/pull/1417#issuecomment-110330979","issue_url":"https://api.github.com/repos/zeromq/libzmq/issues/1417","id":110330979,"user":{"login":"rodgert","id":120839,"avatar_url":"https://avatars.githubusercontent.com/u/120839?v=3","gravatar_id":"","url":"https://api.github.com/users/rodgert","html_url":"https://github.com/rodgert","followers_url":"https://api.github.com/users/rodgert/followers","following_url":"https://api.github.com/users/rodgert/following{/other_user}","gists_url":"https://api.github.com/users/rodgert/gists{/gist_id}","starred_url":"https://api.github.com/users/rodgert/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/rodgert/subscriptions","organizations_url":"https://api.github.com/users/rodgert/orgs","repos_url":"https://api.github.com/users/rodgert/repos","events_url":"https://api.github.com/users/rodgert/events{/privacy}","received_events_url":"https://api.github.com/users/rodgert/received_events","type":"User","site_admin":false},"created_at":"2015-06-09T11:58:04Z","updated_at":"2015-06-09T11:58:04Z","body":"This may over complicate things, but could you introduce a new message\nvariant 'zcmsg' in the union that has the zero copy properties and fall\nback to a traditional lmsg when the client explicitly requests a copy?\n\nOn Tuesday, June 9, 2015, Jens Auer <notifications@github.com> wrote:\n\n> Hi,\n>\n> Thanks for the investigation. I think i know where the error is and is\n> quite obvious now that the change in msg_t to remove content_t cannot work\n> this way.  I have an idwa for a fix that still eliminates the memoy\n> allocation, but i have to investigate this a little more.\n>\n> Best wishes,\n>\n>   Jens\n>\n> -------- Ursprüngliche Nachricht --------\n> Von: Min RK <notifications@github.com\n> <javascript:_e(%7B%7D,'cvml','notifications@github.com');>>\n> Datum: 09.06.2015 0:08 (GMT+01:00)\n> An: zeromq/libzmq <libzmq@noreply.github.com\n> <javascript:_e(%7B%7D,'cvml','libzmq@noreply.github.com');>>\n> Cc: Jens Auer <jens.auer-githun@betaversion.net\n> <javascript:_e(%7B%7D,'cvml','jens.auer-githun@betaversion.net');>>\n> Betreff: Re: [libzmq] Zero copy message receive in v2_decoder (#1417)\n>\n> Further narrowing it down: the reference counter is not shared between two\n> copies. The copy appears to get a copy of the original's counter, so they\n> both start with a value of 2, but decrementing the first counter does not\n> decrement the second, causing the refcount to stop at 1 instead of 0, so\n> the message is never freed.\n>\n> My C++ allocation-fu is weak, but fixing this so the actual counter\n> instance is shared after msg::copy should do the trick.\n>\n> —\n> Reply to this email directly or view it on GitHub.\n>\n> —\n> Reply to this email directly or view it on GitHub\n> <https://github.com/zeromq/libzmq/pull/1417#issuecomment-110252898>.\n>\n"}}