3 #include <string.h> /* for memset() */
4 #include <time.h> /* for time() in srand() */
10 #define MAX_EPOCHS 20000 /* Maximum number of epochs of simulation */
11 #define MAX_LIFETIME 1000 /* Maximum lifetime of a reserved block */
12 #define MAX_LOGSIZE 5 /* Maximum logarithm of block's size */
13 #define TI 5 /* Every `TI' steps dump statistics */
15 typedef struct simnode
{
17 unsigned int lifetime
;
18 LIST_ENTRY(simnode
) next_node
;
21 LIST_HEAD(simhead
, simnode
);
22 typedef struct simhead simhead_t
;
24 /* Function prototypes */
25 void sim_add_to_list(simhead_t
*simhead
, simnode_t
*simnode
);
26 void sim_free_from_list(mpool_t
*mpool
, simhead_t
*simhead
, unsigned int t
);
27 void sim_print_stats(const mpool_t
*mpool
, unsigned int t
, FILE *fp
);
31 simnode_t simnode
[MAX_EPOCHS
];
37 /* Initialize memory pool */
38 mpret
= mpool_init(&mpool
, 25, 5);
39 if (mpret
== MPOOL_ENOMEM
) {
40 fprintf(stderr
, "mpool: not enough memory\n");
43 else if (mpret
== MPOOL_EBADVAL
) {
44 fprintf(stderr
, "mpool: bad value passed to mpool_init()\n");
48 /* Initialize random number generator */
51 /* Initialize simlist */
55 for (t
= 0; t
< MAX_EPOCHS
; t
++) {
56 /* Is it time to dump statistics ? */
58 sim_print_stats(mpool
, t
, stdout
);
60 /* Free all blocks that lived their life */
61 sim_free_from_list(mpool
, &simhead
, t
);
64 * Calculate a random size `sz' and a random lifetime `lt',
65 * similar to the way Moirae defined peoples' lives in Greek Mythology
66 * (One could use other distributions than the uniform we use here)
68 sz
= 1 << rand() % (1 + MAX_LOGSIZE
);
69 if (t
< (MAX_EPOCHS
- MAX_LIFETIME
))
70 lt
= 1 + rand() % MAX_LIFETIME
;
72 lt
= 1 + rand() % (MAX_EPOCHS
- t
);
73 /*printf("t = %u\tsz = %u\tlt = %u\n", t, sz, lt);*/
75 /* Allocate a block of size `sz' and make it last `lt' time intervals */
76 if ((simnode
[t
].ptr
= mpool_alloc(mpool
, sz
)) == NULL
) {
77 fprintf(stderr
, "mpool: no available block\n");
81 simnode
[t
].lifetime
= t
+ lt
;
83 /* Add block to list and let it find its correct position in it */
84 sim_add_to_list(&simhead
, &simnode
[t
]);
87 /* Free the last of Mohicans */
88 sim_free_from_list(mpool
, &simhead
, t
);
91 sim_print_stats(mpool
, t
, stdout
);
93 /* Destroy memory pool and free all resources */
99 void sim_add_to_list(simhead_t
*simhead
, simnode_t
*simnode
)
104 LIST_FOREACH(pnode, simhead, next_node)
105 printf("%u -> ", pnode->lifetime);
109 LIST_FOREACH(pnode
, simhead
, next_node
) {
110 if (simnode
->lifetime
< pnode
->lifetime
) {
111 LIST_INSERT_BEFORE(pnode
, simnode
, next_node
);
114 else if (LIST_NEXT(pnode
, next_node
) == NULL
) {
115 LIST_INSERT_AFTER(pnode
, simnode
, next_node
);
120 /* 1st element goes here -- this is called only when the list is empty */
121 LIST_INSERT_HEAD(simhead
, simnode
, next_node
);
124 void sim_free_from_list(mpool_t
*mpool
, simhead_t
*simhead
, unsigned int t
)
129 * Blocks with the same lifetime are placed together,
130 * e.g. ... -> 5 -> 5 -> 7 -> 7 -> 7 -> 7 -> 8 -> 8 -> 9 -> 9 -> ...
131 * That said, if the continuity breaks in one node,
132 * we are done and we should return
134 LIST_FOREACH(pnode
, simhead
, next_node
) {
135 if (t
== pnode
->lifetime
) {
136 /*printf("freeing %u\tptr = %p\n", t, pnode->ptr);*/
137 mpool_free(mpool
, pnode
->ptr
);
138 LIST_REMOVE(pnode
, next_node
);
145 void sim_print_stats(const mpool_t
*mpool
, unsigned int t
, FILE *fp
)
147 size_t an
, un
; /* nodes */
148 size_t ab
, ub
; /* blocks */
149 size_t me
= 1, sp
= 1; /* merges, splits */
152 mpool_stat_get_nodes(mpool
, &an
, &un
);
153 mpool_stat_get_bytes(mpool
, &ab
, &ub
);
154 me
= mpool_stat_get_merges(mpool
);
155 sp
= mpool_stat_get_splits(mpool
);
157 fprintf(fp
, "%u\t%u\t%u\t%.2f\t%u\t%u\t%.2f\t%u\t%u\t%.2f\n",
158 t
, an
, un
, 100.0 * an
/ (an
+ un
), ab
, ub
, 100.0 * ab
/ (ab
+ ub
), sp
, me
, 1.0*sp
/me
);
160 /* Print length of every block
161 for (i = 0; i < mpool_stat_get_blocks(mpool); i++)
162 fprintf(fp, "%u\t", mpool_stat_get_block_length(mpool, i));