Bugfixes (in-heap check, reclaim, ...) and additional analytical code
[cacao.git] / mm / lifespan.c
1 /*
2  * cacao/mm/lifespan.c
3  * $Id: lifespan.c 106 1998-12-11 02:03:33Z phil $
4  */
5
6 #include "mm.h"
7 #include "lifespan.h"
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11
12 typedef struct {
13         unsigned long time;
14         unsigned long number;
15         unsigned long size;
16 } lifespan_object;
17
18 static unsigned long     current_time = 0;
19 static unsigned long     current_number = 0;
20 static lifespan_object** lifespan_objects = NULL;
21 static lifespan_object** lifespan_objects_end = NULL;
22 static void*             lifespan_objects_off = NULL;
23 static FILE*             lifespan_file = NULL;
24
25 static unsigned long     lifespan_histo_size[64] = {};
26 static unsigned long     lifespan_histo_lifespan[64] = {};
27
28 void lifespan_init(void* heap_base, unsigned long heap_size)
29 {
30         current_time = 0;
31
32         lifespan_objects = (lifespan_object**)malloc(heap_size);
33         lifespan_objects_end = ((lifespan_object**)((unsigned long)lifespan_objects + (unsigned long)heap_size));
34         lifespan_objects_off = (void*)((unsigned long)lifespan_objects - (unsigned long)heap_base);
35         lifespan_file = popen("gzip -9 >lifespans.gz", "w");
36
37         if (!lifespan_objects || !lifespan_file) {
38                 fprintf(stderr, "Failed to allocate memory for lifespan-object index / popen lifespan output stream\n");
39                 exit(-1);
40         }
41
42         memset(lifespan_objects, 0, heap_size);
43 }
44
45 static __inline__ void lifespan_free_object(lifespan_object** o)
46 {
47         int size, high = 0;
48         /* file format: alloc time, size, lifespan */
49
50         if (*o) {
51                 fprintf(lifespan_file, 
52                                 "%ld\t%ld\t%ld\t%ld\t%ld\n", 
53                                 (*o)->number, 
54                                 (*o)->time, 
55                                 (*o)->size, 
56                                 current_number - (*o)->number,
57                                 current_time - (*o)->time);
58                 
59                 /* histo_size */
60                 size = (*o)->size;
61                 while (size) {
62                         ++high;
63                         size = size >> 1;
64                 }
65
66                 ++lifespan_histo_size[high];
67
68                 /* histo_life */
69                 high = 0;
70                 size = current_time - (*o)->time;
71                 while (size) {
72                         ++high;
73                         size = size >> 1;
74                 }
75
76                 ++lifespan_histo_lifespan[high];
77
78                 free(*o);
79                 *o = NULL;
80         }
81 }
82
83 void lifespan_close()
84 {
85         if (lifespan_objects) {
86                 while(lifespan_objects < lifespan_objects_end)
87                         lifespan_free_object(--lifespan_objects_end);
88
89                 free(lifespan_objects);
90         }
91
92         if (lifespan_file)
93                 pclose(lifespan_file);
94 }
95
96 void lifespan_emit()
97 {
98         /* emit summary */
99         int i;
100
101         for (i = 4; i < 32; ++i)
102                 fprintf(stderr, "%Lu-%Lu\t%Lu\n", 
103                                 (1LL << (i-1)), 
104                                 (1LL << i) - 1,
105                                 lifespan_histo_size[i]);
106
107         fprintf(stderr, "\n\n\n");
108
109         for (i = 4; i < 32; ++i)
110                 fprintf(stderr, "%Lu-%Lu\t%Lu\n", 
111                                 (1LL << (i-1)), 
112                                 (1LL << i) - 1,
113                                 lifespan_histo_lifespan[i]);
114 }
115
116 void lifespan_free(void** from, void** limit)
117 {
118         lifespan_object**  object;
119         object = (lifespan_object**)((unsigned long)from + (unsigned long)lifespan_objects_off);
120
121         while (from < limit) {
122                 lifespan_free_object(object++);
123                 ++from;
124         }
125 }
126
127 void lifespan_alloc(void* addr, unsigned long size) 
128 {
129         lifespan_object**  object;
130         object = (lifespan_object**)((unsigned long)addr + (unsigned long)lifespan_objects_off);
131
132         *object = (lifespan_object*)malloc(sizeof(lifespan_object));
133         if (!*object) {
134                 fprintf(stderr, "oops.\n");
135                 exit(-10);
136         }
137         (*object)->time = current_time;
138         (*object)->size = size;
139         (*object)->number = ++current_number;
140         
141         current_time += size;
142 }
143
144 /*
145  * These are local overrides for various environment variables in Emacs.
146  * Please do not remove this and leave it at the end of the file, where
147  * Emacs will automagically detect them.
148  * ---------------------------------------------------------------------
149  * Local variables:
150  * mode: c
151  * indent-tabs-mode: t
152  * c-basic-offset: 4
153  * tab-width: 4
154  * End:
155  */