[nanomsg] Re: Bindings for Golang

  • From: Martin Sustrik <sustrik@xxxxxxxxxx>
  • To: Örjan Persson <o@xxxxxxxx>
  • Date: Tue, 14 May 2013 21:50:15 +0200

On 14/05/13 17:58, Örjan Persson wrote:
On Mon, May 13, 2013 at 11:25 PM, Martin Sustrik<sustrik@xxxxxxxxxx>  wrote:
Btw, I've written a blog post with some tips for writing nanomsg bindings.
If you haven't seen it, maybe it'll help in some minor way:

http://www.250bpm.com/blog:21

Ah, looks very similar to the document[1] I've followed so far. ;)

[1] http://nanomsg.org/development-bindings.html

Right. It's basically the same text. I've first written the blog post, then realised it would be helpful to have the instructions directly on the website. Then I forgot about making the copy :)

Where can I find more information about the domain? Is SP_RAW only
useful when you want to create a new protocol?

This is basically the domain parameter as defined in POSIX socket(3) function. The idea is to keep the nanomsg API as close as possible to POSIX so when one day the messaging functionality is moved to OS kernel, it would be easy to migrate the applications.

In POSIX, domain parameter is used to specify the networking stack to use (AF_UNIX, AF_INET, AF_INET6 etc.) nanomsg adds two new constants AF_SP_RAW to specify that SP stack without the end-to-end functionality is needed. That's useful for creating intermediate nodes in the topologies. Then there's AF_SP to specify that full SP stack with end-to-end functionality is required.

As it is now, I've
hidden that from the user except when calling NewSocket. Eg. for a pub
socket, you call NewPubSocket, and there's no way to specify either
the domain or the protocol.

I would suggest using constants for specifying socket types instead of dedicated functions. The reason is that new protocols may be added to the library. Is such case the new socket types become immediately available via nn_symbol() function -- no need to change or even re-compile the binding. If, on the other hand, you opt for NewPubSocket etc. you'll have to update the binding every time new socket type is added.

I've been thinking of removing it from
NewSocket too, and expose a NewRawSocket method. Feels like not a lot
of users will use the raw socket if they're intended as I understand
it.

It's up to you. New domains are not likely to be added, so hard-coding the two is an option.

In the bindings I've created, a user could still use the returned
raw socket and wrap it up as a pub socket, eg.
&nanomsg.PubSocket{rawSocket}, giving the user the possibility to do
whatever a "normal" pub socket can do.

I am not sure I understand. You cannot change the domain of the socket in runtime. If you create a raw socket (i.e. one without end-to-end functionality), there's no way to turn it into full-blown end-to-end socket.

The document mentioned pitfalls for zero-copy. I am utilizing
zero-copy. I didn't want to ask before because I haven't decided if I
like it or not. From some very non-scientifically benchmarks, the
overhead of adding what Go calls "finalizer" (basically a destructor)
is higher than allocating the memory when the message is<1k.

Zero-copy makes sense only for large messages. Say 1MB or more. If you are not concerned about such scenarios, simply ignore the whole zero-copy part.

And my final question was about poller. There won't be a poller
similar to the one exposed in zmq? My next item on my TODO list is to
try to integrate the file descriptors into Go somehow. I hope it's
possible. :)

What I've tried to do is to provide the native file descriptors (NN_SNDFD, NN_RCVFD) that can be used for polling. Each language should use its idiosyncratic way to do the actual polling. So, in this case, the question is: How does Go poll on multiple TCP sockets? The binding should use the same mechanism to poll on nanomsg sockets.

Hope this helps,
Martin

Other related posts: