On Wed, 26 Apr 2023 at 11:55, Maciek Machnikowski <mac...@machnikowski.net>
wrote:

> On 4/21/2023 6:46 PM, Erez wrote:
> >
> >
> > On Fri, 21 Apr 2023 at 17:27, Maciek Machnikowski
> > <mac...@machnikowski.net <mailto:mac...@machnikowski.net>> wrote:
> >
> >     On 4/21/2023 1:25 PM, Erez wrote:
> >     >
> >     >
> >     > On Thu, 20 Apr 2023 at 19:01, Maciek Machnikowski
> >     > <mac...@machnikowski.net <mailto:mac...@machnikowski.net>
> >     <mailto:mac...@machnikowski.net <mailto:mac...@machnikowski.net>>>
> >     wrote:
> >     >
> >     >     Add option to run callback that when the PMC agent receives
> >     >     signaling messages.
> >     >
> >     >     Signed-off-by: Maciek Machnikowski <mac...@machnikowski.net
> >     <mailto:mac...@machnikowski.net>
> >     >     <mailto:mac...@machnikowski.net <mailto:
> mac...@machnikowski.net>>>
> >     >     ---
> >     >      pmc_agent.c | 21 +++++++++++++++++++--
> >     >      pmc_agent.h |  7 +++++++
> >     >      2 files changed, 26 insertions(+), 2 deletions(-)
> >     >
> >     >     diff --git a/pmc_agent.c b/pmc_agent.c
> >     >     index 62d1a86..ef4e1bb 100644
> >     >     --- a/pmc_agent.c
> >     >     +++ b/pmc_agent.c
> >     >     @@ -42,6 +42,7 @@ struct pmc_agent {
> >     >             bool dds_valid;
> >     >             int leap;
> >     >             int pmc_ds_requested;
> >     >     +       bool signaling_cb_ena;
> >     >             bool stay_subscribed;
> >     >             int sync_offset;
> >     >             int utc_offset_traceable;
> >     >     @@ -127,6 +128,7 @@ static int run_pmc(struct pmc_agent *node,
> int
> >     >     timeout, int ds_id,
> >     >      #define N_FD 1
> >     >             struct pollfd pollfd[N_FD];
> >     >             int cnt, res;
> >     >     +       bool skip_cb;
> >     >
> >     >             while (1) {
> >     >                     pollfd[0].fd = pmc_get_transport_fd(node->pmc);
> >     >     @@ -178,9 +180,18 @@ static int run_pmc(struct pmc_agent
> >     *node, int
> >     >     timeout, int ds_id,
> >     >                             node->pmc_ds_requested = 0;
> >     >                             return RUN_PMC_NODEV;
> >     >                     }
> >     >     -               if (res <= 0 ||
> >     >     +
> >     >     +               /* Skip callback if message is not management
> */
> >     >     +               skip_cb = (res <= 0) ? true : false;
> >     >     +
> >     >     +               /* Run the callback on signaling messages if
> >     >     configured */
> >     >     +               if (node->signaling_cb_ena && (msg_type(*msg)
> ==
> >     >     SIGNALING)) {
> >     >
> >     >
> >     > I would add res == 0, to save time here.
> >     >
> >     > You can have
> >     >            if (res < 0) {
> >     >                skip_cb = false;
> >     >            } else if(res == 0) {
> >     >                   if (node->signaling_cb_ena && (msg_type(*msg) ==
> >     > SIGNALING)) {
> >     >                        skip_cb = true;
> >     >                   } else {
> >     >                       skip_cb = false;
> >     >                   }
> >     >             } else {
> >     >                skip_cb = true;
> >     >             }
> >     >
> >     > This code saves you from checking 'node->signaling_cb_ena' if res
> >     is not 0.
> >     > 'res' is a local variable, 'node->signaling_cb_ena' is referred
> >     through> a pointer, so its fetch time is much bigger.
> >
> >     This is not true. It compiles to a single ASM line even without any
> >     optimizations enabled:
> >
> >
> > This looks like arm64. There are other CPUs beside ARM.
> > And in assembler it is hard to "see" how long it takes to load
> > 'signaling_cb_ena' from node unless it is in the memory cache.
>
> It's similar on x86.
>                 /* Run the callback on signaling messages if configured */
>                 if (res == 0 && node->signaling_cb_ena &&
>  475:   83 7d f4 00             cmpl   $0x0,-0xc(%rbp)
>  479:   75 24                   jne    49f <run_pmc+0x1e0>
> >47b:   48 8b 45 d8             mov    -0x28(%rbp),%rax
> >47f:   0f b6 40 30             movzbl 0x30(%rax),%eax
> >483:   84 c0                   test   %al,%al
>  485:   74 18                   je     49f <run_pmc+0x1e0>
>                     msg_type(*msg) == SIGNALING) {
>  487:   48 8b 45 c8             mov    -0x38(%rbp),%rax
>  48b:   48 8b 00                mov    (%rax),%rax
>  48e:   48 89 c7                mov    %rax,%rdi
>  491:   e8 39 fc ff ff          callq  cf <msg_type>
>
> Do you know any architecture that's different than this?
>

There are about 12 different architectures, not to mention 32 and 64 bit
and old 8 and 16 bits.
But this group is not about machine code and assembler.
I suggest we leave it out. This argument does not fly anywhere.


>
> >
> >
> >                     /* Skip callback if message is not management */
> >                     skip_cb = (res <= 0) ? true : false;
> >      54c:   b94047e0        ldr     w0, [sp, #68]
> >      550:   7100001f        cmp     w0, #0x0
> >      554:   1a9fc7e0        cset    w0, le
> >      558:   39013fe0        strb    w0, [sp, #79]
> >             /* Run the callback on signaling messages if configured */
> >                     if (node->signaling_cb_ena && (msg_type(*msg) ==
> >     SIGNALING)) {
> >      55c:   f94017e0        ldr     x0, [sp, #40]
> >     >560:   3940c000        ldrb    w0, [x0, #48]
> >      564:   7100001f        cmp     w0, #0x0
> >      568:   540000e0        b.eq    584 <run_pmc+0x210>  // b.none
> >      56c:   f9400fe0        ldr     x0, [sp, #24]
> >      570:   f9400000        ldr     x0, [x0]
> >      574:   97fffeea        bl      11c <msg_type>
> >      578:   7100301f        cmp     w0, #0xc
> >      57c:   54000041        b.ne <http://b.ne>    584 <run_pmc+0x210>
> >     // b.any
> >                             skip_cb = false;
> >      580:   39013fff        strb    wzr, [sp, #79]
> >                     }
> >
> >
> >     Adding a check for res adds 3 more ASM instructions:
> >
> >
> > But save loading `signaling_cb_ena` if you mainly use
> management messages!
> >
> >
> >
> >                     /* Run the callback on signaling messages if
> >     configured */
> >                     if (res == 0 && node->signaling_cb_ena &&
> >     >55c:   b94047e0        ldr     w0, [sp, #68]
> >     >560:   7100001f        cmp     w0, #0x0
> >     >564:   54000161        b.ne <http://b.ne>    590 <run_pmc+0x21c>
> >     // b.any
> >      568:   f94017e0        ldr     x0, [sp, #40]
> >      56c:   3940c000        ldrb    w0, [x0, #48]
> >      570:   7100001f        cmp     w0, #0x0
> >      574:   540000e0        b.eq    590 <run_pmc+0x21c>  // b.none
> >                         msg_type(*msg) == SIGNALING) {
> >      578:   f9400fe0        ldr     x0, [sp, #24]
> >      57c:   f9400000        ldr     x0, [x0]
> >      580:   97fffee7        bl      11c <msg_type>
> >                     if (res == 0 && node->signaling_cb_ena &&
> >      584:   7100301f        cmp     w0, #0xc
> >      588:   54000041        b.ne <http://b.ne>    590 <run_pmc+0x21c>
> >     // b.any
> >                             skip_cb = false;
> >      58c:   39013fff        strb    wzr, [sp, #79]
> >                     }
> >
> >     Thanks,
> >     Maciek
> >
> >
> > Again you can simply reuse `res` and have a small code and also faster
> code.
> > I do not understand why you are afraid of using reuse `res`.
> >
> > I only point on optimization. I assume that most cases are
> > management messages, and testing the signaling flag for all packets does
> > not help.
> >
> > If you want a better solution, you replace in run_pmc() :
> >
> > type = msg_type(msg);
> > switch (type) {
> >  case SIGNALING:
> >        res = node->signaling_cb_ena ? 2 : 0;
> >        break;
> > case MANAGEMENT:
> >         res = is_msg_mgt(msg);
> >         break;
> > default:
> >        break
> > }
> >
> > And remove the 'msg_type(msg) != MANAGEMENT' from is_msg_mgt().
>
> Optimizing run_pmc is beyond the scope of my patch. I'll add a check for
> res==0 before checking node->signaling_cb_ena, but I hardly believe
> it'll have any performance benefit.
>


It is your call.
As you change the code, you can also optimize your change.
Nothing is holy with the current implementation.
I understand you want to do "minimum".
But the current code is also optimized code.



>
> If you run the run_pmc infrequently, this check will not matter, as it
> takes only a couple of ns to read from memory. You'll spend much more
> time on function calls preceding this check.
>

Yes, this code does not run much.
This is a more basic question. Do optimize only a hard real time code.
And leave all the rest, heavy and badly optimized?
Again, I understand why you think minimal changes are more pretty.
It is your patch, you and Richard decide. I only share my opinion.


>
> If you call run_pmc constantly, then this location will most likely be
> cached, as it holds a static value, and it will still not negatively
> impact the performance. To see any difference you'd need to hit a ton of
> messages/second - is there any use case that requires it?
>

Again, not all architectures are using catch memory.
Please do not make assumptions.
Same as machine code, this is not the group.
And yes, this is not hard real time.
I do not ask for a very complicated optimization.
Just write good code, please.

Erez



>
> Thanks
> Maciek
>
> >
> > Assembler rarely helps to understand speed and size of code.
> > Especially code that runs on multiple CPUs as free software.
> >
> >
> >
> >
> >
> > Erez
> >
> >
> >
> >
> >     > This code is bigger, but you do not want to reuse the 'res'
> variable.
> >     >
> >     >
> >     >
> >     >     +                       skip_cb = false;
> >     >     +               }
> >     >     +
> >     >     +               if (skip_cb ||
> >     >                         node->recv_subscribed(node->recv_context,
> >     *msg,
> >     >     ds_id) ||
> >     >     -                   management_tlv_id(*msg) != ds_id) {
> >     >     +                   (res == 1 && management_tlv_id(*msg) !=
> >     ds_id)) {
> >     >
> >     >
> >     > This part is OK.
> >     >
> >     > Erez
> >     >
> >     >
> >     >
> >     >                             msg_put(*msg);
> >     >                             *msg = NULL;
> >     >                             continue;
> >     >     @@ -430,3 +441,9 @@ bool pmc_agent_utc_offset_traceable(struct
> >     >     pmc_agent *agent)
> >     >      {
> >     >             return agent->utc_offset_traceable;
> >     >      }
> >     >     +
> >     >     +void pmc_agent_enable_signaling_cb(struct pmc_agent *agent,
> bool
> >     >     enable)
> >     >     +{
> >     >     +       agent->signaling_cb_ena = enable;
> >     >     +}
> >     >     +
> >     >     diff --git a/pmc_agent.h b/pmc_agent.h
> >     >     index 2fb1cc8..9ae37f7 100644
> >     >     --- a/pmc_agent.h
> >     >     +++ b/pmc_agent.h
> >     >     @@ -170,4 +170,11 @@ int pmc_agent_update(struct pmc_agent
> >     *agent);
> >     >       */
> >     >      bool pmc_agent_utc_offset_traceable(struct pmc_agent *agent);
> >     >
> >     >     +/**
> >     >     + * Enables or disables callback on signaling messages
> >     >     + * @param agent  Pointer to a PMC instance obtained via @ref
> >     >     pmc_agent_create().
> >     >     + * @param enable - if set to true, callback will be called on
> >     >     signaling msgs
> >     >     + */
> >     >     +void pmc_agent_enable_signaling_cb(struct pmc_agent *agent,
> bool
> >     >     enable);
> >     >     +
> >     >      #endif
> >     >     --
> >     >     2.30.2
> >     >
> >
>
_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to