You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何macOS的virtual_size与Linux的VmSize差异超千倍?

macOS与Linux进程虚拟内存统计差异解析

我发现macOS中通过MACH_TASK_BASIC_INFO获取的virtual_size,与Linux中/proc/self/status报告的VmSize理论上属于等价指标,但实际测试数值差异超千倍:常驻内存差异合理,但macOS的虚拟内存数值超过4GB,明显不符合预期。以下是测试细节及问题解析:

测试程序

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

#ifdef __APPLE__
#include <mach/mach.h>
#include <mach/task_info.h>
#include <mach/mach_error.h>
#endif

#define MEGABYTE 1048576.0

#ifdef __linux__
typedef struct {
    size_t virtual_size;
    size_t resident_size;
    size_t resident_size_max;
} memory_stats_t;
#endif

int main(void) {
#if defined(__linux__)
    memory_stats_t stats = {};
    FILE* file = fopen("/proc/self/status", "r");
    if (file == NULL) return perror("fopen"), EXIT_FAILURE;
    char line[256];
    while (fgets(line, sizeof(line), file)) {
        if (sscanf(line, "VmSize: %lu kB", &stats.virtual_size) == 1) {
            stats.virtual_size *= 1024;
        } else if (sscanf(line, "VmRSS: %lu kB", &stats.resident_size) == 1) {
            stats.resident_size *= 1024;
        } else if (sscanf(line, "VmHWM: %lu kB", &stats.resident_size_max) == 1) {
            stats.resident_size_max *= 1024;
        }
    }
    fclose(file);
#elif defined(__APPLE__)
    task_t task = MACH_PORT_NULL;
    kern_return_t kr = task_for_pid(mach_task_self(), getpid(), &task);
    if (kr != KERN_SUCCESS) {
        return fprintf(stderr, "task_for_pid error: %s\n", mach_error_string(kr)), EXIT_FAILURE;
    }
    mach_task_basic_info_data_t stats;
    mach_msg_type_number_t task_info_count = MACH_TASK_BASIC_INFO_COUNT;
    kr = task_info(task, MACH_TASK_BASIC_INFO, (task_info_t)&stats, &task_info_count);
    if (kr != KERN_SUCCESS) {
        return fprintf(stderr, "task_info error: %s\n", mach_error_string(kr)), EXIT_FAILURE;
    }
#else
#   error "Unsupported OS"
#endif

    // Print memory usage information
    printf("=== Current process memory usage [PID: %d]\n", getpid());
    printf("Virtual:       %.3f MB\n", stats.virtual_size / MEGABYTE);
    printf("Resident:      %.3f MB\n", stats.resident_size / MEGABYTE);
    printf("Resident-Peak: %.3f MB\n", stats.resident_size_max / MEGABYTE);
    return EXIT_SUCCESS;
}

编译运行命令

gcc -o memusage memusage.c && ./memusage(macOS环境下的gcc实际为Apple Clang)

测试输出

Linux下输出

=== Current process memory usage [PID: 1403418]
Virtual:       2.594 MB
Resident:      1.125 MB
Resident-Peak: 1.125 MB

macOS下输出

=== Current process memory usage [PID: 68603]
Virtual:       4169.246 MB
Resident:      0.699 MB
Resident-Peak: 0.699 MB

核心差异解析

1. 虚拟内存统计定义不同

  • Linux的VmSize:统计进程实际已分配的虚拟地址空间总和,包含已映射的文件、匿名内存、栈、堆等所有被进程主动使用的虚拟内存区域,不包含未被分配的预留地址空间。
  • macOS的MACH_TASK_BASIC_INFO.virtual_size:统计的是进程整个虚拟地址空间的跨度——即从进程虚拟地址的最低有效位到最高有效位的总范围,其中包含了大量未被实际分配、仅为未来使用预留的地址空间(64位macOS进程默认会预留极大的虚拟地址范围),因此数值会远高于实际使用量。

2. macOS替代API:获取接近Linux VmSize的统计值

如果需要在macOS上获取与Linux VmSize定义相近的虚拟内存使用量,可以使用task_vm_info接口,其中的used_address_space字段代表进程实际已使用的虚拟内存大小,与Linux VmSize的统计逻辑一致。

修改后的macOS代码片段示例:

#elif defined(__APPLE__)
    task_t task = MACH_PORT_NULL;
    kern_return_t kr = task_for_pid(mach_task_self(), getpid(), &task);
    if (kr != KERN_SUCCESS) {
        return fprintf(stderr, "task_for_pid error: %s\n", mach_error_string(kr)), EXIT_FAILURE;
    }
    task_vm_info_data_t stats_vm;
    mach_msg_type_number_t task_info_count = TASK_VM_INFO_COUNT;
    kr = task_info(task, TASK_VM_INFO, (task_info_t)&stats_vm, &task_info_count);
    if (kr != KERN_SUCCESS) {
        return fprintf(stderr, "task_info error: %s\n", mach_error_string(kr)), EXIT_FAILURE;
    }
    // 映射到统一结构以便打印
    struct {
        size_t virtual_size;
        size_t resident_size;
        size_t resident_size_max;
    } stats = {
        .virtual_size = stats_vm.used_address_space,
        .resident_size = stats_vm.resident_size,
        .resident_size_max = stats_vm.high_watermark
    };
#endif

替换后重新编译运行,macOS的虚拟内存数值会和Linux的VmSize处于同一量级,符合预期。


内容的提问来源于stack exchange,提问作者Simon Kissane

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.20 08:50:01