Merge lp:~epics-core/epics-base/dbConvert-memmove into lp:~epics-core/epics-base/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
Reviewer Review Type Date Requested Status
Andrew Johnson Approve
Review via email: mp+223116@code.launchpad.net

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 :

On x86_64 Linux Intel(R) Xeon(R) CPU W3530 @ 2.80GHz

Before

$ ./src/ioc/db/test/O.linux-x86_64-debug/benchdbConvert | 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/benchdbConvert | 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)

Revision history for this message
Andrew Johnson (anj) wrote :

Nice.

review: Approve

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+}

Subscribers

People subscribed via source and target branches

to all changes: