On 3/20/26 11:56 AM, Waiman Long wrote:
>> diff --git a/mm/memcontrol.c b/mm/memcontrol.c
>> --- a/mm/memcontrol.c
>> +++ b/mm/memcontrol.c
>> @@ -548,20 +548,20 @@ struct memcg_vmstats {
>> * rstat update tree grow unbounded.
>> *
>> * 2) Flush the stats synchronously on reader side only when there
are more than
>> - * (MEMCG_CHARGE_BATCH * nr_cpus) update events. Though this
optimization
>> - * will let stats be out of sync by atmost (MEMCG_CHARGE_BATCH
* nr_cpus) but
>> - * only for 2 seconds due to (1).
>> + * (MEMCG_CHARGE_BATCH * (ilog2(nr_cpus) + 1)) update events.
Though this
>> + * optimization will let stats be out of sync by up to that
amount but only
>> + * for 2 seconds due to (1).
> Is this description accurate regarding the maximum out of sync amount?
> Looking at memcg_rstat_updated(), updates are buffered locally on
each CPU
> up to MEMCG_CHARGE_BATCH - 1 before they are added to the global
> vmstats->stats_updates counter.
> Because memcg_vmstats_needs_flush() only checks the global counter,
could
> N CPUs each buffer MEMCG_CHARGE_BATCH - 1 updates without triggering a
> synchronous flush?
> If so, wouldn't the actual worst-case out-of-sync error be
> N * (MEMCG_CHARGE_BATCH - 1) + vmstats_flush_threshold, which remains
> linear with the number of CPUs rather than scaling logarithmically?
Good point, the worst case scenario can indeed be worse than that. I
will update the comment accordingly.
Looking at the code again, the hidden charge in memcg_stock should only
affect memory.current, not memory.stat. There is nothing to add to the
worst case situation.
Cheers,
Longman