On Wed May 31 08:42:46 2017, felipe@felipegasper.com wrote:
Show quoted text> … assuming that that user wants to make only one N::D::R query at a
> time.
That assumption was baked into Net::DNS long ago.
Show quoted text> Consider the case of having two concurrent queries. There’s no
> documented way currently to receive an event when the first of these
> is available to bgread(). The only way is to roll one’s own select()
> loop--despite the admonishments in the documentation--and hope for the
> best.
>
> *That* could be solved by accepting multiple handles to bgbusy(),
> which would seem pretty simple to implement? But, again, without being
> able to specify a wait time, N::D::R is assuming that the application
> has nothing better to do than to wait an arbitrary length of time for
> that event.
Out of scope for the present discussion, but willing to consider better ideas.
Show quoted text> There’s another issue: N::D::R creates an extra IO::Select and
> select() system call on every bgread(). So if I do:
>
> 1 while $resolver->bgbusy($handle);
> $packet = $resolver->bgread($handle);
>
> … that’s actually doing at two select()s and creating at least two
> IO::Select objects.
See below
Show quoted text> Why use IO::Select in the first place, btw? Are there portability
> advantages?
As I pointed out earlier, there is other information added to the object. Extending IO::Select is easier than writing another package from scratch.
Show quoted text> Those could be cached within the handle to avoid
> recreating them.
Tempting, but that creates indirect self-references which prevents memory from being reclaimed. That bring in its wake either DESTROY() methods to disentangle the objects, or using weak references which one needs to be careful not to copy lest they regain their strength.
Show quoted text> > I assume you are really arguing for a zero dwell time on the
> > IO::Select rather than a wish to specify an arbitrary value.
You did not answer the question:
Would you be happy (happier?) with a zero dwell time in bgbusy(), assuming the tight loop objection can be overcome?
Yes or No?
Show quoted text> I actually hadn’t noticed that bgread() includes a zero-wait select().
> That seems to contradict the documentation, which speaks of a timeout?
> That might be useful to document if it’s intended that people can do
> bgread() as a zero-wait check on the socket.
Forget about select() and zero waits, they are implementation detail.
Concentrate on the abstract object model.
The (Resolver) documentation is quite clear that if you have a handle from bgsend(), then you can use bgread() to obtain the response. Nowhere does it say that you need to test bgbusy() first. (FYI Older versions did need to test bgisready().)
Look more carefully at the code:
sub bgread {
while (&bgbusy) { next; } # side effect: TCP retry
&_bgread;
}
sub _bgread {
my ( $self, $handle ) = @_;
return unless $handle;
my $appendix = ${*$handle}{net_dns_bg};
my ( $expire, $query, $read ) = @$appendix;
return shift(@$read) if ref($read);
return unless IO::Select->new($handle)->can_read(0);
my $peer = $handle->peerhost;
$self->answerfrom($peer);
bgread() contains a bgbusy() loop before calling _bgread(), so it is ok to do bgread() straight after bgsend().
The can_read(0) in _bgread() is needed to decide if the bgbusy() loop ended because a packet arrived or the timeout interval expired.
Show quoted text> Anyhow. My team currently implements an 0.05 wait time; neither the
> code’s original author nor I are sure of the original rationale.
I guess the author's rationale was much the same as mine, tight busy loops.
Just for fun, I removed the 200ms dwell in bgbusy() and measured the speed of the loop running on my laptop. 68000 per second!
Show quoted text> >> But it only allows checking one background query at a time.
> >> bgselect()
> >> would allow checking multiple queries concurrently.
> >
> > Sure, but it does not fit easily into the Net::DNS model as presently
> > realised.
>
> Is there a git mirror of the repo that can accept pull requests? I’ve
> forgotten the svn-fu that used to be my daily grind. :)
>
> I’d be willing to take a crack at adding this if you like.
Too many users depend on this distro, so uncontrolled code bashing is not really an option.
If you want to redesign this bit of the resolver, the way to start is to write some outline documentation with example use-cases. The idea is to capture the abstract object model from the user perspective.
Email me directly to discuss further.
Show quoted text> >> Sorry … they’re “at least” sockets. :) select() works on them,
> >> anyhow;
> >> unfortunately, that’s the only way right now to use them with this
> >> degree of flexibility.
> >
> > These "sockets" can transform themselves from UDP into TCP if a reply
> > packet is truncated and the query is retried automatically. A Do-It-
> > Yourself select scheme will get very confused when that happens.
> >
>
> So far we’re safe: we do a manual select(), then bgbusy() on the
> evented handles, then bgread(). It’s definitely not ideal, but it’s
> the only way for now, and our application needs a more efficient path
> than waiting on a single handle at a time. Obviously we’d love to use
> upstream logic instead.
It would be useful for us to know a bit of detail about what your application is trying to do.