1

I'm trying to use Geektool to keep a running monitor on my system, and wanted to include proper memory usage in my stats. I'm using Activity Monitor as the basis of my memory monitoring, but I'm running into an issue.

I can find and accurately calculate wired memory using the following command:

vm_stat | grep wired | awk '{print $4*4096/1024/1024/1024"GB"}'

I can't seem to get an accurate calculation of app memory though. I've tried adding up different portions of the vm_stat command to show app memory, but it doesn't seem to ever add up.

I've also tried getting used memory by trying to figure up the used, but it always comes back with more memory usage than Activity Monitor reports. I've looked online, and all Apple's website says is that App memory is the memory used by apps and background processes, which isn't really useful.

Is there combination of vm_stat pages that will add up to the used memory or app memory so that I can correctly show my memory usage in my geeklet?

  • Did you solve it ? – mac Jun 7 '17 at 13:18
  • Nope. I tried multiple ways of adding up memory, but none of them lined up with what Activity Monitor would give me. – Andrew Wallace Jun 8 '17 at 15:30
2

After some frustration, I believe I have the answer.

vm_stat is only part of the picture, we also need:

$ sysctl vm.page_pageable_internal_count

App Memory is then:

page_pageable_internal_count - Pages Purgable (from vm_stat)

This Python script gets all of vm_stat, bits of sysctl, prints out it all prettily. The last 6 lines give the same numbers as Activity Monitor.

#!/usr/bin/python

import sys
import subprocess
import re

f = 0.00000000093132257   # 1/(1024*1024*1024) Converts bytes to GB

# vm_stat (get all results)
vm = subprocess.Popen(['vm_stat'], stdout=subprocess.PIPE).communicate()[0]

vmLines = vm.split('\n')
sep = re.compile(':[\s]+')
vmStats = {}
for row in range(1,len(vmLines)-2):
    rowText = vmLines[row].strip()
    rowElements = sep.split(rowText)
    vmStats[(rowElements[0])] = int(rowElements[1].strip('\.')) * 4096

# sysctl  (just get a couple of numbers)
sy = subprocess.Popen(['sysctl','vm.page_pageable_internal_count'], stdout=subprocess.PIPE).communicate()[0]
p1 = sy.find(':')
page_pageable_internal_count = float(sy[p1+1:50]) * 4096
sy = subprocess.Popen(['sysctl','vm.swapusage'], stdout=subprocess.PIPE).communicate()[0]
p1 = sy.find('used')
p2 = sy.find('M',p1)
swapUsed = float(sy[p1+7:p2])   # This is Mbytes

appMemory = page_pageable_internal_count - vmStats["Pages purgeable"] 

print 'Wired Memory:\t\t%9.3f GB' % ( vmStats["Pages wired down"] * f )
print 'Active Memory:\t\t%9.3f GB' % ( vmStats["Pages active"] * f )
print 'Inactive Memory:\t%9.3f GB' % ( vmStats["Pages inactive"] * f )
print 'Speculative:\t\t%9.3f GB' % ( vmStats["Pages speculative"] * f )
print 'Throttled:\t\t%9.3f GB' % ( vmStats["Pages throttled"] * f )
print 'Free Memory:\t\t%9.3f GB' % ( vmStats["Pages free"] * f )

print 'Compressor:\t\t%9.3f GB' % ( vmStats["Pages occupied by compressor"] * f )
print 'Total:\t\t\t%9.3f GB' % ( (vmStats["Pages free"] + vmStats["Pages wired down"] + vmStats["Pages active"] + vmStats["Pages inactive"] + vmStats["Pages speculative"] + vmStats["Pages throttled"] + vmStats["Pages occupied by compressor"]) * f )
print ''
print 'Compressed:\t\t%9.3f GB' % ( vmStats["Pages stored in compressor"] * f )
print 'Purgeable:\t\t%9.3f GB' % ( vmStats["Pages purgeable"] * f )
print 'File-backed:\t\t%9.3f GB' % ( vmStats["File-backed pages"] * f )
print 'Anonymous:\t\t%9.3f GB' % ( vmStats["Anonymous pages"] * f )
print ''
print 'Pageable Internal:\t%9.3f GB' % (page_pageable_internal_count * f) 
print ''

print 'App Memory:\t\t%9.3f GB' % ( appMemory * f )
print 'Wired Memory:\t\t%9.3f GB' % ( vmStats["Pages wired down"] * f )
print 'Compressor:\t\t%9.3f GB  %9.3f MB' % ( vmStats["Pages occupied by compressor"] * f ,vmStats["Pages occupied by compressor"] * 1/(1024*1024) )
print 'Memory Used:\t\t%9.3f GB' % ( (appMemory + vmStats["Pages wired down"] + vmStats["Pages occupied by compressor"] ) * f )
print 'Cached Files:\t\t%9.3f GB' % ( (vmStats["File-backed pages"] + vmStats["Pages purgeable"]) * f )
print 'Swap Used:\t\t%9.3f GB  %9.3f MB' % ( swapUsed * 0.0009765625, swapUsed )

sys.exit(0);

The strange fudge factors are because a MB is 1024*1024 and a GB is 1024*1024*1024. A GB is not 1000 times a MB!

I have had most of this script for some time. The final piece of the puzzle was derived from https://stackoverflow.com/questions/31469355/how-to-calculate-app-and-cache-memory-like-activity-monitor-in-objective-c-in-ma

  • Is sysctl's page_pageable_internal_count the same as vm_stat's Anonymous pages? I am beginning to think that I should just use Anonymous Pages in place of Pageable Internal. Comments? – Gilby Jan 30 '18 at 6:14

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .