// Copyright 2017 The Emscripten Authors. All rights reserved. // Emscripten is available under two separate licenses, the MIT license and the // University of Illinois/NCSA Open Source License. Both these licenses can be // found in the LICENSE file. #include #include #include #include #include #include #ifdef WIN32 #include #define aligned_alloc(align, size) _aligned_malloc((size), (align)) #endif #ifdef __EMSCRIPTEN__ #include #endif #include "tick.h" char dst[1024*1024*64+16] = {}; uint8_t resultCheckSum = 0; void __attribute__((noinline)) test_memset(int numTimes, int copySize) { for(int i = 0; i < numTimes - 8; i += 8) { memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; } numTimes &= 15; for(int i = 0; i < numTimes; ++i) { memset(dst, i ^ 0xAA, copySize); resultCheckSum += dst[copySize >> 1]; } } std::vector copySizes; std::vector results; std::vector testCases; double totalTimeSecs = 0.0; void test_case(int copySize) { const int minimumCopyBytes = 1024*1024*64; int numTimes = (minimumCopyBytes + copySize-1) / copySize; if (numTimes < 8) numTimes = 8; tick_t bestResult = 1e9; #ifndef NUM_TRIALS #define NUM_TRIALS 5 #endif for(int i = 0; i < NUM_TRIALS; ++i) { double t0 = tick(); test_memset(numTimes, copySize); double t1 = tick(); if (t1 - t0 < bestResult) bestResult = t1 - t0; totalTimeSecs += (double)(t1 - t0) / ticks_per_sec(); } unsigned long long totalBytesTransferred = numTimes * copySize; copySizes.push_back(copySize); tick_t ticksElapsed = bestResult; if (ticksElapsed > 0) { double seconds = (double)ticksElapsed / ticks_per_sec(); double bytesPerSecond = totalBytesTransferred / seconds; double mbytesPerSecond = bytesPerSecond / (1024.0*1024.0); results.push_back(mbytesPerSecond); } else { results.push_back(0.0); } } void print_results() { std::cout << "Test cases: " << std::endl; for(size_t i = 0; i < copySizes.size(); ++i) { std::cout << copySizes[i]; if (i != copySizes.size()-1) std::cout << ","; else std::cout << std::endl; if (i % 10 == 9) std::cout << std::endl; } std::cout << std::endl; std::cout << std::endl; std::cout << std::endl; std::cout << "Test results: " << std::endl; for(size_t i = 0; i < results.size(); ++i) { std::cout << results[i]; if (i != results.size()-1) std::cout << ","; else std::cout << std::endl; if (i % 10 == 9) std::cout << std::endl; } std::cout << "Result checksum: " << (int)resultCheckSum << std::endl; std::cout << "Total time: " << totalTimeSecs << std::endl; } int numDone = 0; void run_one() { std::cout << (numDone+1) << "/" << (numDone+testCases.size()) << std::endl; ++numDone; int copySize = testCases.front(); testCases.erase(testCases.begin()); test_case(copySize); } #ifdef __EMSCRIPTEN__ void main_loop() { if (!testCases.empty()) { run_one(); } else { emscripten_cancel_main_loop(); print_results(); } } #endif #ifndef MAX_COPY #define MAX_COPY 32*1024*1024 #endif #ifndef MIN_COPY #define MIN_COPY 1 #endif int main() { for(int copySizeI = MIN_COPY; copySizeI < MAX_COPY; copySizeI <<= 1) for(int copySizeJ = 1; copySizeJ <= copySizeI; copySizeJ <<= 1) { testCases.push_back(copySizeI | copySizeJ); } std::sort(testCases.begin(), testCases.end()); #if defined(__EMSCRIPTEN__) && !defined(BUILD_FOR_SHELL) emscripten_set_main_loop(main_loop, 0, 0); #else while(!testCases.empty()) run_one(); print_results(); #endif }