Merge lp:~epics-core/epics-base/dbConvert-memmove into lp:~epics-core/epics-base/3.15
- dbConvert-memmove
- Merge into 3.15
Proposed by
mdavidsaver
Status: | Merged |
---|---|
Merged at revision: | 12490 |
Proposed branch: | lp:~epics-core/epics-base/dbConvert-memmove |
Merge into: | lp:~epics-core/epics-base/3.15 |
Diff against target: |
819 lines (+355/-180) 6 files modified
src/ioc/db/dbConvert.c (+54/-180) src/ioc/db/dbConvert.h (+1/-0) src/ioc/db/test/Makefile (+8/-0) src/ioc/db/test/benchdbConvert.c (+124/-0) src/ioc/db/test/epicsRunDbTests.c (+2/-0) src/ioc/db/test/testdbConvert.c (+166/-0) |
To merge this branch: | bzr merge lp:~epics-core/epics-base/dbConvert-memmove |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Andrew Johnson | Approve | ||
Review via email: mp+223116@code.launchpad.net |
Commit message
Description of the change
in dbConvert.c use memmove instead of for loop when no conversion takes place. On some archs this yields a significant speedup for array copies.
To post a comment you must log in.
Revision history for this message
mdavidsaver (mdavidsaver) wrote : | # |
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'src/ioc/db/dbConvert.c' |
2 | --- src/ioc/db/dbConvert.c 2014-06-04 19:18:43 +0000 |
3 | +++ src/ioc/db/dbConvert.c 2014-06-13 19:56:49 +0000 |
4 | @@ -38,6 +38,29 @@ |
5 | #include "recGbl.h" |
6 | #include "dbConvert.h" |
7 | |
8 | +/* Helper for copy as bytes with no type conversion. |
9 | + * Assumes nRequest <= no_bytes |
10 | + * nRequest, no_bytes, and offset should be given in bytes. |
11 | + */ |
12 | +static void copyNoConvert(const void *pfrom, |
13 | + void *pto, |
14 | + long nRequest, |
15 | + long no_bytes, |
16 | + long offset) |
17 | +{ |
18 | + if(offset>0 && offset < no_bytes && offset+nRequest > no_bytes) { |
19 | + const size_t N = no_bytes - offset; |
20 | + /* copy with wrap */ |
21 | + memmove(pto, pfrom + offset, N); |
22 | + memmove(pto + N, pfrom, nRequest - N); |
23 | + } else { |
24 | + /* no wrap, just copy */ |
25 | + memmove(pto, pfrom + offset, nRequest); |
26 | + } |
27 | +} |
28 | +#define COPYNOCONVERT(N, FROM, TO, NREQ, NO_ELEM, OFFSET) \ |
29 | + copyNoConvert(FROM, TO, (N)*(NREQ), (N)*(NO_ELEM), (N)*(OFFSET)) |
30 | + |
31 | /* DATABASE ACCESS GET CONVERSION SUPPORT */ |
32 | |
33 | |
34 | static long getStringString ( |
35 | @@ -427,12 +450,7 @@ |
36 | *pbuffer = *psrc; |
37 | return(0); |
38 | } |
39 | - psrc += offset; |
40 | - while (nRequest) { |
41 | - *pbuffer++ = *psrc++; |
42 | - if(++offset==no_elements) psrc=(char *)paddr->pfield; |
43 | - nRequest--; |
44 | - } |
45 | + COPYNOCONVERT(sizeof(char), paddr->pfield, pto, nRequest, no_elements, offset); |
46 | return(0); |
47 | } |
48 | |
49 | |
50 | @@ -454,12 +472,7 @@ |
51 | *pbuffer = *psrc; |
52 | return(0); |
53 | } |
54 | - psrc += offset; |
55 | - while (nRequest) { |
56 | - *pbuffer++ = *psrc++; |
57 | - if(++offset==no_elements) psrc=(char *)paddr->pfield; |
58 | - nRequest--; |
59 | - } |
60 | + COPYNOCONVERT(sizeof(char), paddr->pfield, pto, nRequest, no_elements, offset); |
61 | return(0); |
62 | } |
63 | |
64 | @@ -638,12 +651,7 @@ |
65 | *pbuffer = *psrc; |
66 | return(0); |
67 | } |
68 | - psrc += offset; |
69 | - while (nRequest) { |
70 | - *pbuffer++ = *psrc++; |
71 | - if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; |
72 | - nRequest--; |
73 | - } |
74 | + COPYNOCONVERT(sizeof(unsigned char), paddr->pfield, pto, nRequest, no_elements, offset); |
75 | return(0); |
76 | } |
77 | |
78 | |
79 | @@ -658,12 +666,7 @@ |
80 | *pbuffer = *psrc; |
81 | return(0); |
82 | } |
83 | - psrc += offset; |
84 | - while (nRequest) { |
85 | - *pbuffer++ = *psrc++; |
86 | - if(++offset==no_elements) psrc=(unsigned char *)paddr->pfield; |
87 | - nRequest--; |
88 | - } |
89 | + COPYNOCONVERT(sizeof(unsigned char), paddr->pfield, pto, nRequest, no_elements, offset); |
90 | return(0); |
91 | } |
92 | |
93 | @@ -870,6 +873,7 @@ |
94 | } |
95 | return(0); |
96 | } |
97 | + |
98 | static long getShortShort( |
99 | const dbAddr *paddr, |
100 | void *pto, long nRequest, long no_elements, long offset) |
101 | @@ -881,12 +885,7 @@ |
102 | *pbuffer = *psrc; |
103 | return(0); |
104 | } |
105 | - psrc += offset; |
106 | - while (nRequest) { |
107 | - *pbuffer++ = *psrc++; |
108 | - if(++offset==no_elements) psrc=(short *)paddr->pfield; |
109 | - nRequest--; |
110 | - } |
111 | + COPYNOCONVERT(sizeof(short), paddr->pfield, pto, nRequest, no_elements, offset); |
112 | return(0); |
113 | } |
114 | |
115 | |
116 | @@ -901,12 +900,7 @@ |
117 | *pbuffer = *psrc; |
118 | return(0); |
119 | } |
120 | - psrc += offset; |
121 | - while (nRequest) { |
122 | - *pbuffer++ = *psrc++; |
123 | - if(++offset==no_elements) psrc=(short *)paddr->pfield; |
124 | - nRequest--; |
125 | - } |
126 | + COPYNOCONVERT(sizeof(short), paddr->pfield, pto, nRequest, no_elements, offset); |
127 | return(0); |
128 | } |
129 | |
130 | @@ -1084,12 +1078,7 @@ |
131 | *pbuffer = *psrc; |
132 | return(0); |
133 | } |
134 | - psrc += offset; |
135 | - while (nRequest) { |
136 | - *pbuffer++ = *psrc++; |
137 | - if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; |
138 | - nRequest--; |
139 | - } |
140 | + COPYNOCONVERT(sizeof(unsigned short), paddr->pfield, pto, nRequest, no_elements, offset); |
141 | return(0); |
142 | } |
143 | |
144 | |
145 | @@ -1104,12 +1093,7 @@ |
146 | *pbuffer = *psrc; |
147 | return(0); |
148 | } |
149 | - psrc += offset; |
150 | - while (nRequest) { |
151 | - *pbuffer++ = *psrc++; |
152 | - if(++offset==no_elements) psrc=(unsigned short *)paddr->pfield; |
153 | - nRequest--; |
154 | - } |
155 | + COPYNOCONVERT(sizeof(unsigned short), paddr->pfield, pto, nRequest, no_elements, offset); |
156 | return(0); |
157 | } |
158 | |
159 | @@ -1328,12 +1312,7 @@ |
160 | *pbuffer = *psrc; |
161 | return(0); |
162 | } |
163 | - psrc += offset; |
164 | - while (nRequest) { |
165 | - *pbuffer++ = *psrc++; |
166 | - if(++offset==no_elements) psrc=(epicsInt32 *)paddr->pfield; |
167 | - nRequest--; |
168 | - } |
169 | + COPYNOCONVERT(sizeof(long), paddr->pfield, pto, nRequest, no_elements, offset); |
170 | return(0); |
171 | } |
172 | |
173 | |
174 | @@ -1348,12 +1327,7 @@ |
175 | *pbuffer = *psrc; |
176 | return(0); |
177 | } |
178 | - psrc += offset; |
179 | - while (nRequest) { |
180 | - *pbuffer++ = *psrc++; |
181 | - if(++offset==no_elements) psrc=(epicsInt32 *)paddr->pfield; |
182 | - nRequest--; |
183 | - } |
184 | + COPYNOCONVERT(sizeof(long), paddr->pfield, pto, nRequest, no_elements, offset); |
185 | return(0); |
186 | } |
187 | |
188 | @@ -1532,12 +1506,7 @@ |
189 | *pbuffer = *psrc; |
190 | return(0); |
191 | } |
192 | - psrc += offset; |
193 | - while (nRequest) { |
194 | - *pbuffer++ = *psrc++; |
195 | - if(++offset==no_elements) psrc=(epicsUInt32 *)paddr->pfield; |
196 | - nRequest--; |
197 | - } |
198 | + COPYNOCONVERT(sizeof(unsigned long), paddr->pfield, pto, nRequest, no_elements, offset); |
199 | return(0); |
200 | } |
201 | |
202 | |
203 | @@ -1552,12 +1521,7 @@ |
204 | *pbuffer = *psrc; |
205 | return(0); |
206 | } |
207 | - psrc += offset; |
208 | - while (nRequest) { |
209 | - *pbuffer++ = *psrc++; |
210 | - if(++offset==no_elements) psrc=(epicsUInt32 *)paddr->pfield; |
211 | - nRequest--; |
212 | - } |
213 | + COPYNOCONVERT(sizeof(unsigned long), paddr->pfield, pto, nRequest, no_elements, offset); |
214 | return(0); |
215 | } |
216 | |
217 | @@ -1782,12 +1746,7 @@ |
218 | *pbuffer = *psrc; |
219 | return(0); |
220 | } |
221 | - psrc += offset; |
222 | - while (nRequest) { |
223 | - *pbuffer++ = *psrc++; |
224 | - if(++offset==no_elements) psrc=(float *)paddr->pfield; |
225 | - nRequest--; |
226 | - } |
227 | + COPYNOCONVERT(sizeof(float), paddr->pfield, pto, nRequest, no_elements, offset); |
228 | return(0); |
229 | } |
230 | |
231 | |
232 | @@ -2013,12 +1972,7 @@ |
233 | *pbuffer = *psrc; |
234 | return(0); |
235 | } |
236 | - psrc += offset; |
237 | - while (nRequest) { |
238 | - *pbuffer++ = *psrc++; |
239 | - if(++offset==no_elements) psrc=(double *)paddr->pfield; |
240 | - nRequest--; |
241 | - } |
242 | + COPYNOCONVERT(sizeof(double), paddr->pfield, pto, nRequest, no_elements, offset); |
243 | return(0); |
244 | } |
245 | |
246 | @@ -2228,12 +2182,7 @@ |
247 | *pbuffer = *psrc; |
248 | return(0); |
249 | } |
250 | - psrc += offset; |
251 | - while (nRequest) { |
252 | - *pbuffer++ = *psrc++; |
253 | - if(++offset==no_elements) psrc=(epicsEnum16 *)paddr->pfield; |
254 | - nRequest--; |
255 | - } |
256 | + COPYNOCONVERT(sizeof(epicsEnum16), paddr->pfield, pto, nRequest, no_elements, offset); |
257 | return(0); |
258 | } |
259 | |
260 | |
261 | @@ -2734,12 +2683,7 @@ |
262 | *pdest = *pbuffer; |
263 | return(0); |
264 | } |
265 | - pdest += offset; |
266 | - while (nRequest) { |
267 | - *pdest++ = *pbuffer++; |
268 | - if(++offset==no_elements) pdest=(char *)paddr->pfield; |
269 | - nRequest--; |
270 | - } |
271 | + COPYNOCONVERT(sizeof(char), pfrom, paddr->pfield, nRequest, no_elements, offset); |
272 | return(0); |
273 | } |
274 | |
275 | |
276 | @@ -2754,12 +2698,7 @@ |
277 | *pdest = *pbuffer; |
278 | return(0); |
279 | } |
280 | - pdest += offset; |
281 | - while (nRequest) { |
282 | - *pdest++ = *pbuffer++; |
283 | - if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; |
284 | - nRequest--; |
285 | - } |
286 | + COPYNOCONVERT(sizeof(unsigned char), pfrom, paddr->pfield, nRequest, no_elements, offset); |
287 | return(0); |
288 | } |
289 | |
290 | @@ -2940,12 +2879,7 @@ |
291 | *pdest = *pbuffer; |
292 | return(0); |
293 | } |
294 | - pdest += offset; |
295 | - while (nRequest) { |
296 | - *pdest++ = *pbuffer++; |
297 | - if(++offset==no_elements) pdest=(char *)paddr->pfield; |
298 | - nRequest--; |
299 | - } |
300 | + COPYNOCONVERT(sizeof(unsigned char), pfrom, paddr->pfield, nRequest, no_elements, offset); |
301 | return(0); |
302 | } |
303 | |
304 | |
305 | @@ -2960,12 +2894,7 @@ |
306 | *pdest = *pbuffer; |
307 | return(0); |
308 | } |
309 | - pdest += offset; |
310 | - while (nRequest) { |
311 | - *pdest++ = *pbuffer++; |
312 | - if(++offset==no_elements) pdest=(unsigned char *)paddr->pfield; |
313 | - nRequest--; |
314 | - } |
315 | + COPYNOCONVERT(sizeof(unsigned char), pfrom, paddr->pfield, nRequest, no_elements, offset); |
316 | return(0); |
317 | } |
318 | |
319 | @@ -3186,12 +3115,7 @@ |
320 | *pdest = *pbuffer; |
321 | return(0); |
322 | } |
323 | - pdest += offset; |
324 | - while (nRequest) { |
325 | - *pdest++ = *pbuffer++; |
326 | - if(++offset==no_elements) pdest=(short *)paddr->pfield; |
327 | - nRequest--; |
328 | - } |
329 | + COPYNOCONVERT(sizeof(short), pfrom, paddr->pfield, nRequest, no_elements, offset); |
330 | return(0); |
331 | } |
332 | |
333 | |
334 | @@ -3206,12 +3130,7 @@ |
335 | *pdest = *pbuffer; |
336 | return(0); |
337 | } |
338 | - pdest += offset; |
339 | - while (nRequest) { |
340 | - *pdest++ = *pbuffer++; |
341 | - if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; |
342 | - nRequest--; |
343 | - } |
344 | + COPYNOCONVERT(sizeof(short), pfrom, paddr->pfield, nRequest, no_elements, offset); |
345 | return(0); |
346 | } |
347 | |
348 | @@ -3392,12 +3311,7 @@ |
349 | *pdest = *pbuffer; |
350 | return(0); |
351 | } |
352 | - pdest += offset; |
353 | - while (nRequest) { |
354 | - *pdest++ = *pbuffer++; |
355 | - if(++offset==no_elements) pdest=(short *)paddr->pfield; |
356 | - nRequest--; |
357 | - } |
358 | + COPYNOCONVERT(sizeof(unsigned short), pfrom, paddr->pfield, nRequest, no_elements, offset); |
359 | return(0); |
360 | } |
361 | |
362 | |
363 | @@ -3412,12 +3326,7 @@ |
364 | *pdest = *pbuffer; |
365 | return(0); |
366 | } |
367 | - pdest += offset; |
368 | - while (nRequest) { |
369 | - *pdest++ = *pbuffer++; |
370 | - if(++offset==no_elements) pdest=(unsigned short *)paddr->pfield; |
371 | - nRequest--; |
372 | - } |
373 | + COPYNOCONVERT(sizeof(unsigned short), pfrom, paddr->pfield, nRequest, no_elements, offset); |
374 | return(0); |
375 | } |
376 | |
377 | @@ -3638,12 +3547,7 @@ |
378 | *pdest = *pbuffer; |
379 | return(0); |
380 | } |
381 | - pdest += offset; |
382 | - while (nRequest) { |
383 | - *pdest++ = *pbuffer++; |
384 | - if(++offset==no_elements) pdest=(epicsInt32 *)paddr->pfield; |
385 | - nRequest--; |
386 | - } |
387 | + COPYNOCONVERT(sizeof(epicsInt32), pfrom, paddr->pfield, nRequest, no_elements, offset); |
388 | return(0); |
389 | } |
390 | |
391 | |
392 | @@ -3658,12 +3562,7 @@ |
393 | *pdest = *pbuffer; |
394 | return(0); |
395 | } |
396 | - pdest += offset; |
397 | - while (nRequest) { |
398 | - *pdest++ = *pbuffer++; |
399 | - if(++offset==no_elements) pdest=(epicsUInt32 *)paddr->pfield; |
400 | - nRequest--; |
401 | - } |
402 | + COPYNOCONVERT(sizeof(epicsInt32), pfrom, paddr->pfield, nRequest, no_elements, offset); |
403 | return(0); |
404 | } |
405 | |
406 | @@ -3844,12 +3743,7 @@ |
407 | *pdest = *pbuffer; |
408 | return(0); |
409 | } |
410 | - pdest += offset; |
411 | - while (nRequest) { |
412 | - *pdest++ = *pbuffer++; |
413 | - if(++offset==no_elements) pdest=(epicsInt32 *)paddr->pfield; |
414 | - nRequest--; |
415 | - } |
416 | + COPYNOCONVERT(sizeof(epicsUInt32), pfrom, paddr->pfield, nRequest, no_elements, offset); |
417 | return(0); |
418 | } |
419 | |
420 | |
421 | @@ -3864,12 +3758,7 @@ |
422 | *pdest = *pbuffer; |
423 | return(0); |
424 | } |
425 | - pdest += offset; |
426 | - while (nRequest) { |
427 | - *pdest++ = *pbuffer++; |
428 | - if(++offset==no_elements) pdest=(epicsUInt32 *)paddr->pfield; |
429 | - nRequest--; |
430 | - } |
431 | + COPYNOCONVERT(sizeof(epicsUInt32), pfrom, paddr->pfield, nRequest, no_elements, offset); |
432 | return(0); |
433 | } |
434 | |
435 | @@ -4095,12 +3984,7 @@ |
436 | *pdest = *pbuffer; |
437 | return(0); |
438 | } |
439 | - pdest += offset; |
440 | - while (nRequest) { |
441 | - *pdest++ = *pbuffer++; |
442 | - if(++offset==no_elements) pdest=(float *)paddr->pfield; |
443 | - nRequest--; |
444 | - } |
445 | + COPYNOCONVERT(sizeof(float), pfrom, paddr->pfield, nRequest, no_elements, offset); |
446 | return(0); |
447 | } |
448 | |
449 | |
450 | @@ -4327,12 +4211,7 @@ |
451 | *pdest = *pbuffer; |
452 | return(0); |
453 | } |
454 | - pdest += offset; |
455 | - while (nRequest) { |
456 | - *pdest++ = *pbuffer++; |
457 | - if(++offset==no_elements) pdest=(double *)paddr->pfield; |
458 | - nRequest--; |
459 | - } |
460 | + COPYNOCONVERT(sizeof(double), pfrom, paddr->pfield, nRequest, no_elements, offset); |
461 | return(0); |
462 | } |
463 | |
464 | @@ -4553,12 +4432,7 @@ |
465 | *pdest = *pbuffer; |
466 | return(0); |
467 | } |
468 | - pdest += offset; |
469 | - while (nRequest) { |
470 | - *pdest++ = *pbuffer++; |
471 | - if(++offset==no_elements) pdest=(epicsEnum16 *)paddr->pfield; |
472 | - nRequest--; |
473 | - } |
474 | + COPYNOCONVERT(sizeof(epicsEnum16), pfrom, paddr->pfield, nRequest, no_elements, offset); |
475 | return(0); |
476 | } |
477 | |
478 | |
479 | |
480 | === modified file 'src/ioc/db/dbConvert.h' |
481 | --- src/ioc/db/dbConvert.h 2009-02-24 22:57:15 +0000 |
482 | +++ src/ioc/db/dbConvert.h 2014-06-13 19:56:49 +0000 |
483 | @@ -12,6 +12,7 @@ |
484 | #define INCdbConverth |
485 | |
486 | #include "dbFldTypes.h" |
487 | +#include "dbAddr.h" |
488 | #include "shareLib.h" |
489 | |
490 | #ifdef __cplusplus |
491 | |
492 | === modified file 'src/ioc/db/test/Makefile' |
493 | --- src/ioc/db/test/Makefile 2012-07-17 19:33:31 +0000 |
494 | +++ src/ioc/db/test/Makefile 2014-06-13 19:56:49 +0000 |
495 | @@ -16,6 +16,11 @@ |
496 | |
497 | PROD_LIBS = xRec dbCore ca Com |
498 | |
499 | +TESTPROD_HOST += testdbConvert |
500 | +testdbConvert_SRCS += testdbConvert.c |
501 | +testHarness_SRCS += testdbConvert.c |
502 | +TESTS += testdbConvert |
503 | + |
504 | TESTPROD_HOST += callbackTest |
505 | callbackTest_SRCS += callbackTest.c |
506 | testHarness_SRCS += callbackTest.c |
507 | @@ -56,6 +61,9 @@ |
508 | TESTFILES += $(COMMON_DIR)/arrShorthandTest.dbd |
509 | TESTS += arrShorthandTest |
510 | |
511 | +TESTPROD_HOST += benchdbConvert |
512 | +benchdbConvert_SRCS += benchdbConvert.c |
513 | + |
514 | # The testHarness runs all the test programs in a known working order. |
515 | testHarness_SRCS += epicsRunDbTests.c |
516 | |
517 | |
518 | === added file 'src/ioc/db/test/benchdbConvert.c' |
519 | --- src/ioc/db/test/benchdbConvert.c 1970-01-01 00:00:00 +0000 |
520 | +++ src/ioc/db/test/benchdbConvert.c 2014-06-13 19:56:49 +0000 |
521 | @@ -0,0 +1,124 @@ |
522 | +/*************************************************************************\ |
523 | +* Copyright (c) 2013 Brookhaven Science Assoc, as Operator of Brookhaven |
524 | +* National Laboratory. |
525 | +\*************************************************************************/ |
526 | +#include "string.h" |
527 | + |
528 | +#include "cantProceed.h" |
529 | +#include "dbAddr.h" |
530 | +#include "dbConvert.h" |
531 | +#include "dbDefs.h" |
532 | +#include "epicsTime.h" |
533 | +#include "epicsMath.h" |
534 | +#include "epicsAssert.h" |
535 | + |
536 | +#include "epicsUnitTest.h" |
537 | +#include "testMain.h" |
538 | + |
539 | +typedef struct { |
540 | + size_t nelem, niter; |
541 | + |
542 | + short *output; |
543 | + short *input; |
544 | + |
545 | + GETCONVERTFUNC getter; |
546 | + |
547 | + DBADDR addr; |
548 | +} testData; |
549 | + |
550 | +static long runRep(testData *D) |
551 | +{ |
552 | + size_t i; |
553 | + |
554 | + for(i=0; i<D->niter; i++) { |
555 | + D->getter(&D->addr, D->output, D->nelem, D->nelem, 0); |
556 | + } |
557 | + return 0; |
558 | +} |
559 | + |
560 | +static void runBench(size_t nelem, size_t niter, size_t nrep) |
561 | +{ |
562 | + size_t i; |
563 | + testData tdat; |
564 | + double *reptimes; |
565 | + testDiag("Using %lu element arrays.",(unsigned long)nelem); |
566 | + testDiag("run %lu reps with %lu iterations each", |
567 | + (unsigned long)nrep, (unsigned long)niter); |
568 | + |
569 | + reptimes = callocMustSucceed(nrep, sizeof(*reptimes), "runBench"); |
570 | + tdat.output = callocMustSucceed(nelem, sizeof(*tdat.output), "runBench"); |
571 | + tdat.input = callocMustSucceed(nelem, sizeof(*tdat.input), "runBench"); |
572 | + |
573 | + tdat.nelem = nelem; |
574 | + tdat.niter = niter; |
575 | + |
576 | + tdat.getter = dbGetConvertRoutine[DBF_SHORT][DBF_SHORT]; |
577 | + |
578 | + memset(&tdat.addr, 0, sizeof(tdat.addr)); |
579 | + tdat.addr.field_type = DBF_SHORT; |
580 | + tdat.addr.field_size = nelem*sizeof(*tdat.input); |
581 | + tdat.addr.no_elements = nelem; |
582 | + tdat.addr.pfield = (void*)tdat.input; |
583 | + |
584 | + for(i=0; i<nelem; i++) |
585 | + tdat.input[i] = (short)i; |
586 | + |
587 | + for(i=0; i<nrep; i++) |
588 | + { |
589 | + epicsTimeStamp start, stop; |
590 | + |
591 | + if(epicsTimeGetCurrent(&start)!=epicsTimeOK) { |
592 | + testAbort("Failed to get timestamp"); |
593 | + goto done; |
594 | + } |
595 | + |
596 | + if(runRep(&tdat)) |
597 | + goto done; |
598 | + |
599 | + if(epicsTimeGetCurrent(&stop)!=epicsTimeOK) { |
600 | + testAbort("Failed to get timestamp"); |
601 | + goto done; |
602 | + } |
603 | + |
604 | + reptimes[i] = epicsTimeDiffInSeconds(&stop, &start); |
605 | + |
606 | + testDiag("%lu bytes in %.03f ms. %.1f MB/s", |
607 | + (unsigned long)(nelem*niter), |
608 | + reptimes[i]*1e3, |
609 | + (nelem*niter)/reptimes[i]/1e6); |
610 | + } |
611 | + |
612 | + { |
613 | + double sum=0, sum2=0, mean; |
614 | + for(i=0; i<nrep; i++) { |
615 | + sum += reptimes[i]; |
616 | + sum2 += reptimes[i]*reptimes[i]; |
617 | + } |
618 | + |
619 | + mean = sum/nrep; |
620 | + testDiag("Final: %.04f ms +- %.05f ms. %.1f MB/s (for %lu elements)", |
621 | + mean*1e3, |
622 | + sqrt(sum2/nrep - mean*mean)*1e3, |
623 | + (nelem*niter)/mean/1e6, |
624 | + (unsigned long)nelem); |
625 | + } |
626 | + |
627 | +done: |
628 | + free(reptimes); |
629 | + free(tdat.input); |
630 | + free(tdat.output); |
631 | +} |
632 | + |
633 | +MAIN(benchdbConvert) |
634 | +{ |
635 | + testPlan(0); |
636 | + runBench(1, 10000000, 10); |
637 | + runBench(2, 5000000, 10); |
638 | + runBench(10, 1000000, 10); |
639 | + runBench(100, 100000, 10); |
640 | + runBench(10000, 1000, 10); |
641 | + runBench(100000, 100, 10); |
642 | + runBench(1000000, 10, 10); |
643 | + runBench(10000000, 1, 10); |
644 | + return testDone(); |
645 | +} |
646 | |
647 | === modified file 'src/ioc/db/test/epicsRunDbTests.c' |
648 | --- src/ioc/db/test/epicsRunDbTests.c 2012-06-28 14:55:46 +0000 |
649 | +++ src/ioc/db/test/epicsRunDbTests.c 2014-06-13 19:56:49 +0000 |
650 | @@ -16,6 +16,7 @@ |
651 | #include "epicsExit.h" |
652 | #include "dbmf.h" |
653 | |
654 | +int testdbConvert(void); |
655 | int callbackTest(void); |
656 | int dbStateTest(void); |
657 | int testDbChannel(void); |
658 | @@ -26,6 +27,7 @@ |
659 | { |
660 | testHarness(); |
661 | |
662 | + runTest(testdbConvert); |
663 | runTest(callbackTest); |
664 | runTest(dbStateTest); |
665 | runTest(testDbChannel); |
666 | |
667 | === added file 'src/ioc/db/test/testdbConvert.c' |
668 | --- src/ioc/db/test/testdbConvert.c 1970-01-01 00:00:00 +0000 |
669 | +++ src/ioc/db/test/testdbConvert.c 2014-06-13 19:56:49 +0000 |
670 | @@ -0,0 +1,166 @@ |
671 | +/*************************************************************************\ |
672 | +* Copyright (c) 2013 Brookhaven Science Assoc, as Operator of Brookhaven |
673 | +* National Laboratory. |
674 | +\*************************************************************************/ |
675 | +#include "string.h" |
676 | + |
677 | +#include "cantProceed.h" |
678 | +#include "dbConvert.h" |
679 | +#include "dbDefs.h" |
680 | +#include "epicsAssert.h" |
681 | + |
682 | +#include "epicsUnitTest.h" |
683 | +#include "testMain.h" |
684 | + |
685 | +static const short s_input[] = {-1,0,1,2,3,4,5}; |
686 | +static const size_t s_input_len = NELEMENTS(s_input); |
687 | + |
688 | +static void testBasicGet(void) |
689 | +{ |
690 | + short *scratch; |
691 | + DBADDR addr; |
692 | + GETCONVERTFUNC getter; |
693 | + |
694 | + getter = dbGetConvertRoutine[DBF_SHORT][DBF_SHORT]; |
695 | + |
696 | + scratch = callocMustSucceed(s_input_len, sizeof(s_input), "testBasicGet"); |
697 | + |
698 | + memset(&addr, 0, sizeof(addr)); |
699 | + addr.field_type = DBF_SHORT; |
700 | + addr.field_size = s_input_len*sizeof(*scratch); |
701 | + addr.no_elements = s_input_len; |
702 | + addr.pfield = (void*)s_input; |
703 | + |
704 | + testDiag("Test dbGetConvertRoutine[DBF_SHORT][DBF_SHORT]"); |
705 | + |
706 | + { |
707 | + testDiag("Copy out first element"); |
708 | + |
709 | + getter(&addr, scratch, 1, s_input_len, 0); |
710 | + |
711 | + testOk1(scratch[0]==s_input[0]); |
712 | + |
713 | + memset(scratch, 0x42, sizeof(s_input)); |
714 | + } |
715 | + |
716 | + { |
717 | + testDiag("Copy out entire array"); |
718 | + |
719 | + getter(&addr, scratch, s_input_len, s_input_len, 0); |
720 | + |
721 | + testOk1(memcmp(scratch, s_input, sizeof(s_input))==0); |
722 | + |
723 | + memset(scratch, 0x42, sizeof(s_input)); |
724 | + } |
725 | + |
726 | + { |
727 | + testDiag("Copy out partial array"); |
728 | + |
729 | + getter(&addr, scratch, 2, s_input_len, 0); |
730 | + |
731 | + testOk1(memcmp(scratch, s_input, sizeof(short)*2)==0); |
732 | + testOk1(scratch[2]==0x4242); |
733 | + |
734 | + memset(scratch, 0x42, sizeof(s_input)); |
735 | + } |
736 | + |
737 | + { |
738 | + testDiag("Copy out w/ offset"); |
739 | + |
740 | + getter(&addr, scratch, 2, s_input_len, 1); |
741 | + |
742 | + testOk1(memcmp(scratch, s_input+1, sizeof(short)*2)==0); |
743 | + testOk1(scratch[2]==0x4242); |
744 | + |
745 | + memset(scratch, 0x42, sizeof(s_input)); |
746 | + } |
747 | + |
748 | + { |
749 | + testDiag("Copy out end of array"); |
750 | + |
751 | + getter(&addr, scratch, 2, s_input_len, s_input_len-2); |
752 | + |
753 | + testOk1(s_input_len-2 == 5); |
754 | + |
755 | + testOk1(memcmp(scratch, s_input+5, sizeof(short)*2)==0); |
756 | + testOk1(scratch[2]==0x4242); |
757 | + |
758 | + memset(scratch, 0x42, sizeof(s_input)); |
759 | + } |
760 | + |
761 | + { |
762 | + testDiag("Copy out with wrap"); |
763 | + |
764 | + getter(&addr, scratch, 2, s_input_len, s_input_len-1); |
765 | + |
766 | + testOk1(s_input_len-2 == 5); |
767 | + |
768 | + testOk1(scratch[0] == s_input[6]); |
769 | + testOk1(scratch[1] == s_input[0]); |
770 | + testOk1(scratch[2]==0x4242); |
771 | + |
772 | + memset(scratch, 0x42, sizeof(s_input)); |
773 | + } |
774 | + |
775 | + { |
776 | + testDiag("Crazy copy from out of bounds offset"); |
777 | + |
778 | + addr.pfield = (short*)(2*sizeof(short)); |
779 | + |
780 | + getter(&addr, scratch, s_input_len, s_input_len, (long)(s_input-2)/sizeof(short)); |
781 | + |
782 | + testOk1(memcmp(scratch, s_input, sizeof(s_input))==0); |
783 | + |
784 | + memset(scratch, 0x42, sizeof(s_input)); |
785 | + } |
786 | + |
787 | + free(scratch); |
788 | +} |
789 | + |
790 | +static void testBasicPut(void) |
791 | +{ |
792 | + short *scratch; |
793 | + DBADDR addr; |
794 | + PUTCONVERTFUNC putter; |
795 | + |
796 | + putter = dbPutConvertRoutine[DBF_SHORT][DBF_SHORT]; |
797 | + |
798 | + scratch = callocMustSucceed(s_input_len, sizeof(s_input), "testBasicPut"); |
799 | + |
800 | + memset(&addr, 0, sizeof(addr)); |
801 | + addr.field_type = DBF_SHORT; |
802 | + addr.field_size = s_input_len*sizeof(*scratch); |
803 | + addr.no_elements = s_input_len; |
804 | + addr.pfield = (void*)scratch; |
805 | + |
806 | + testDiag("Test dbPutConvertRoutine[DBF_SHORT][DBF_SHORT]"); |
807 | + |
808 | + { |
809 | + testDiag("Copy in first element"); |
810 | + |
811 | + putter(&addr, s_input, 1, s_input_len, 0); |
812 | + |
813 | + testOk1(scratch[0]==s_input[0]); |
814 | + |
815 | + memset(scratch, 0x42, sizeof(s_input)); |
816 | + } |
817 | + |
818 | + { |
819 | + testDiag("Copy in entire array"); |
820 | + |
821 | + putter(&addr, s_input, s_input_len, s_input_len, 0); |
822 | + |
823 | + testOk1(memcmp(scratch, s_input, sizeof(s_input))==0); |
824 | + |
825 | + memset(scratch, 0x42, sizeof(s_input)); |
826 | + } |
827 | + |
828 | +} |
829 | + |
830 | +MAIN(testdbConvert) |
831 | +{ |
832 | + testPlan(16); |
833 | + testBasicGet(); |
834 | + testBasicPut(); |
835 | + return testDone(); |
836 | +} |
On x86_64 Linux Intel(R) Xeon(R) CPU W3530 @ 2.80GHz
Before
$ ./src/ioc/ db/test/ O.linux- x86_64- debug/benchdbCo nvert | grep Final
# Final: 89.8318 ms +- 1.39919 ms. 111.3 MB/s (for 1 elements)
# Final: 93.7699 ms +- 0.56535 ms. 106.6 MB/s (for 2 elements)
# Final: 50.4515 ms +- 0.38340 ms. 198.2 MB/s (for 10 elements)
# Final: 41.5719 ms +- 0.17008 ms. 240.5 MB/s (for 100 elements)
# Final: 40.1080 ms +- 0.14451 ms. 249.3 MB/s (for 10000 elements)
# Final: 40.1119 ms +- 0.08290 ms. 249.3 MB/s (for 100000 elements)
# Final: 40.4242 ms +- 0.27215 ms. 247.4 MB/s (for 1000000 elements)
# Final: 41.1180 ms +- 1.41750 ms. 243.2 MB/s (for 10000000 elements)
After
$ ./src/ioc/ db/test/ O.linux- x86_64- debug/benchdbCo nvert | grep Final
# Final: 93.0104 ms +- 1.61940 ms. 107.5 MB/s (for 1 elements)
# Final: 76.3337 ms +- 0.39694 ms. 131.0 MB/s (for 2 elements)
# Final: 16.4737 ms +- 0.13362 ms. 607.0 MB/s (for 10 elements)
# Final: 2.2798 ms +- 0.10152 ms. 4386.4 MB/s (for 100 elements)
# Final: 1.0701 ms +- 0.06246 ms. 9345.2 MB/s (for 10000 elements)
# Final: 1.2648 ms +- 0.09690 ms. 7906.4 MB/s (for 100000 elements)
# Final: 2.2044 ms +- 0.14698 ms. 4536.4 MB/s (for 1000000 elements)
# Final: 4.0375 ms +- 1.74425 ms. 2476.8 MB/s (for 10000000 elements)