-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Added function for lazy message reading per #222 #224
Conversation
As I think is my normal review mode, i will go over each change in detail and then (hopefully) see the bigger picture and moan about that :-) |
return nil, err | ||
} else if n < 12 { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Think 12 is better as a constant, headerSize ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Any reason to choose private vs making it public?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
return nil, err
- } else if n < 12 {
Any reason to choose private vs making it public?
Could as well be public.
Looks pretty good. Actually hooking it up in the lib itself is another PR (which is really fine) |
Should I continue in this one to reuse Msg.Unpack properly or finish this one and open new later? |
Fixing this up first and then a new PR is fine. Does this function need to be exported though? |
Yeah... it's good function for convenience of those who write clients. Sometimes you only need packets with answers and without this function you'd go and parse all fields in authority/additional even if your client does not care about them. |
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
Ok. Works for me. /Miek Miek Gieben |
Well... Here is what I got... I still followed with changing all we discussed in one PR, since there is not much. Logic is still same as it was in ReadMsg. I'm not sure there is any good in pursuing creation of a function that's not reserving such large buffers... In TCP it's probably doable, but in UDP things must be loaded in one Read call; it's really not possible to change... |
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
Ah yeah. I see what you mean... you can't do a partial read and then |
Last patch shows how I see it could be done for TCP. 64K is very large buffer I agree. dns.Conn.Read becomes less useful here since it expects to read everything in one pre-allocated buffer in TCP. |
// | ||
// Note that this function would not be able to report TSIG error or | ||
// check it got actual DNS payload. | ||
func (co *Conn) ReadMsgBytes(hdr *Header) ([]byte, error) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So... What if we would really makes this only read 12 (or 14 in case of tcp) bytes and let it return the Conn, the bytes read and an error? Maybe the buffer should also by given to the function, so it is really without any internal allocations? So if you get an error you just discard and write FormErr (maybe from within the lib already). If thinks look OK we can parse the bytes to a real header and assemble the packet...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Once you read from UDP rest is discarded. You could not really read again there so you end up buffering and faking ability to read which is slow.
http://golang.org/src/net/udpsock_posix.go?s=1547:1620#L53
http://golang.org/src/net/fd_unix.go#L256
then from rcvfrom(2):
All three routines return the length of the message on successful
completion. If a message is too long to fit in the supplied buffer,
excess bytes may be discarded depending on the type of socket
the message is received from.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
+// Note that this function would not be able to report TSIG error or
+// check it got actual DNS payload.
+func (co *Conn) ReadMsgBytes(hdr *Header) ([]byte, error) {Once you read from UDP rest is discarded. You could not really read again there so you end up buffering and faking ability to read which is slow.
http://golang.org/src/net/udpsock_posix.go?s=1547:1620#L53
http://golang.org/src/net/fd_unix.go#L256then from rcvfrom(2):
All three routines return the length of the message on successful completion. If a message
is too long to fit in the supplied buffer, excess bytes may be discarded depending on the
type of socket the message is received from.
Grrrr :( So what would be the win then, this is the typical space/time trade
off? So the allocation of memory still happens, the only thing that you shortcut
is the potentially slowish parsing of the rest of the packet. I rather spend
cycles on making that faster, or fail ealier.
/Miek
Miek Gieben
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReadMsgBytes -> ReadMsgHeader as a function name.
I'll experiment with profiler a bit and let you know. IMO net lib has limits by itself plus fact that dns lib built around strings... Allocs for message reading are probably not worst thing there.... |
I created new clientbench branch and put some test code there... As expected, UDP is close, almost no difference but TCP is faster in new implementation (not reserving 64K each time):
With pprof and web -cum BenchmarkName it looks that most CPU time was still on syscalls... and pack/unpack StructValue; I decided to stub all of those, wrote small fake net.Conn for that... (second commit in that branch)... I also changed UDPSize to 4096 and run it with benchtime=10s to make sure I'll have small CPU expenses visible (paranoid Alex). Here is what it looks like for "web -cum ReadMsg" only on new client test:
You can see there is almost no time spent where you think we can win something. |
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
Ack. Yep, that points to something different. |
But convinience that I was asking for in #222 is already there plus small bonus for TCP... Maybe you can merge this one? (I understand if not...) as of performance, could be separate effort to look at different places but the need of reserving smallish structures with new(...) (or &Name{}) and work with strings is what could be hard to deal with... |
[ Quoting notifications@github.com in "Re: [dns] Added function for lazy m..." ]
Yes, I will. But I first want to take another look.
No, indeed. Having just strings make it easy to work with. /Miek Miek Gieben |
return m, err | ||
} | ||
|
||
// ReadMsgBytes reads DNS packet, parses and fills wire header (passing nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ReadMsgBytes reads a DNS message, parses it and populates hdr (when hdr is not nil)
} | ||
|
||
// ReadMsgBytes reads DNS packet, parses and fills wire header (passing nil | ||
// would cause skipping that). Returns message in byte format to parse with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It return the rest of the message as a byte slice to pasrse with Msg.Unpack later on.
Thanks for careful review... I decided not to wait on your comments, I think I followed most of your recommendations here. |
Ack, two naming nits. But it fix those shortly. |
Added function for lazy message reading per #222
No description provided.