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