@@ -171,10 +171,6 @@ class IOPriority(enum.IntEnum):
171
171
svmem = namedtuple (
172
172
'svmem' , ['total' , 'available' , 'percent' , 'used' , 'free' ,
173
173
'active' , 'inactive' , 'buffers' , 'cached' , 'shared' , 'slab' ])
174
- # psutil.zfs_arc_stats()
175
- szfsarc = namedtuple (
176
- 'szfsarc' , ['enabled' , 'min' , 'max' , 'compressed' , 'uncompressed' ,
177
- 'size' , 'header' , 'anon' , 'mfu' , 'mru' , 'other' ])
178
174
# psutil.disk_io_counters()
179
175
sdiskio = namedtuple (
180
176
'sdiskio' , ['read_count' , 'write_count' ,
@@ -419,15 +415,13 @@ def calculate_avail_vmem(mems):
419
415
return int (avail )
420
416
421
417
422
- def virtual_memory (include_zfs_arc : bool = False ):
418
+ def virtual_memory ():
423
419
"""Report virtual memory stats.
424
420
This implementation mimics procps-ng-3.3.12, aka "free" CLI tool:
425
421
https://gitlab.com/procps-ng/procps/blob/
426
422
24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L778-791
427
423
The returned values are supposed to match both "free" and "vmstat -s"
428
424
CLI tools.
429
- If specifying the `include_zfs_arc` parameter, the implementation mimics
430
- "htop" CLI tool instead of "free" CLI tool.
431
425
"""
432
426
missing_fields = []
433
427
mems = {}
@@ -529,29 +523,7 @@ def virtual_memory(include_zfs_arc: bool = False):
529
523
# 24fd2605c51fccc375ab0287cec33aa767f06718/proc/sysinfo.c#L764
530
524
avail = free
531
525
532
- # ZFS ARC memory consumption is not reported by /proc/meminfo.
533
- # Specifying `include_zfs_arc` will include reclaimable ZFS ARC
534
- # memory in the returned values.
535
- # N.B. this will make psutil match the output of "htop" instead
536
- # of "free" CLI tool.
537
- # See:
538
- # https://www.reddit.com/r/zfs/comments/ha0p7f/understanding_arcstat_and_free/
539
- # https://github.com/openzfs/zfs/issues/10255
540
- if include_zfs_arc :
541
- zfs = zfs_arc_stats ()
542
-
543
- # When accounting for zfs memory, we need to keep track of "shared"
544
- # So "used" memory is more relevant than "available"
545
- used += shared
546
- cached -= shared
547
- if zfs .enabled :
548
- shrinkable_size = max (zfs .size - zfs .min , 0 )
549
- used -= shrinkable_size
550
- cached += shrinkable_size
551
- avail += shrinkable_size
552
- percent = usage_percent (used , total , round_ = 1 )
553
- else :
554
- percent = usage_percent ((total - avail ), total , round_ = 1 )
526
+ percent = usage_percent ((total - avail ), total , round_ = 1 )
555
527
556
528
# Warn about missing metrics which are set to 0.
557
529
if missing_fields :
@@ -631,19 +603,11 @@ def swap_memory():
631
603
return _common .sswap (total , used , free , percent , sin , sout )
632
604
633
605
634
- def zfs_arc_stats ( ):
635
- """Return ZFS ARC (Adaptive Replacement Cache) stats."""
636
- missing_fields = []
606
+ def apply_zfs_arcstats ( vm_stats : svmem ):
607
+ """Apply ZFS ARC (Adaptive Replacement Cache) stats to
608
+ input virtual memory call results"""
637
609
mems = {}
638
610
639
- def get_if_available (key ):
640
- try :
641
- return mems [key ]
642
- except KeyError :
643
- missing_fields .append (key )
644
- return 0
645
-
646
-
647
611
with open_binary ('%s/spl/kstat/zfs/arcstats' % get_procfs_path ()) as f :
648
612
for line in f :
649
613
fields = line .split ()
@@ -653,44 +617,35 @@ def get_if_available(key):
653
617
# Not a key: value line
654
618
continue
655
619
656
- zfs_min = get_if_available (b'c_min' )
657
- zfs_max = get_if_available (b'c_max' )
658
- zfs_compressed = get_if_available (b'compressed_size' )
659
- zfs_uncompressed = get_if_available (b'uncompressed_size' )
660
- zfs_size = get_if_available (b'size' )
661
- zfs_header = get_if_available (b'hdr_size' )
662
- dbuf_size = get_if_available (b'dbuf_size' )
663
- dnode_size = get_if_available (b'dnode_size' )
664
- bonus_size = get_if_available (b'bonus_size' )
665
- zfs_anon = get_if_available (b'anon_size' )
666
- zfs_mfu = get_if_available (b'mfu_size' )
667
- zfs_mru = get_if_available (b'mru_size' )
668
-
669
- zfs_enabled = zfs_size > 0
670
- zfs_other = dbuf_size + dnode_size + bonus_size if all ([dbuf_size , dnode_size , bonus_size ]) else 0
671
-
672
- # Warn about missing metrics which are set to 0.
673
- if missing_fields :
674
- msg = "%s memory stats couldn't be determined and %s set to 0" % (
675
- ", " .join (missing_fields ),
676
- "was" if len (missing_fields ) == 1 else "were" ,
677
- )
620
+ try :
621
+ zfs_min = mems [b'c_min' ]
622
+ zfs_size = mems [b'size' ]
623
+ except KeyError :
624
+ msg = ("ZFS ARC memory stats couldn't be determined, "
625
+ "no modification made to virtual memory stats" )
678
626
warnings .warn (msg , RuntimeWarning , stacklevel = 2 )
627
+ zfs_min = zfs_size = 0
679
628
680
- return szfsarc (
681
- zfs_enabled ,
682
- zfs_min ,
683
- zfs_max ,
684
- zfs_compressed ,
685
- zfs_uncompressed ,
686
- zfs_size ,
687
- zfs_header ,
688
- zfs_anon ,
689
- zfs_mfu ,
690
- zfs_mru ,
691
- zfs_other
692
- )
629
+ # ZFS ARC memory consumption is not reported by /proc/meminfo.
630
+ # Running this func will include reclaimable ZFS ARC
631
+ # memory in the returned values.
632
+ # N.B. this will make psutil match the output of "htop" instead
633
+ # of "free" CLI tool.
634
+ # See:
635
+ # https://www.reddit.com/r/zfs/comments/ha0p7f/understanding_arcstat_and_free/
636
+ # https://github.com/openzfs/zfs/issues/10255
693
637
638
+ # When accounting for zfs memory, we need to keep track of "shared"
639
+ # So "used" memory is more relevant than "available"
640
+ vm_stats .used += vm_stats .shared
641
+ vm_stats .cached -= vm_stats .shared
642
+ shrinkable_size = max (zfs_size - zfs_min , 0 )
643
+ vm_stats .used -= shrinkable_size
644
+ vm_stats .cached += shrinkable_size
645
+ vm_stats .available += shrinkable_size
646
+ vm_stats .percent = usage_percent (vm_stats .used , vm_stats .total , round_ = 1 )
647
+
648
+ return vm_stats
694
649
695
650
696
651
# =====================================================================
0 commit comments