> From: Ferruh Yigit [mailto:ferruh.yi...@amd.com]
> Sent: Friday, 3 May 2024 17.46
> 
> For stats reset, use an offset instead of zeroing out actual stats values,
> get_stats() displays diff between stats and offset.
> This way stats only updated in datapath and offset only updated in stats
> reset function. This makes stats reset function more reliable.
> 
> As stats only written by single thread, we can remove 'volatile' qualifier
> which should improve the performance in datapath.
> 
> While updating around, 'igb_stats' parameter renamed as 'stats'.
> 
> Signed-off-by: Ferruh Yigit <ferruh.yi...@amd.com>
> ---
> Cc: Mattias Rönnblom <mattias.ronnb...@ericsson.com>
> Cc: Stephen Hemminger <step...@networkplumber.org>
> Cc: Morten Brørup <m...@smartsharesystems.com>
> 
> This update triggered by mail list discussion [1].
> 
> [1]
> https://inbox.dpdk.org/dev/3b2cf48e-2293-4226-b6cd-
> 5f4dd3969...@lysator.liu.se/
> 
> v2:
> * Remove wrapping check for stats
> 
> v3:
> * counter and offset put into same struct per stats
> * Use atomic load / store for stats values
> ---

Note: My comments below relate to software PMDs only.

Design for the following invariants:
1. "counter" may increase at any time. (So stopping forwarding is not required.)
2. "counter" may not decrease.
3. "offset" is always <= "counter".

So:

Stats_get() must read "offset" before "counter"; if "counter" races to increase 
in the mean time, it doesn't hurt. Stats_get() is a relatively "cold" function, 
so barriers etc. are acceptable.

Assuming that stats_add() lazy-writes "counter"; if stats_get() reads an old 
value, its result will be slightly off, but not negative.

Similarly for stats_reset(), which obviously reads "counter" before writing 
"offset"; if "counter" races to increase in the mean time, the too low "offset" 
will not cause negative stats from stats_get().


And a requested change for performance:

> +struct stats {
> +     uint64_t counter;
> +     uint64_t offset;
> +};

The "offset" is cold.
Stats_add(), which is the only hot function, only touches "counter".

Instead of having a struct with {counter, offset}, I strongly prefer having 
them separate.
E.g. as a struct defining the set of statistics (e.g. pkts, bytes, errors), 
instantiated once for the counters (in a hot zone of the device data structure) 
and once for the offsets (in a cold zone of the device data structure).
There could be variants of this "set of statistics" struct, e.g. one for RX and 
a different one for TX. (Each variant would be instantiated twice, once for 
counters, and once for offsets.)

Reply via email to