Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
emscripten-core
GitHub Repository: emscripten-core/emscripten
Path: blob/main/test/benchmark/benchmark_memcpy.cpp
4133 views
1
// Copyright 2017 The Emscripten Authors. All rights reserved.
2
// Emscripten is available under two separate licenses, the MIT license and the
3
// University of Illinois/NCSA Open Source License. Both these licenses can be
4
// found in the LICENSE file.
5
6
#include <string.h>
7
#include <stdio.h>
8
#include <stdlib.h>
9
#include <vector>
10
#include <iostream>
11
#include <algorithm>
12
13
#ifdef WIN32
14
#include <Windows.h>
15
#define aligned_alloc(align, size) _aligned_malloc((size), (align))
16
#endif
17
18
#ifdef __EMSCRIPTEN__
19
#include <emscripten/emscripten.h>
20
#endif
21
22
#include "tick.h"
23
24
char dst[1024*1024*64+16] = {};
25
char src[1024*1024*64+16] = {};
26
27
uint8_t resultCheckSum = 0;
28
29
void __attribute__((noinline)) test_memcpy(int numTimes, int copySize)
30
{
31
for(int i = 0; i < numTimes - 8; i += 8)
32
{
33
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
34
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
35
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
36
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
37
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
38
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
39
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
40
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
41
}
42
numTimes &= 15;
43
for(int i = 0; i < numTimes; ++i)
44
{
45
memcpy(dst, src, copySize); resultCheckSum += dst[copySize >> 1];
46
}
47
}
48
49
std::vector<int> copySizes;
50
std::vector<double> results;
51
52
std::vector<int> testCases;
53
54
double totalTimeSecs = 0.0;
55
56
void test_case(int copySize)
57
{
58
const int minimumCopyBytes = 1024*1024*64;
59
60
int numTimes = (minimumCopyBytes + copySize-1) / copySize;
61
if (numTimes < 8) numTimes = 8;
62
63
tick_t bestResult = 1e9;
64
65
#ifndef NUM_TRIALS
66
#define NUM_TRIALS 5
67
#endif
68
69
for(int i = 0; i < NUM_TRIALS; ++i)
70
{
71
double t0 = tick();
72
test_memcpy(numTimes, copySize);
73
double t1 = tick();
74
if (t1 - t0 < bestResult) bestResult = t1 - t0;
75
totalTimeSecs += (double)(t1 - t0) / ticks_per_sec();
76
}
77
unsigned long long totalBytesTransferred = numTimes * copySize;
78
79
copySizes.push_back(copySize);
80
81
tick_t ticksElapsed = bestResult;
82
if (ticksElapsed > 0)
83
{
84
double seconds = (double)ticksElapsed / ticks_per_sec();
85
double bytesPerSecond = totalBytesTransferred / seconds;
86
double mbytesPerSecond = bytesPerSecond / (1024.0*1024.0);
87
results.push_back(mbytesPerSecond);
88
}
89
else
90
{
91
results.push_back(0.0);
92
}
93
}
94
95
void print_results()
96
{
97
std::cout << "Test cases: " << std::endl;
98
for(size_t i = 0; i < copySizes.size(); ++i)
99
{
100
std::cout << copySizes[i];
101
if (i != copySizes.size()-1) std::cout << ", ";
102
else std::cout << std::endl;
103
if (i % 10 == 9) std::cout << std::endl;
104
}
105
std::cout << std::endl;
106
std::cout << std::endl;
107
std::cout << std::endl;
108
std::cout << "Test results: " << std::endl;
109
for(size_t i = 0; i < results.size(); ++i)
110
{
111
std::cout << results[i];
112
if (i != results.size()-1) std::cout << ", ";
113
else std::cout << std::endl;
114
if (i % 10 == 9) std::cout << std::endl;
115
}
116
117
std::cout << "Result checksum: " << (int)resultCheckSum << std::endl;
118
std::cout << "Total time: " << totalTimeSecs << std::endl;
119
}
120
121
int numDone = 0;
122
123
void run_one()
124
{
125
std::cout << (numDone+1) << "/" << (numDone+testCases.size()) << std::endl;
126
++numDone;
127
128
int copySize = testCases.front();
129
testCases.erase(testCases.begin());
130
test_case(copySize);
131
}
132
133
#ifdef __EMSCRIPTEN__
134
void main_loop()
135
{
136
if (!testCases.empty())
137
{
138
run_one();
139
}
140
else
141
{
142
emscripten_cancel_main_loop();
143
print_results();
144
}
145
}
146
#endif
147
148
#ifndef MAX_COPY
149
#define MAX_COPY 32*1024*1024
150
#endif
151
152
#ifndef MIN_COPY
153
#define MIN_COPY 1
154
#endif
155
156
int main()
157
{
158
for(int copySizeI = MIN_COPY; copySizeI < MAX_COPY; copySizeI <<= 1)
159
for(int copySizeJ = 1; copySizeJ <= copySizeI; copySizeJ <<= 1)
160
{
161
testCases.push_back(copySizeI | copySizeJ);
162
}
163
164
std::sort(testCases.begin(), testCases.end());
165
#if defined(__EMSCRIPTEN__) && !defined(BUILD_FOR_SHELL)
166
emscripten_set_main_loop(main_loop, 0, 0);
167
#else
168
while(!testCases.empty()) run_one();
169
print_results();
170
#endif
171
}
172
173