class Process::Metrics::Memory::Darwin

def self.capture(pid, count: 1, **options)

Capture memory usage for the given process IDs.
def self.capture(pid, count: 1, **options)
	usage = Memory.zero
	
	IO.popen(["vmmap", pid.to_s], "r") do |io|
		io.each_line do |line|
			if match = LINE.match(line)
				virtual_size = parse_size(match[:virtual_size])
				resident_size = parse_size(match[:resident_size])
				dirty_size = parse_size(match[:dirty_size])
				swap_size = parse_size(match[:swap_size])
				
				# Update counts
				usage.map_count += 1
				usage.resident_size += resident_size
				usage.swap_size += swap_size
				
				# Private vs. Shared memory
				# COW=copy_on_write PRV=private NUL=empty ALI=aliased 
				# SHM=shared ZER=zero_filled S/A=shared_alias
				case match[:sharing_mode]
				when "PRV"
					usage.private_clean_size += resident_size - dirty_size
					usage.private_dirty_size += dirty_size
				when "COW", "SHM"
					usage.shared_clean_size += resident_size - dirty_size
					usage.shared_dirty_size += dirty_size
				end
				
				# Anonymous memory: no region detail path or special names
				if match[:region_name] =~ /MALLOC|VM_ALLOCATE|Stack|STACK|anonymous/
					usage.anonymous_size += resident_size
				end
			end
		end
	end
	
	# Darwin does not expose proportional memory usage, so we guess based on the number of processes. Yes, this is a terrible hack, but it's the most reasonable thing to do given the constraints:
	usage.proportional_size = usage.resident_size / count
	usage.proportional_swap_size = usage.swap_size / count
	
	return usage
end