1 // Performance test for the leak checker from bug #191182.
2 // Nb: it must be run with --leak-resolution=high to show the quadratic
3 // behaviour caused by the large number of loss records.
4 // By Philippe Waroquiers.
6 // On my machine, before being fixed, building the loss record list took about
7 // 36 seconds, and sorting + printing it took about 20 seconds. After being
8 // fixed it took about 2 seconds, and the leak checking was only a small
9 // fraction of that. --njn
18 /* we will create stack_fan_out ^ stack_depth different call stacks */
19 int stack_fan_out
= 15;
22 /* for each call stack, allocate malloc_fan blocks */
25 /* for each call stack, allocate data structures having malloc_depth
26 indirection at each malloc-ed level */
29 /* in addition to the pointer needed to maintain the levels; some more
30 bytes are allocated simulating the data stored in the data structure */
33 /* every n top blocks, 1 block and all its children will be freed instead of
37 /* every n release block operation, 1 block and its children will be leaked */
38 int leak_every_n
= 250;
47 struct Chunk
** topblocks
;
51 long total_malloced
= 0;
58 void free_chunks (struct Chunk
** mem
)
63 free_chunks ((&(*mem
)->child
));
70 void release (struct Chunk
** mem
)
74 if (releaseop
% leak_every_n
== 0) {
76 *mem
= 0; // lose the pointer without free-ing the blocks
82 void call_stack (int level
)
86 if (level
== stack_depth
) {
87 int sz
= sizeof(struct Chunk
*) + malloc_data
;
91 for (f
= 0; f
< malloc_fan
; f
++) {
92 struct Chunk
*new = NULL
; // shut gcc up
93 struct Chunk
*prev
= NULL
;
95 for (d
= 0; d
< malloc_depth
; d
++) {
102 topblocks
[freetop
] = new;
104 if (freetop
% free_every_n
== 0) {
105 release (&topblocks
[freetop
]);
113 /* Nb: don't common these up into a loop! We need different code
114 locations to exercise the problem. */
115 call_stack (level
+ 1);
116 if (call_fan_out
== stack_fan_out
) return;
119 call_stack (level
+ 1);
120 if (call_fan_out
== stack_fan_out
) return;
123 call_stack (level
+ 1);
124 if (call_fan_out
== stack_fan_out
) return;
127 call_stack (level
+ 1);
128 if (call_fan_out
== stack_fan_out
) return;
131 call_stack (level
+ 1);
132 if (call_fan_out
== stack_fan_out
) return;
135 call_stack (level
+ 1);
136 if (call_fan_out
== stack_fan_out
) return;
139 call_stack (level
+ 1);
140 if (call_fan_out
== stack_fan_out
) return;
143 call_stack (level
+ 1);
144 if (call_fan_out
== stack_fan_out
) return;
147 call_stack (level
+ 1);
148 if (call_fan_out
== stack_fan_out
) return;
151 call_stack (level
+ 1);
152 if (call_fan_out
== stack_fan_out
) return;
155 call_stack (level
+ 1);
156 if (call_fan_out
== stack_fan_out
) return;
159 call_stack (level
+ 1);
160 if (call_fan_out
== stack_fan_out
) return;
163 call_stack (level
+ 1);
164 if (call_fan_out
== stack_fan_out
) return;
167 call_stack (level
+ 1);
168 if (call_fan_out
== stack_fan_out
) return;
171 call_stack (level
+ 1);
172 if (call_fan_out
== stack_fan_out
) return;
175 call_stack (level
+ 1);
176 if (call_fan_out
== stack_fan_out
) return;
179 call_stack (level
+ 1);
180 if (call_fan_out
== stack_fan_out
) return;
183 call_stack (level
+ 1);
184 if (call_fan_out
== stack_fan_out
) return;
187 call_stack (level
+ 1);
188 if (call_fan_out
== stack_fan_out
) return;
191 call_stack (level
+ 1);
192 if (call_fan_out
== stack_fan_out
) return;
195 printf ("maximum stack_fan_out exceeded\n");
203 for (d
= 0; d
< stack_depth
; d
++)
204 stacks
*= stack_fan_out
;
205 printf ("will generate %d different stacks\n", stacks
);
206 topblocks
= malloc(sizeof(struct Chunk
*) * stacks
* malloc_fan
);
208 printf ("total stacks %d\n", total_stacks
);
209 printf ("total bytes malloc-ed: %ld\n", total_malloced
);
210 printf ("total blocks malloc-ed: %d\n", blocknr
);
211 printf ("total blocks free-ed: %d\n", blockfreed
);
212 printf ("total blocks leak-ed: %d\n", blockleaked
);