1 /*====================================================================*
2 - Copyright (C) 2001 Leptonica. All rights reserved.
3 -
4 - Redistribution and use in source and binary forms, with or without
5 - modification, are permitted provided that the following conditions
6 - are met:
7 - 1. Redistributions of source code must retain the above copyright
8 - notice, this list of conditions and the following disclaimer.
9 - 2. Redistributions in binary form must reproduce the above
10 - copyright notice, this list of conditions and the following
11 - disclaimer in the documentation and/or other materials
12 - provided with the distribution.
13 -
14 - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
15 - ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
16 - LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
17 - A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL ANY
18 - CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
19 - EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
20 - PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
21 - PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
22 - OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23 - NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24 - SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 *====================================================================*/
26
27 /*
28 * pixalloc_reg.c
29 *
30 * Tests custom pix allocator.
31 *
32 * The custom allocator is intended for situations where a number of large
33 * pix will be repeatedly allocated and freed over the lifetime of a program.
34 * If those pix are large, relying on malloc and free can result in
35 * fragmentation, even if there are no small memory leaks in the program.
36 *
37 * Here we test the allocator in two situations:
38 * * a small number of relatively large pix
39 * * a large number of very small pix
40 *
41 * For the second case, timing shows that the custom allocator does
42 * about as well as (malloc, free), even for thousands of very small pix.
43 * (Turn off logging to get a fair comparison).
44 */
45
46 #include <math.h>
47 #include "allheaders.h"
48
49 static const l_int32 logging = FALSE;
50
51 static const l_int32 ncopies = 2;
52 static const l_int32 nlevels = 4;
53 static const l_int32 ntimes = 30;
54
55
56 PIXA *GenerateSetOfMargePix(void);
57 void CopyStoreClean(PIXA *pixas, l_int32 nlevels, l_int32 ncopies);
58
59
main(int argc,char ** argv)60 int main(int argc,
61 char **argv)
62 {
63 l_int32 i;
64 BOXA *boxa;
65 NUMA *nas, *nab;
66 PIX *pixs;
67 PIXA *pixa, *pixas;
68
69 setLeptDebugOK(1);
70 lept_mkdir("lept/alloc");
71
72 /* ----------------- Custom with a few large pix -----------------*/
73 /* Set up pms */
74 nas = numaCreate(4); /* small */
75 numaAddNumber(nas, 5);
76 numaAddNumber(nas, 4);
77 numaAddNumber(nas, 3);
78 numaAddNumber(nas, 2);
79 setPixMemoryManager(pmsCustomAlloc, pmsCustomDealloc);
80 pmsCreate(200000, 400000, nas, "/tmp/lept/alloc/file1.log");
81
82 /* Make the pix and do successive copies and removals of the copies */
83 pixas = GenerateSetOfMargePix();
84 startTimer();
85 for (i = 0; i < ntimes; i++)
86 CopyStoreClean(pixas, nlevels, ncopies);
87 fprintf(stderr, "Time (big pix; custom) = %7.3f sec\n", stopTimer());
88
89 /* Clean up */
90 numaDestroy(&nas);
91 pixaDestroy(&pixas);
92 pmsDestroy();
93
94
95 /* ----------------- Standard with a few large pix -----------------*/
96 setPixMemoryManager(malloc, free);
97
98 /* Make the pix and do successive copies and removals of the copies */
99 startTimer();
100 pixas = GenerateSetOfMargePix();
101 for (i = 0; i < ntimes; i++)
102 CopyStoreClean(pixas, nlevels, ncopies);
103 fprintf(stderr, "Time (big pix; standard) = %7.3f sec\n", stopTimer());
104 pixaDestroy(&pixas);
105
106
107 /* ----------------- Custom with many small pix -----------------*/
108 /* Set up pms */
109 nab = numaCreate(10);
110 numaAddNumber(nab, 2000);
111 numaAddNumber(nab, 2000);
112 numaAddNumber(nab, 2000);
113 numaAddNumber(nab, 500);
114 numaAddNumber(nab, 100);
115 numaAddNumber(nab, 100);
116 numaAddNumber(nab, 100);
117 setPixMemoryManager(pmsCustomAlloc, pmsCustomDealloc);
118 if (logging) /* use logging == 0 for speed comparison */
119 pmsCreate(20, 40, nab, "/tmp/lept/alloc/file2.log");
120 else
121 pmsCreate(20, 40, nab, NULL);
122 pixs = pixRead("feyn.tif");
123
124 startTimer();
125 for (i = 0; i < 5; i++) {
126 boxa = pixConnComp(pixs, &pixa, 8);
127 boxaDestroy(&boxa);
128 pixaDestroy(&pixa);
129 }
130
131 numaDestroy(&nab);
132 pixDestroy(&pixs);
133 pmsDestroy();
134 fprintf(stderr, "Time (custom) = %7.3f sec\n", stopTimer());
135
136
137 /* ----------------- Standard with many small pix -----------------*/
138 setPixMemoryManager(malloc, free);
139 pixs = pixRead("feyn.tif");
140
141 startTimer();
142 for (i = 0; i < 5; i++) {
143 boxa = pixConnComp(pixs, &pixa, 8);
144 boxaDestroy(&boxa);
145 pixaDestroy(&pixa);
146 }
147 pixDestroy(&pixs);
148 fprintf(stderr, "Time (standard) = %7.3f sec\n", stopTimer());
149 return 0;
150 }
151
152
153 PIXA *
GenerateSetOfMargePix(void)154 GenerateSetOfMargePix(void)
155 {
156 l_float32 factor;
157 BOX *box;
158 PIX *pixs, *pixt1, *pixt2, *pixt3, *pixt4;
159 PIXA *pixa;
160
161 pixs = pixRead("marge.jpg");
162 box = boxCreate(130, 93, 263, 253);
163 factor = sqrt(2.0);
164 pixt1 = pixClipRectangle(pixs, box, NULL); /* 266 KB */
165 pixt2 = pixScale(pixt1, factor, factor); /* 532 KB */
166 pixt3 = pixScale(pixt2, factor, factor); /* 1064 KB */
167 pixt4 = pixScale(pixt3, factor, factor); /* 2128 KB */
168 pixa = pixaCreate(4);
169 pixaAddPix(pixa, pixt1, L_INSERT);
170 pixaAddPix(pixa, pixt2, L_INSERT);
171 pixaAddPix(pixa, pixt3, L_INSERT);
172 pixaAddPix(pixa, pixt4, L_INSERT);
173 boxDestroy(&box);
174 pixDestroy(&pixs);
175 return pixa;
176 }
177
178
179 void
CopyStoreClean(PIXA * pixas,l_int32 nlevels,l_int32 ncopies)180 CopyStoreClean(PIXA *pixas,
181 l_int32 nlevels,
182 l_int32 ncopies)
183 {
184 l_int32 i, j;
185 PIX *pix, *pixt;
186 PIXA *pixa;
187 PIXAA *paa;
188
189 paa = pixaaCreate(0);
190 for (i = 0; i < nlevels ; i++) {
191 pixa = pixaCreate(0);
192 pixaaAddPixa(paa, pixa, L_INSERT);
193 pix = pixaGetPix(pixas, i, L_CLONE);
194 for (j = 0; j < ncopies; j++) {
195 pixt = pixCopy(NULL, pix);
196 pixaAddPix(pixa, pixt, L_INSERT);
197 }
198 pixDestroy(&pix);
199 }
200 pixaaDestroy(&paa);
201
202 return;
203 }
204
205