Bug 199169

Summary: [patch] zone "UMA Zones" has bigger size than need
Product: Base System Reporter: luke.tw
Component: kernAssignee: Dmitry Chagin <dchagin>
Status: Closed FIXED    
Severity: Affects Only Me CC: dchagin
Priority: --- Keywords: patch
Version: CURRENT   
Hardware: Any   
OS: Any   
Attachments:
Description Flags
UMA Zones size patch none

Description luke.tw 2015-04-05 10:05:34 UTC
Created attachment 155194 [details]
UMA Zones size patch

It calculates the size for per cpu cache with (mp_maxid + 1 ). 
This allocates space with one extra struct uma_cache.

* before patch
 % vmstat -z | grep Zone
UMA Zones:             1152,      0,     196,       2,     196,   0,   0

* after patch
% vmstat -z | grep Zone
UMA Zones:             1024,      0,     196,       2,     196,   0,   0
Comment 1 Dmitry Chagin freebsd_committer freebsd_triage 2015-04-05 16:50:53 UTC
hm, mp_maxid is a max cpu id. on my 8 threaded cpu mp_maxid is 7.
Comment 2 luke.tw 2015-04-06 03:35:07 UTC
hi, Dmitry,

Thanks for your feedback.
That's right, but there is already one uma_cache in the struct uma_zone.
Let me do an experiment on sleepq_zone. 
I have 4-core cpu and the mp_maxid is 3. 
(kgdb) p mp_maxid
$1 = 3

The size of all per-cpu cache in sleepq_zone is 640 bytes.
(kgdb) p sleepq_zone
$2 = 0xfffff80002bb8000
(kgdb) p sleepq_zone->uz_cpu
$3 = 0xfffff80002bb8200
(kgdb) p masterzone_z->uz_size - (0xfffff80002bb8200 - 0xfffff80002bb8000)
$4 = 640

So, there are total 5 elements in the uz_cpu array
(kgdb) p 640 / sizeof(struct uma_cache)
$5 = 5

Only the first 4 elements are used. 
(kgdb) p sleepq_zone->uz_cpu[0]
$6 = {uc_freebucket = 0x0, uc_allocbucket = 0xfffff80002bb1c00, uc_allocs = 73, uc_frees = 0}
(kgdb) p sleepq_zone->uz_cpu[1]
$7 = {uc_freebucket = 0x0, uc_allocbucket = 0xfffff8000516a800, uc_allocs = 18, uc_frees = 0}
(kgdb) p sleepq_zone->uz_cpu[2]
$8 = {uc_freebucket = 0x0, uc_allocbucket = 0xfffff80004747c00, uc_allocs = 18, uc_frees = 0}
(kgdb) p sleepq_zone->uz_cpu[3]
$9 = {uc_freebucket = 0x0, uc_allocbucket = 0xfffff800047a1c00, uc_allocs = 36, uc_frees = 0}
(kgdb) p sleepq_zone->uz_cpu[4]
$10 = {uc_freebucket = 0x0, uc_allocbucket = 0x0, uc_allocs = 0, uc_frees = 0}
Comment 3 Dmitry Chagin freebsd_committer freebsd_triage 2015-04-06 17:06:59 UTC
(In reply to luke.tw from comment #2)

Yes, I see. 

It would be nice to add db_show_zone DDB method and use a now unused uma_print_zone with their counterparts.
Comment 4 commit-hook freebsd_committer freebsd_triage 2015-04-06 18:46:08 UTC
A commit references this bug:

Author: dchagin
Date: Mon Apr  6 18:45:42 UTC 2015
New revision: 281162
URL: https://svnweb.freebsd.org/changeset/base/281162

Log:
  Properly calculate "UMA Zones" per cpu cache size. Avoid allocating
  an extra struct uma_cache since the struct uma_zone already has one.

  PR:		199169
  Submitted by:	luke.tw gmail com
  MFC after:	1 week

Changes:
  head/sys/vm/uma_core.c
Comment 5 commit-hook freebsd_committer freebsd_triage 2015-04-15 05:13:49 UTC
A commit references this bug:

Author: dchagin
Date: Wed Apr 15 05:13:42 UTC 2015
New revision: 281543
URL: https://svnweb.freebsd.org/changeset/base/281543

Log:
  MFC r281162, r281451:

  Use flexible array for per cpu uma_cache to avoid allocating
  an extra struct uma_cache.

  PR:		199169

Changes:
_U  stable/10/
  stable/10/sys/vm/uma_int.h
Comment 6 Dmitry Chagin freebsd_committer freebsd_triage 2015-04-18 18:47:02 UTC
committed, thanks.