-
Notifications
You must be signed in to change notification settings - Fork 1
/
fancystat.c
168 lines (150 loc) · 5.26 KB
/
fancystat.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//
// Fancy allocator stats
// 2D diagram for your allocator.c ... implementation
//
// Copyright (C) 2014 Alen Bou-Haidar <alencool@gmail.com>
//
// FancyStat is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 2 of the License, or
// (at your option) any later version.
//
// FancyStat is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>
#include <string.h>
#define STAT_WIDTH 32
#define STAT_HEIGHT 16
#define BG_FREE "\x1b[48;5;35m"
#define BG_ALLOC "\x1b[48;5;39m"
#define FG_FREE "\x1b[38;5;35m"
#define FG_ALLOC "\x1b[38;5;39m"
#define CL_RESET "\x1b[0m"
typedef struct point {int x, y;} point;
static point offset_to_point(int offset, int size, int is_end);
static void fill_block(char graph[STAT_HEIGHT][STAT_WIDTH][20],
int offset, char * label);
// Print fancy 2D view of memory
// Note, This is limited to memory_sizes of under 16MB
void sal_stats2 (void * alpha[26]) {
int i, j;
vlink_t offset;
char graph[STAT_HEIGHT][STAT_WIDTH][20];
char free_sizes[26][32];
char alloc_sizes[26][32];
char label[3]; // letters for used memory, numbers for free memory
int free_count, alloc_count, max_count;
free_header_t * block;
// initilise size lists
for (i=0; i<26; i++) {
free_sizes[i][0]= '\0';
alloc_sizes[i][0]= '\0';
}
// Fill graph with free memory
offset = 0;
i = 1;
free_count = 0;
while (offset < memory_size){
block = (free_header_t *)(memory + offset);
if (block->magic == MAGIC_FREE) {
snprintf(free_sizes[free_count++], 32,
"%d) %d bytes", i, block->size);
snprintf(label, 3, "%d", i++);
fill_block(graph, offset,label);
}
offset += block->size;
}
// Fill graph with allocated memory
alloc_count = 0;
for (i=0; i<26; i++) {
if (alpha[i] != NULL) {
offset = ((byte *) alpha[i] - (byte *) memory) - HEADER_SIZE;
block = (free_header_t *)(memory + offset);
snprintf(alloc_sizes[alloc_count++], 32,
"%c) %d bytes", 'a' + i, block->size);
snprintf(label, 3, "%c", 'a' + i);
fill_block(graph, offset,label);
}
}
// Print all the memory!
for (i=0; i<STAT_HEIGHT; i++) {
for (j=0; j<STAT_WIDTH; j++) {
printf("%s", graph[i][j]);
}
printf("\n");
}
//Print table of sizes
max_count = (free_count > alloc_count)? free_count: alloc_count;
printf(FG_FREE"%-32s"CL_RESET, "Free");
if (alloc_count > 0){
printf(FG_ALLOC"%s\n"CL_RESET, "Allocated");
} else {
printf("\n");
}
for (i=0; i<max_count;i++) {
printf("%-32s%s\n", free_sizes[i], alloc_sizes[i]);
}
}
// Fill block area
static void fill_block(char graph[STAT_HEIGHT][STAT_WIDTH][20],
int offset, char * label) {
point start, end;
free_header_t * block;
char * color;
char text[3];
block = (free_header_t *)(memory + offset);
start = offset_to_point(offset, memory_size, 0);
end = offset_to_point(offset + block->size, memory_size, 1);
color = (block->magic == MAGIC_FREE) ? BG_FREE: BG_ALLOC;
int x, y;
for (y=start.y; y < end.y; y++) {
for (x=start.x; x < end.x; x++) {
if (x == start.x && y == start.y) {
// draw top left corner
snprintf(text, 3, "|%s", label);
} else if (x == start.x && y == end.y - 1) {
// draw bottom left corner
snprintf(text, 3, "|_");
} else if (y == end.y - 1) {
// draw bottom border
snprintf(text, 3, "__");
} else if (x == start.x) {
// draw left border
snprintf(text, 3, "| ");
} else {
snprintf(text, 3, " ");
}
sprintf(graph[y][x], "%s%s"CL_RESET, color, text);
}
}
}
// Converts offset to coordinate
static point offset_to_point(int offset, int size, int is_end) {
int pot[2] = {STAT_WIDTH, STAT_HEIGHT}; // potential XY
int crd[2] = {0}; // coordinates
int sign = 1; // Adding/Subtracting
int inY = 0; // which axis context
int curr = size >> 1; // first bit to check
point c; // final coordinate
if (is_end) {
offset = size - offset;
crd[0] = STAT_WIDTH;
crd[1] = STAT_HEIGHT;
sign = -1;
}
while (curr) {
pot[inY] >>= 1;
if (curr & offset) {
crd[inY] += pot[inY]*sign;
}
inY = !inY; // flip which axis to look at
curr >>= 1; // shift to the right to advance
}
c.x = crd[0];
c.y = crd[1];
return c;
}