Implement spend_cpu_cycles in assembly
The compiler was unrolling it previously, so we're doing assembly now for consistency.
This commit is contained in:
@@ -79,8 +79,8 @@ struct SubscriptionConfig {
|
||||
*/
|
||||
struct BenchmarkConfig {
|
||||
/// CPU-intensive loop iterations for /ok requests in resolve stage
|
||||
/// 0 = health check only, 7000 = default benchmark load (650ns, 1M req/s)
|
||||
int ok_resolve_iterations = 7000;
|
||||
/// 0 = health check only, 4000 = default benchmark load (740ns, 1M req/s)
|
||||
int ok_resolve_iterations = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,10 +1,61 @@
|
||||
#include "cpu_work.hpp"
|
||||
|
||||
void spend_cpu_cycles(int iterations) {
|
||||
// Perform CPU-intensive work that cannot be optimized away
|
||||
// Use inline assembly to prevent compiler optimization
|
||||
for (int i = 0; i < iterations; ++i) {
|
||||
// Simple loop with inline assembly barrier to prevent optimization
|
||||
asm volatile("");
|
||||
}
|
||||
}
|
||||
#if defined(__x86_64__) || defined(__amd64__)
|
||||
// x86-64 file-scoped assembly implementation
|
||||
#ifdef __APPLE__
|
||||
asm(".text\n"
|
||||
".globl _spend_cpu_cycles\n"
|
||||
"_spend_cpu_cycles:\n"
|
||||
" test %edi, %edi\n" // Test if iterations <= 0
|
||||
" jle .L_end\n" // Jump to end if <= 0
|
||||
".L_loop:\n" // Loop start
|
||||
" dec %edi\n" // Decrement iterations
|
||||
" jnz .L_loop\n" // Jump back if not zero
|
||||
".L_end:\n" // End
|
||||
" ret\n" // Return
|
||||
);
|
||||
#else
|
||||
asm(".text\n"
|
||||
".globl spend_cpu_cycles\n"
|
||||
".type spend_cpu_cycles, @function\n"
|
||||
"spend_cpu_cycles:\n"
|
||||
" test %edi, %edi\n" // Test if iterations <= 0
|
||||
" jle .L_end\n" // Jump to end if <= 0
|
||||
".L_loop:\n" // Loop start
|
||||
" dec %edi\n" // Decrement iterations
|
||||
" jnz .L_loop\n" // Jump back if not zero
|
||||
".L_end:\n" // End
|
||||
" ret\n" // Return
|
||||
".size spend_cpu_cycles, .-spend_cpu_cycles\n");
|
||||
#endif
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
// ARM64 file-scoped assembly implementation
|
||||
#ifdef __APPLE__
|
||||
asm(".text\n"
|
||||
".globl _spend_cpu_cycles\n"
|
||||
"_spend_cpu_cycles:\n"
|
||||
" cmp w0, wzr\n" // Compare iterations with zero
|
||||
" b.le .L_end\n" // Branch to end if <= 0
|
||||
".L_loop:\n" // Loop start
|
||||
" subs w0, w0, #1\n" // Decrement iterations and set flags
|
||||
" b.ne .L_loop\n" // Branch back if not zero
|
||||
".L_end:\n" // End
|
||||
" ret\n" // Return
|
||||
);
|
||||
#else
|
||||
asm(".text\n"
|
||||
".globl spend_cpu_cycles\n"
|
||||
".type spend_cpu_cycles, %function\n"
|
||||
"spend_cpu_cycles:\n"
|
||||
" cmp w0, wzr\n" // Compare iterations with zero
|
||||
" b.le .L_end\n" // Branch to end if <= 0
|
||||
".L_loop:\n" // Loop start
|
||||
" subs w0, w0, #1\n" // Decrement iterations and set flags
|
||||
" b.ne .L_loop\n" // Branch back if not zero
|
||||
".L_end:\n" // End
|
||||
" ret\n" // Return
|
||||
".size spend_cpu_cycles, spend_cpu_cycles\n");
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
extern "C" {
|
||||
|
||||
/**
|
||||
* @brief Perform CPU-intensive work for benchmarking and health check purposes.
|
||||
*
|
||||
@@ -10,6 +12,7 @@
|
||||
* @param iterations Number of loop iterations to perform
|
||||
*/
|
||||
void spend_cpu_cycles(int iterations);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Default CPU work iterations for health check benchmarking.
|
||||
@@ -18,4 +21,4 @@ void spend_cpu_cycles(int iterations);
|
||||
* /ok health check resolve stage. This value provides 650ns of CPU work
|
||||
* and achieves 1M requests/second throughput through the 4-stage pipeline.
|
||||
*/
|
||||
constexpr int DEFAULT_HEALTH_CHECK_ITERATIONS = 7000;
|
||||
constexpr int DEFAULT_HEALTH_CHECK_ITERATIONS = 4000;
|
||||
|
||||
@@ -79,6 +79,11 @@ void HttpHandler::on_connection_closed(Connection &conn) {
|
||||
void HttpHandler::on_write_buffer_drained(
|
||||
std::unique_ptr<Connection> &conn_ptr) {
|
||||
// Reset arena after all messages have been written for the next request
|
||||
auto *state = static_cast<HttpConnectionState *>(conn_ptr->user_data);
|
||||
if (state) {
|
||||
TRACE_EVENT("http", "reply",
|
||||
perfetto::Flow::Global(state->http_request_id));
|
||||
}
|
||||
on_connection_closed(*conn_ptr);
|
||||
conn_ptr->reset();
|
||||
on_connection_established(*conn_ptr);
|
||||
|
||||
@@ -88,7 +88,7 @@ struct HttpHandler : ConnectionHandler {
|
||||
resolveThread = std::thread{[this]() {
|
||||
pthread_setname_np(pthread_self(), "txn-resolve");
|
||||
for (;;) {
|
||||
auto guard = commitPipeline.acquire<1, 0>();
|
||||
auto guard = commitPipeline.acquire<1, 0>(/*maxBatch*/ 1);
|
||||
if (process_resolve_batch(guard.batch)) {
|
||||
return; // Shutdown signal received
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user