[Click] Notifier::upstream_empty_signal is always active

Ashish Sharma ashishs.sharma at gmail.com
Fri May 29 20:40:29 EDT 2009


Hi Cliff,
Thanks for the quick response. A couple of clarifications : It is not the
pull function's performance that is killing me. In my case, the check to
determine whether a queue is valid or not seems to be the bottleneck (but
only when called in a loop by the scheduler multiple times. I know this as
when I timed the valid/invalid function it takes about 2-3 micros to get in
and out of the function, but it takes a while, when the scheduler invokes
the same function in a loop, in the absence of a reliable empty_notifier,
just as it would call a pull function which returns null if the queue is
empty). So as an optimization my plan was to do this - first determine which
input queues are non-empty and then on those queues perform my valid/invalid
check which seems to be a rather expensive operation.

To give you a sense of how this is effecting my performance, the scenario is
Node A sends a message to Node B and expects a response back immediately. If
Node B is using a simple prioscheduler, assuming all queues are valid, it
takes less than 1ms for the Node B to respond. However, if I use my
scheduler, it takes on an average about 20ms (worst case is upto 40
sometimes). So I need a way to only call the valid/invalid operation when I
am sure that a queue is non-empty.

The problem with simply calling the pull function is that I do not want to
deal with the pulled packet if this queue is not valid. I want to have a
simple test operation. I tried writing an extended queue element (TestQueue)
that has a public function that tests whether the queue is empty. But here
is what happened - when my scheduler calls

if (_signals[k] &&  (false == input(k).test_empty()))

instead of

if (_signals[k] && (p = input(k).pull()))

, the compiler complains saying error: 'const class Element::Port' has no
member named 'test_empty' and even casting (TestQueue
*)input(k)).test_empty() does not work.

So I am guessing pull and push are special click functions that can be
invoked on a port, but other functions cannot.

I am now trying to work by creating a new notifier, although I must admit
this is all new territory for me. Any thoughts?

Sorry for the extra long query. Don't know if this is adding to the public
knowledge at all, but the problem is very relevant to me:)

Ashish


On Fri, May 29, 2009 at 11:50 AM, Cliff Frey <cliff at meraki.com> wrote:

> Hi Ashish,
>
> First off, I am very suspicious that the performance here is actually the
> issue.  Assuming you have queues hooked up directly to this element, calling
> pull() and having it return NULL should just be a very simple/fast function
> call.  So really I think that you are talking about changing from a function
> call to an indirect pointer read or something.
>
> Or does it really bother you that click is using 100% of the CPU even
> though it isn't getting anything done?  This rarely matters, but I guess if
> you are using the machine for other things as well, or are
> power-constrained.
>
> In any case, if you are actually that performance sensitive, then you could
> either build one element that contained all of the queues, or you could keep
> a Vector of Queue objects that are upstream, and just directly look at their
> sizes rather than calling pull()... but I doubt that it would be any faster.
>
> If you are just bothered by the CPU utilization (this will not likely make
> any performance difference, or might slow things down slightly, but can
> still be nice if you are on a shared system), then you need to have a
> notifier in your element, and override the cast() function to look for
> Notifier::EMPTY_NOTIFIER (like notifierqueue.cc) and correctly keep that
> notifier in the right state.
>
> Cliff
>
> On Fri, May 29, 2009 at 2:05 AM, Ashish Sharma <ashishs.sharma at gmail.com>wrote:
>
>> Hi all,
>> I am trying to write a modified scheduler (based on prioscheduler). The
>> new
>> scheduler maintains a list of permissible queues from which the scheduler
>> can draw packets from. So if there are n input queues to the scheduler, at
>> any point of time only a subset of the queues are "valid" and the
>> scheduler
>> must check only these queues to see if they have any packets to transmit.
>> This subset of "valid" queues changes with time.
>>
>> I am relying on the Notifier::upstream_empty_signal to check if the input
>> queues are non-empty. But, it turns out that the signal is active most of
>> the time and is only reset after the pull function is called which returns
>> null in case of an empty queue. Since the valid/invalid test is an
>> expensive
>> one, what I would like is for the Notifier signal to act like a test
>> function, so I only perform the valid/invalid operation if a queue is
>> non-empty. Further, in case the queue is not empty but belongs to the set
>> of
>> "invalid" queues, I do not want to put the packet back at the head of the
>> queue (of which I cannot think of a simple way of doing from within the
>> scheduler element).
>>
>> One solution is that I extend the Queue element to include a test function
>> and along with the signal check the test function.
>>
>> Is there a clean way to make the Notifier signal active only when the
>> input
>> queue is really non-empty and not a false alarm?
>>
>> Thank you for your time. I would really appreciate any suggestions or
>> thoughts.
>>
>> Thanks
>> Ashish
>> _______________________________________________
>> click mailing list
>> click at amsterdam.lcs.mit.edu
>> https://amsterdam.lcs.mit.edu/mailman/listinfo/click
>>
>
>


More information about the click mailing list