asmjit_bench_codegen.h (3099B)
1 // This file is part of AsmJit project <https://asmjit.com> 2 // 3 // See <asmjit/core.h> or LICENSE.md for license and copyright information 4 // SPDX-License-Identifier: Zlib 5 6 #ifndef ASMJIT_TEST_PERF_H_INCLUDED 7 #define ASMJIT_TEST_PERF_H_INCLUDED 8 9 #include <asmjit/core.h> 10 11 #include "../commons/asmjitutils.h" 12 #include "../commons/performancetimer.h" 13 14 namespace asmjit_perf_utils { 15 16 class TestErrorHandler : public asmjit::ErrorHandler { 17 void handle_error(asmjit::Error err, const char* message, asmjit::BaseEmitter* origin) override { 18 (void)err; 19 (void)origin; 20 printf("ERROR: %s\n", message); 21 abort(); 22 } 23 }; 24 25 #ifndef ASMJIT_NO_BUILDER 26 template<typename BuilderT, typename FuncT> 27 static uint32_t calculate_instruction_count(asmjit::CodeHolder& code, asmjit::Arch arch, const FuncT& func) noexcept { 28 BuilderT builder; 29 TestErrorHandler eh; 30 31 asmjit::Environment env(arch); 32 code.init(env); 33 code.set_error_handler(&eh); 34 code.attach(&builder); 35 func(builder); 36 37 uint32_t count = 0; 38 asmjit::BaseNode* node = builder.first_node(); 39 40 while (node) { 41 count += uint32_t(node->is_inst()); 42 node = node->next(); 43 } 44 45 code.reset(); 46 return count; 47 } 48 #endif 49 50 static inline double calculate_mbps(double duration_us, uint64_t output_size) noexcept { 51 if (duration_us == 0) 52 return 0.0; 53 54 double bytes_total = double(output_size); 55 return (bytes_total * 1000000) / (duration_us * 1024 * 1024); 56 } 57 58 static inline double calculate_mips(double duration, uint64_t instruction_count) noexcept { 59 if (duration == 0) 60 return 0.0; 61 62 return double(instruction_count) * 1000000.0 / (duration * 1e6); 63 } 64 65 template<typename EmitterT, typename FuncT> 66 static void bench(asmjit::CodeHolder& code, asmjit::Arch arch, uint32_t num_iterations, const char* test_name, uint32_t instruction_count, const FuncT& func) noexcept { 67 EmitterT emitter; 68 TestErrorHandler eh; 69 70 const char* arch_name = asmjit_arch_as_string(arch); 71 const char* emitter_name = 72 emitter.is_assembler() ? "Assembler" : 73 emitter.is_compiler() ? "Compiler" : 74 emitter.is_builder() ? "Builder" : "Unknown"; 75 76 uint64_t code_size = 0; 77 asmjit::Environment env(arch); 78 79 PerformanceTimer timer; 80 double duration = std::numeric_limits<double>::infinity(); 81 82 code.init(env); 83 code.set_error_handler(&eh); 84 code.attach(&emitter); 85 86 for (uint32_t r = 0; r < num_iterations; r++) { 87 code_size = 0; 88 89 timer.start(); 90 func(emitter); 91 code_size += code.code_size(); 92 93 code.reinit(); 94 timer.stop(); 95 96 duration = asmjit::Support::min(duration, timer.duration() * 1000); 97 } 98 99 printf(" [%-7s] %-9s %-16s | CodeSize:%5llu [B] | Time:%7.3f [us]", arch_name, emitter_name, test_name, (unsigned long long)code_size, duration); 100 if (code_size) { 101 printf(" | Speed:%7.1f [MiB/s]", calculate_mbps(duration, code_size)); 102 } 103 else { 104 printf(" | Speed: N/A "); 105 } 106 107 if (instruction_count) { 108 printf(", %8.1f [MInst/s]", calculate_mips(duration, instruction_count)); 109 } 110 111 printf("\n"); 112 code.reset(); 113 } 114 115 } // {asmjit_perf_utils} 116 117 #endif // ASMJIT_TEST_PERF_H_INCLUDED