blob: fcb1e1b951bf69cc69cb3705a5431d98bd2b884c [file] [log] [blame]
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -07001/*
2 * Copyright (c) 2008 Travis Geiselbrecht
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <debug.h>
24#include <string.h>
25#include <malloc.h>
26#include <platform.h>
27#include <kernel/thread.h>
28
29static uint8_t *src;
30static uint8_t *dst;
31
32static uint8_t *src2;
33static uint8_t *dst2;
34
35#define BUFFER_SIZE (1024*1024)
36#define ITERATIONS 16
37
38extern void *mymemcpy(void *dst, const void *src, size_t len);
39extern void *mymemset(void *dst, int c, size_t len);
40
41static void *null_memcpy(void *dst, const void *src, size_t len)
42{
43 return dst;
44}
45
46static time_t bench_memcpy_routine(void *memcpy_routine(void *, const void *, size_t), size_t srcalign, size_t dstalign)
47{
48 int i;
49 time_t t0;
50
51 t0 = current_time();
52 for (i=0; i < ITERATIONS; i++) {
53 memcpy_routine(dst + dstalign, src + srcalign, BUFFER_SIZE);
54 }
55 return current_time() - t0;
56}
57
58static void bench_memcpy(void)
59{
60 time_t null, libc, mine;
61 size_t srcalign, dstalign;
62
Travis Geiselbrechteb946052008-09-07 22:32:49 -070063 printf("memcpy speed test\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070064 thread_sleep(200); // let the debug string clear the serial port
65
66 for (srcalign = 0; srcalign < 64; ) {
67 for (dstalign = 0; dstalign < 64; ) {
68
69 null = bench_memcpy_routine(&null_memcpy, srcalign, dstalign);
70 libc = bench_memcpy_routine(&memcpy, srcalign, dstalign);
71 mine = bench_memcpy_routine(&mymemcpy, srcalign, dstalign);
72
Travis Geiselbrechteb946052008-09-07 22:32:49 -070073 printf("srcalign %lu, dstalign %lu\n", srcalign, dstalign);
74 printf(" null memcpy %u msecs\n", null);
75 printf(" libc memcpy %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
76 printf(" my memcpy %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -070077
78 if (dstalign == 0)
79 dstalign = 1;
80 else
81 dstalign <<= 1;
82 }
83 if (srcalign == 0)
84 srcalign = 1;
85 else
86 srcalign <<= 1;
87 }
88}
89
90static void fillbuf(void *ptr, size_t len, uint32_t seed)
91{
92 size_t i;
93
94 for (i = 0; i < len; i++) {
95 ((char *)ptr)[i] = seed;
96 seed *= 0x1234567;
97 }
98}
99
100static void validate_memcpy(void)
101{
102 size_t srcalign, dstalign, size;
103 const size_t maxsize = 256;
104
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700105 printf("testing memcpy for correctness\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700106
107 /*
108 * do the simple tests to make sure that memcpy doesn't color outside
109 * the lines for all alignment cases
110 */
111 for (srcalign = 0; srcalign < 64; srcalign++) {
112 for (dstalign = 0; dstalign < 64; dstalign++) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700113// printf("srcalign %zu, dstalign %zu\n", srcalign, dstalign);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700114 for (size = 0; size < maxsize; size++) {
115
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700116// printf("srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700117
118 fillbuf(src, maxsize * 2, 567);
119 fillbuf(src2, maxsize * 2, 567);
120 fillbuf(dst, maxsize * 2, 123514);
121 fillbuf(dst2, maxsize * 2, 123514);
122
123 memcpy(dst + dstalign, src + srcalign, size);
124 mymemcpy(dst2 + dstalign, src2 + srcalign, size);
125
126 int comp = memcmp(dst, dst2, maxsize * 2);
127 if (comp != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700128 printf("error! srcalign %zu, dstalign %zu, size %zu\n", srcalign, dstalign, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700129 }
130 }
131 }
132 }
133}
134
135static time_t bench_memset_routine(void *memset_routine(void *, int, size_t), size_t dstalign)
136{
137 int i;
138 time_t t0;
139
140 t0 = current_time();
141 for (i=0; i < ITERATIONS; i++) {
142 memset_routine(dst + dstalign, 0, BUFFER_SIZE);
143 }
144 return current_time() - t0;
145}
146
147static void bench_memset(void)
148{
149 time_t libc, mine;
150 size_t dstalign;
151
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700152 printf("memset speed test\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700153 thread_sleep(200); // let the debug string clear the serial port
154
155 for (dstalign = 0; dstalign < 64; dstalign++) {
156
157 libc = bench_memset_routine(&memset, dstalign);
158 mine = bench_memset_routine(&mymemset, dstalign);
159
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700160 printf("dstalign %lu\n", dstalign);
161 printf(" libc memset %u msecs, %llu bytes/sec\n", libc, BUFFER_SIZE * ITERATIONS * 1000ULL / libc);
162 printf(" my memset %u msecs, %llu bytes/sec\n", mine, BUFFER_SIZE * ITERATIONS * 1000ULL / mine);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700163 }
164}
165
166static void validate_memset(void)
167{
168 size_t dstalign, size;
169 int c;
170 const size_t maxsize = 256;
171
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700172 printf("testing memset for correctness\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700173
174 for (dstalign = 0; dstalign < 64; dstalign++) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700175 printf("align %zd\n", dstalign);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700176 for (size = 0; size < maxsize; size++) {
177 for (c = 0; c < 256; c++) {
178
179 fillbuf(dst, maxsize * 2, 123514);
180 fillbuf(dst2, maxsize * 2, 123514);
181
182 memset(dst + dstalign, c, size);
183 mymemset(dst2 + dstalign, c, size);
184
185 int comp = memcmp(dst, dst2, maxsize * 2);
186 if (comp != 0) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700187 printf("error! align %zu, c %d, size %zu\n", dstalign, c, size);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700188 }
189 }
190 }
191 }
192}
193
Travis Geiselbrecht39deded2009-01-24 20:12:27 -0800194#if defined(WITH_LIB_CONSOLE)
195#include <lib/console.h>
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700196
197static int string_tests(int argc, cmd_args *argv)
198{
199 src = memalign(64, BUFFER_SIZE + 256);
200 dst = memalign(64, BUFFER_SIZE + 256);
201 src2 = memalign(64, BUFFER_SIZE + 256);
202 dst2 = memalign(64, BUFFER_SIZE + 256);
203
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700204 printf("src %p, dst %p\n", src, dst);
205 printf("src2 %p, dst2 %p\n", src2, dst2);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700206
207 if (argc < 3) {
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700208 printf("not enough arguments:\n");
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700209usage:
Travis Geiselbrechteb946052008-09-07 22:32:49 -0700210 printf("%s validate <routine>\n", argv[0].str);
211 printf("%s bench <routine>\n", argv[0].str);
Travis Geiselbrecht1d0df692008-09-01 02:26:09 -0700212 goto out;
213 }
214
215 if (!strcmp(argv[1].str, "validate")) {
216 if (!strcmp(argv[2].str, "memcpy")) {
217 validate_memcpy();
218 } else if (!strcmp(argv[2].str, "memset")) {
219 validate_memset();
220 }
221 } else if (!strcmp(argv[1].str, "bench")) {
222 if (!strcmp(argv[2].str, "memcpy")) {
223 bench_memcpy();
224 } else if (!strcmp(argv[2].str, "memset")) {
225 bench_memset();
226 }
227 } else {
228 goto usage;
229 }
230
231out:
232 free(src);
233 free(dst);
234 free(src2);
235 free(dst2);
236
237 return 0;
238}
239
240STATIC_COMMAND_START
241{ "string", NULL, &string_tests },
242STATIC_COMMAND_END(stringtests);
243
244#endif
245