149 lines
5.4 KiB
C
149 lines
5.4 KiB
C
|
|
#include <stdio.h>
|
|||
|
|
#include <stdlib.h>
|
|||
|
|
#include <string.h>
|
|||
|
|
|
|||
|
|
// Phase 8: Detailed smaps breakdown
|
|||
|
|
// Parse every memory region to find the 5.6 MB overhead
|
|||
|
|
|
|||
|
|
typedef struct {
|
|||
|
|
char name[128];
|
|||
|
|
unsigned long rss;
|
|||
|
|
unsigned long pss;
|
|||
|
|
unsigned long anon;
|
|||
|
|
unsigned long size;
|
|||
|
|
} MemRegion;
|
|||
|
|
|
|||
|
|
void print_smaps_detailed(const char* label) {
|
|||
|
|
printf("\n╔═══════════════════════════════════════════════╗\n");
|
|||
|
|
printf("║ %s\n", label);
|
|||
|
|
printf("╚═══════════════════════════════════════════════╝\n");
|
|||
|
|
|
|||
|
|
FILE* f = fopen("/proc/self/smaps", "r");
|
|||
|
|
if (!f) {
|
|||
|
|
printf("Cannot open /proc/self/smaps\n");
|
|||
|
|
return;
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
char line[512];
|
|||
|
|
MemRegion regions[1000];
|
|||
|
|
int region_count = 0;
|
|||
|
|
MemRegion* current = NULL;
|
|||
|
|
|
|||
|
|
unsigned long total_rss = 0;
|
|||
|
|
unsigned long total_anon = 0;
|
|||
|
|
|
|||
|
|
while (fgets(line, sizeof(line), f)) {
|
|||
|
|
// New region starts with address range
|
|||
|
|
if (strchr(line, '-') && strchr(line, ' ')) {
|
|||
|
|
if (region_count < 1000) {
|
|||
|
|
current = ®ions[region_count++];
|
|||
|
|
memset(current, 0, sizeof(MemRegion));
|
|||
|
|
|
|||
|
|
// Extract region name (last part of line)
|
|||
|
|
char* p = strchr(line, '/');
|
|||
|
|
if (p) {
|
|||
|
|
char* end = strchr(p, '\n');
|
|||
|
|
if (end) *end = '\0';
|
|||
|
|
snprintf(current->name, sizeof(current->name), "%s", p);
|
|||
|
|
} else if (strstr(line, "[heap]")) {
|
|||
|
|
snprintf(current->name, sizeof(current->name), "[heap]");
|
|||
|
|
} else if (strstr(line, "[stack]")) {
|
|||
|
|
snprintf(current->name, sizeof(current->name), "[stack]");
|
|||
|
|
} else if (strstr(line, "[vdso]")) {
|
|||
|
|
snprintf(current->name, sizeof(current->name), "[vdso]");
|
|||
|
|
} else if (strstr(line, "[vvar]")) {
|
|||
|
|
snprintf(current->name, sizeof(current->name), "[vvar]");
|
|||
|
|
} else {
|
|||
|
|
snprintf(current->name, sizeof(current->name), "[anon]");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
} else if (current) {
|
|||
|
|
unsigned long val;
|
|||
|
|
if (sscanf(line, "Size: %lu kB", &val) == 1) {
|
|||
|
|
current->size = val;
|
|||
|
|
}
|
|||
|
|
if (sscanf(line, "Rss: %lu kB", &val) == 1) {
|
|||
|
|
current->rss = val;
|
|||
|
|
total_rss += val;
|
|||
|
|
}
|
|||
|
|
if (sscanf(line, "Pss: %lu kB", &val) == 1) {
|
|||
|
|
current->pss = val;
|
|||
|
|
}
|
|||
|
|
if (sscanf(line, "Anonymous: %lu kB", &val) == 1) {
|
|||
|
|
current->anon = val;
|
|||
|
|
total_anon += val;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
fclose(f);
|
|||
|
|
|
|||
|
|
// Print regions sorted by RSS (largest first)
|
|||
|
|
printf("\nTop memory regions by RSS:\n");
|
|||
|
|
printf("%-50s %10s %10s %10s\n", "Region", "Size", "RSS", "Anon");
|
|||
|
|
printf("────────────────────────────────────────────────────────────────────────────\n");
|
|||
|
|
|
|||
|
|
// Simple bubble sort by RSS
|
|||
|
|
for (int i = 0; i < region_count - 1; i++) {
|
|||
|
|
for (int j = i + 1; j < region_count; j++) {
|
|||
|
|
if (regions[j].rss > regions[i].rss) {
|
|||
|
|
MemRegion tmp = regions[i];
|
|||
|
|
regions[i] = regions[j];
|
|||
|
|
regions[j] = tmp;
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Print top 30 regions
|
|||
|
|
for (int i = 0; i < region_count && i < 30; i++) {
|
|||
|
|
if (regions[i].rss > 0) {
|
|||
|
|
printf("%-50s %7lu KB %7lu KB %7lu KB\n",
|
|||
|
|
regions[i].name,
|
|||
|
|
regions[i].size,
|
|||
|
|
regions[i].rss,
|
|||
|
|
regions[i].anon);
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
printf("────────────────────────────────────────────────────────────────────────────\n");
|
|||
|
|
printf("TOTAL: %7lu KB %7lu KB\n",
|
|||
|
|
total_rss, total_anon);
|
|||
|
|
printf(" %.1f MB %.1f MB\n",
|
|||
|
|
total_rss / 1024.0, total_anon / 1024.0);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
int main() {
|
|||
|
|
printf("╔═══════════════════════════════════════════════╗\n");
|
|||
|
|
printf("║ Detailed smaps Analysis ║\n");
|
|||
|
|
printf("╚═══════════════════════════════════════════════╝\n");
|
|||
|
|
|
|||
|
|
print_smaps_detailed("Baseline (program start)");
|
|||
|
|
|
|||
|
|
// Allocate 1M × 16B
|
|||
|
|
int n = 1000000;
|
|||
|
|
void** ptrs = malloc(n * sizeof(void*));
|
|||
|
|
|
|||
|
|
for (int i = 0; i < n; i++) {
|
|||
|
|
ptrs[i] = malloc(16);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_smaps_detailed("After 1M × 16B allocation");
|
|||
|
|
|
|||
|
|
// Free all
|
|||
|
|
for (int i = 0; i < n; i++) {
|
|||
|
|
free(ptrs[i]);
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
// Flush Magazine
|
|||
|
|
extern void hak_tiny_magazine_flush_all(void) __attribute__((weak));
|
|||
|
|
if (hak_tiny_magazine_flush_all) {
|
|||
|
|
hak_tiny_magazine_flush_all();
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
print_smaps_detailed("After free + flush");
|
|||
|
|
|
|||
|
|
free(ptrs);
|
|||
|
|
|
|||
|
|
return 0;
|
|||
|
|
}
|