diff --git a/include/silk/util/assert.h b/include/silk/util/assert.h index 58dfba5..a7b764b 100644 --- a/include/silk/util/assert.h +++ b/include/silk/util/assert.h @@ -16,12 +16,18 @@ static constexpr bool DebugAssertionsEnabled = false; #endif /** - * Print a symbolized stack trace, the error message, and optional details, then abort. + * Print a symbolized stack trace, the error message, optional printf-formatted + * details, and abort. `fmt` is a printf-style format string; pass nullptr (or + * omit) to skip the details line. */ -[[noreturn]] void assertFail(const char * message, const char * file, int line, const char * details = nullptr) noexcept; +[[noreturn]] void assertFail(const char * message, const char * file, int line, const char * fmt = nullptr, ...) noexcept + __attribute__((format(printf, 4, 5))); } // namespace silk +// Unconditional abort. +#define SILK_FAIL(message, ...) silk::assertFail(message, __FILE__, __LINE__ __VA_OPT__(, ) __VA_ARGS__) + // Assertion active in all builds unless DISABLE_ASSERTIONS is defined. // Use for invariants that must hold in release -- hard internal contract violations. #define SILK_ASSERT(condition, ...) \ @@ -29,7 +35,7 @@ static constexpr bool DebugAssertionsEnabled = false; { \ if (silk::ReleaseAssertionsEnabled && !(condition)) [[unlikely]] \ { \ - silk::assertFail("assertion failed: " #condition, __FILE__, __LINE__ __VA_OPT__(, std::format(__VA_ARGS__).c_str())); \ + silk::assertFail("assertion failed: " #condition, __FILE__, __LINE__ __VA_OPT__(, ) __VA_ARGS__); \ } \ } while (0) @@ -40,6 +46,6 @@ static constexpr bool DebugAssertionsEnabled = false; { \ if (silk::DebugAssertionsEnabled && !(condition)) [[unlikely]] \ { \ - silk::assertFail("assertion failed: " #condition, __FILE__, __LINE__ __VA_OPT__(, std::format(__VA_ARGS__).c_str())); \ + silk::assertFail("assertion failed: " #condition, __FILE__, __LINE__ __VA_OPT__(, ) __VA_ARGS__); \ } \ } while (0) diff --git a/include/silk/util/logger.h b/include/silk/util/logger.h index 7fecc5b..1f9e474 100644 --- a/include/silk/util/logger.h +++ b/include/silk/util/logger.h @@ -1,12 +1,12 @@ #pragma once #include -#include -#include namespace silk { +// Log severity, ordered low-to-high. A record is emitted when its level is +// >= the logger's configured minimum (default INFO; change via Logger::setLevel). enum class LogLevel { DEBUG, @@ -26,20 +26,16 @@ class Logger { public: /** Set the minimum level for messages to be emitted. */ - static void setLevel(LogLevel level) noexcept; + static void setLevel(LogLevel level) noexcept { currentLevel.store(level, std::memory_order_relaxed); } /** Return true if messages at the given level would be emitted. */ static bool isEnabled(LogLevel level) noexcept { return level >= currentLevel.load(std::memory_order_relaxed); } - /** Emit a pre-formatted message. */ - static void log(LogLevel level, std::string_view file, int line, std::string_view message) noexcept; + /** Emit a pre-formatted message verbatim (no printf parsing). */ + static void log(LogLevel level, const char * file, int line, const char * message) noexcept; - /** Format and emit a message. */ - template - static void log(LogLevel level, std::string_view file, int line, std::format_string fmt, Args &&... args) noexcept - { - log(level, file, line, std::format(fmt, std::forward(args)...)); - } + /** Emit a printf-formatted message. */ + static void logf(LogLevel level, const char * file, int line, const char * fmt, ...) noexcept __attribute__((format(printf, 4, 5))); private: inline static std::atomic currentLevel{LogLevel::INFO}; @@ -47,9 +43,22 @@ class Logger } // namespace silk -// clang-format off -#define SILK_DEBUG(...) do { if (silk::Logger::isEnabled(silk::LogLevel::DEBUG)) silk::Logger::log(silk::LogLevel::DEBUG, __FILE__, __LINE__, __VA_ARGS__); } while (0) -#define SILK_INFO(...) do { if (silk::Logger::isEnabled(silk::LogLevel::INFO)) silk::Logger::log(silk::LogLevel::INFO, __FILE__, __LINE__, __VA_ARGS__); } while (0) -#define SILK_WARN(...) do { if (silk::Logger::isEnabled(silk::LogLevel::WARN)) silk::Logger::log(silk::LogLevel::WARN, __FILE__, __LINE__, __VA_ARGS__); } while (0) -#define SILK_ERROR(...) do { if (silk::Logger::isEnabled(silk::LogLevel::ERROR)) silk::Logger::log(silk::LogLevel::ERROR, __FILE__, __LINE__, __VA_ARGS__); } while (0) -// clang-format on +// Emit a log record at the given level. Dispatches to Logger::log for plain +// strings (SILK_INFO("text")) and to Logger::logf for printf-style calls +// (SILK_INFO("foo %d", x)) -- the latter is the only path that pays vsnprintf. +// The format string is checked at every call site (-Wformat); formatting only +// runs when the level is enabled, so a disabled-level call site is one relaxed +// atomic load. +#define SILK_LOG(level, fmt, ...) \ + do \ + { \ + if (silk::Logger::isEnabled(level)) \ + { \ + silk::Logger::log##__VA_OPT__(f)(level, __FILE__, __LINE__, fmt __VA_OPT__(, ) __VA_ARGS__); \ + } \ + } while (0) + +#define SILK_DEBUG(fmt, ...) SILK_LOG(silk::LogLevel::DEBUG, fmt __VA_OPT__(, ) __VA_ARGS__) +#define SILK_INFO(fmt, ...) SILK_LOG(silk::LogLevel::INFO, fmt __VA_OPT__(, ) __VA_ARGS__) +#define SILK_WARN(fmt, ...) SILK_LOG(silk::LogLevel::WARN, fmt __VA_OPT__(, ) __VA_ARGS__) +#define SILK_ERROR(fmt, ...) SILK_LOG(silk::LogLevel::ERROR, fmt __VA_OPT__(, ) __VA_ARGS__) diff --git a/src/fibers/fiber.cpp b/src/fibers/fiber.cpp index 2597ba8..9b9eb7e 100644 --- a/src/fibers/fiber.cpp +++ b/src/fibers/fiber.cpp @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -398,7 +397,7 @@ void Fiber::fiberContextMain(boost::context::detail::transfer_t transfer) noexce fiber->result = fiber->fiberMain(fiber->parameters); fiber->changeState(FiberState::RUNNING, FiberState::STOPPED); fiber->switchToThreadContext(true); - SILK_ASSERT(false, "unreachable"); + SILK_FAIL("unreachable"); } void Fiber::changeState(FiberState expectedState, FiberState newState) noexcept @@ -406,7 +405,7 @@ void Fiber::changeState(FiberState expectedState, FiberState newState) noexcept FiberState prevState = state.exchange(newState, std::memory_order_acq_rel); SILK_ASSERT( prevState == expectedState, - "invalid fiber state: expected={}, actual={}", + "invalid fiber state: expected=%d, actual=%d", static_cast(expectedState), static_cast(prevState)); } @@ -430,7 +429,7 @@ bool Fiber::tryChangeStateToSuspended() noexcept // runFiber will enqueue the fiber after the callback returns. return false; default: - SILK_ASSERT(false, "Unexpected fiber state: {}", static_cast(currentState)); + SILK_FAIL("unexpected fiber state", "state=%d", static_cast(currentState)); } } } @@ -457,7 +456,7 @@ bool Fiber::tryChangeStateToReady() noexcept } break; default: - SILK_ASSERT(false, "Unexpected fiber state: {}", static_cast(currentState)); + SILK_FAIL("unexpected fiber state", "state=%d", static_cast(currentState)); } } } diff --git a/src/fibers/mutex.cpp b/src/fibers/mutex.cpp index e89ac23..a25adaf 100644 --- a/src/fibers/mutex.cpp +++ b/src/fibers/mutex.cpp @@ -5,7 +5,6 @@ #include #include -#include namespace silk { diff --git a/src/perf/fiber-http.cpp b/src/perf/fiber-http.cpp index 82b361e..b6303ad 100644 --- a/src/perf/fiber-http.cpp +++ b/src/perf/fiber-http.cpp @@ -8,7 +8,6 @@ #include #include -#include #include #include @@ -130,7 +129,7 @@ bool FiberSocketImpl::poll(const Poco::Timespan & timeout, int mode) int FiberSocketImpl::sendBytes(const void * buffer, int length, int flags) { // Poco flags (MSG_NOSIGNAL, MSG_PEEK, etc.) are not plumbed through to io_uring read/write. - SILK_ASSERT(flags == 0, "FiberSocketImpl::sendBytes does not support flags (got {})", flags); + SILK_ASSERT(flags == 0, "FiberSocketImpl::sendBytes does not support flags (got %d)", flags); int total = 0; const char * ptr = static_cast(buffer); @@ -170,7 +169,7 @@ int FiberSocketImpl::sendBytes(const void * buffer, int length, int flags) int FiberSocketImpl::receiveBytes(void * buffer, int length, int flags) { // Poco flags (MSG_NOSIGNAL, MSG_PEEK, etc.) are not plumbed through to io_uring read/write. - SILK_ASSERT(flags == 0, "FiberSocketImpl::receiveBytes does not support flags (got {})", flags); + SILK_ASSERT(flags == 0, "FiberSocketImpl::receiveBytes does not support flags (got %d)", flags); #if defined(USE_IO_URING_RW) uint64_t bytesRead = 0; diff --git a/src/perf/file-perf.cpp b/src/perf/file-perf.cpp index 37ff7d8..b77e687 100644 --- a/src/perf/file-perf.cpp +++ b/src/perf/file-perf.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -221,7 +220,7 @@ void Benchmark::start() for (Job & job : jobs) { int r = silk::FiberScheduler::run(workerFiberMain, {this, &job}, &job.future); - SILK_ASSERT(!r, "cannot start fiber: {}", std::strerror(r)); + SILK_ASSERT(!r, "cannot start fiber: %s", std::strerror(r)); } warmupEndCycles.store(silk::Tsc::getCycles() + silk::Tsc::nanosecondsToCycles(cfg.warmupNs), std::memory_order_relaxed); @@ -280,7 +279,7 @@ int Benchmark::workerFiberMain(WorkerFiberParams * params) noexcept int r = slot->future.wait(); if (r) { - SILK_ERROR("request failed: {}", std::strerror(r)); + SILK_ERROR("request failed: %s", std::strerror(r)); break; } @@ -300,7 +299,7 @@ int Benchmark::workerFiberMain(WorkerFiberParams * params) noexcept for (uint32_t i = 0; i < benchmark->cfg.iodepth; ++i) { int r = job->slots[i].future.wait(); - SILK_ERROR("request failed: {}", std::strerror(r)); + SILK_ERROR("request failed: %s", std::strerror(r)); } return 0; @@ -403,14 +402,14 @@ int main(int argc, char ** argv) int openFlags = O_RDWR | O_CREAT | O_TRUNC | O_CLOEXEC | (cfg.direct ? O_DIRECT : 0); int fd = ::open(cfg.filename.c_str(), openFlags, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); - SILK_ASSERT(fd >= 0, "open failed: {}", std::strerror(errno)); + SILK_ASSERT(fd >= 0, "open failed: %s", std::strerror(errno)); struct stat st; int r = ::fstat(fd, &st); - SILK_ASSERT(!r, "fstat failed: {}", std::strerror(errno)); + SILK_ASSERT(!r, "fstat failed: %s", std::strerror(errno)); r = ::fallocate(fd, 0, 0, static_cast(cfg.fileSize)); - SILK_ASSERT(!r, "fallocate failed: {}", std::strerror(errno)); + SILK_ASSERT(!r, "fallocate failed: %s", std::strerror(errno)); sigset_t mask = blockSignals(); @@ -426,8 +425,8 @@ int main(int argc, char ** argv) silk::FiberScheduler::initialize(&options); SILK_INFO( - "starting benchmark on: {} size={:.1f}GiB{}", - cfg.filename, + "starting benchmark on: %s size=%.1fGiB%s", + cfg.filename.c_str(), static_cast(cfg.fileSize) / (1024.0 * 1024 * 1024), cfg.direct ? " direct" : ""); @@ -440,13 +439,13 @@ int main(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } diff --git a/src/perf/http-perf.cpp b/src/perf/http-perf.cpp index d3e1a35..e4196e8 100644 --- a/src/perf/http-perf.cpp +++ b/src/perf/http-perf.cpp @@ -34,7 +34,6 @@ #include #include #include -#include #include #include #include @@ -135,7 +134,7 @@ void Client::start() else { int r = silk::FiberScheduler::run(fiberMain, {this, &conn}, &conn.future); - SILK_ASSERT(!r, "cannot start fiber: {}", std::strerror(r)); + SILK_ASSERT(!r, "cannot start fiber: %s", std::strerror(r)); } } @@ -156,7 +155,7 @@ void Client::stop() { if (!isExpectedShutdown(e.code())) { - SILK_ERROR("shutdown failed: {}", e.displayText()); + SILK_ERROR("shutdown failed: %s", e.displayText().c_str()); } } } @@ -204,7 +203,7 @@ void Client::runLoop(Connection * conn) noexcept { if (!stopping.load(std::memory_order_relaxed) && !isExpectedShutdown(e.code())) { - SILK_ERROR("HTTP request failed: {}", e.displayText()); + SILK_ERROR("HTTP request failed: %s", e.displayText().c_str()); } break; } @@ -308,9 +307,9 @@ static void runClient(int argc, char ** argv) } SILK_INFO( - "starting {} http client, host={}:{}, connections={}", + "starting %s http client, host=%s:%u, connections=%u", cfg.useThreads ? "threaded" : "fiber", - cfg.host, + cfg.host.c_str(), cfg.port, cfg.numConnections); @@ -319,13 +318,13 @@ static void runClient(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } @@ -492,7 +491,7 @@ class FiberHTTPServer void FiberHTTPServer::start() { int r = silk::FiberScheduler::run(acceptFiberMain, AcceptFiberParams{this}, &acceptFuture); - SILK_ASSERT(r == 0, "spawn accept fiber: {}", std::strerror(r)); + SILK_ASSERT(r == 0, "spawn accept fiber: %s", std::strerror(r)); } void FiberHTTPServer::stop() @@ -509,12 +508,12 @@ void FiberHTTPServer::stop() { if (!isExpectedShutdown(e.code())) { - SILK_ERROR("shutdown failed: {}", e.displayText()); + SILK_ERROR("shutdown failed: %s", e.displayText().c_str()); } } int r = acceptFuture.wait(); - SILK_ASSERT(r == 0, "accept fiber: {}", std::strerror(r)); + SILK_ASSERT(r == 0, "accept fiber: %s", std::strerror(r)); socket.close(); @@ -530,7 +529,7 @@ void FiberHTTPServer::stop() { if (!isExpectedShutdown(e.code())) { - SILK_ERROR("shutdown failed: {}", e.displayText()); + SILK_ERROR("shutdown failed: %s", e.displayText().c_str()); } } } @@ -556,7 +555,7 @@ void FiberHTTPServer::acceptLoop() noexcept { if (!stopping.load(std::memory_order_relaxed) && !isExpectedShutdown(e.code())) { - SILK_ERROR("accept failed: {}", e.displayText()); + SILK_ERROR("accept failed: %s", e.displayText().c_str()); } return; } @@ -571,7 +570,7 @@ void FiberHTTPServer::acceptLoop() noexcept int r = silk::FiberScheduler::run(connFiberMain, ConnFiberParams{this, clientSocket}, &conn->future); if (r != 0) { - SILK_ERROR("spawn conn fiber: {}", std::strerror(r)); + SILK_ERROR("spawn conn fiber: %s", std::strerror(r)); { std::lock_guard lock(connsMutex); conns.remove(conn); @@ -593,7 +592,7 @@ void FiberHTTPServer::connectionLoop(Poco::Net::StreamSocket socket) noexcept { if (!stopping.load(std::memory_order_relaxed) && !isExpectedShutdown(e.code())) { - SILK_ERROR("connection error: {}", e.displayText()); + SILK_ERROR("connection error: %s", e.displayText().c_str()); } } } @@ -668,11 +667,11 @@ static void runServer(int argc, char ** argv) Poco::Net::HTTPRequestHandlerFactory::Ptr factory = new EchoHandlerFactory(handlerCfg); SILK_INFO( - "starting {} http server on port {}, queued={}, delay={}", + "starting %s http server on port %u, queued=%u, delay=%s", cfg.useThreads ? "threaded" : "fiber", cfg.port, cfg.maxQueued, - formatDuration(cfg.delayNs)); + formatDuration(cfg.delayNs).c_str()); if (cfg.useThreads) { diff --git a/src/perf/net-perf-asio.cpp b/src/perf/net-perf-asio.cpp index 7d786b4..13bbf8c 100644 --- a/src/perf/net-perf-asio.cpp +++ b/src/perf/net-perf-asio.cpp @@ -115,7 +115,7 @@ asio::awaitable Server::acceptLoop() { if (!isExpectedShutdown(ec)) { - SILK_ERROR("accept failed: {}", ec.message()); + SILK_ERROR("accept failed: %s", ec.message().c_str()); } break; } @@ -147,7 +147,7 @@ asio::awaitable Server::handleConnection(Server * server, std::shared_ptr< { if (!isExpectedShutdown(ec)) { - SILK_ERROR("read failed: {}", ec.message()); + SILK_ERROR("read failed: %s", ec.message().c_str()); } co_return; } @@ -168,7 +168,7 @@ asio::awaitable Server::handleConnection(Server * server, std::shared_ptr< { if (!isExpectedShutdown(ec)) { - SILK_ERROR("sleep failed: {}", ec.message()); + SILK_ERROR("sleep failed: %s", ec.message().c_str()); } co_return; } @@ -183,7 +183,7 @@ asio::awaitable Server::handleConnection(Server * server, std::shared_ptr< { if (!isExpectedShutdown(ec)) { - SILK_ERROR("write failed: {}", ec.message()); + SILK_ERROR("write failed: %s", ec.message().c_str()); } co_return; } @@ -297,7 +297,7 @@ asio::awaitable Client::clientConnection(Client * client, Connection * con { if (!isExpectedShutdown(ec)) { - SILK_ERROR("write failed: {}", ec.message()); + SILK_ERROR("write failed: %s", ec.message().c_str()); } co_return; } @@ -313,7 +313,7 @@ asio::awaitable Client::clientConnection(Client * client, Connection * con { if (!isExpectedShutdown(ec)) { - SILK_ERROR("read failed: {}", ec.message()); + SILK_ERROR("read failed: %s", ec.message().c_str()); } co_return; } @@ -428,7 +428,7 @@ static void runServer(int argc, char ** argv) Server server(ioc, cfg); server.start(); - SILK_INFO("starting server on {}:{}", cfg.host, cfg.port); + SILK_INFO("starting server on %s:%u", cfg.host.c_str(), cfg.port); int sig = 0; sigwait(&mask, &sig); @@ -515,13 +515,13 @@ static void runClient(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } diff --git a/src/perf/net-perf-epoll.cpp b/src/perf/net-perf-epoll.cpp index 86b53e5..ecc0a63 100644 --- a/src/perf/net-perf-epoll.cpp +++ b/src/perf/net-perf-epoll.cpp @@ -119,7 +119,7 @@ int Event::create(Event * out) noexcept if (fd < 0) { int r = errno; - SILK_ERROR("eventfd failed: {}", std::strerror(r)); + SILK_ERROR("eventfd failed: %s", std::strerror(r)); return r; } *out = Event(fd); @@ -133,7 +133,7 @@ int Event::trigger() noexcept if (n != sizeof(value)) { int r = errno; - SILK_ERROR("write eventfd failed: {}", std::strerror(r)); + SILK_ERROR("write eventfd failed: %s", std::strerror(r)); return r; } return 0; @@ -205,7 +205,7 @@ int Epoll::create(Epoll * out) noexcept if (fd < 0) { int r = errno; - SILK_ERROR("epoll_create1 failed: {}", std::strerror(r)); + SILK_ERROR("epoll_create1 failed: %s", std::strerror(r)); return r; } *out = Epoll(fd); @@ -221,7 +221,7 @@ int Epoll::add(int fd, uint32_t events, void * ptr) noexcept if (r) { r = errno; - SILK_ERROR("epoll_ctl ADD failed: {}", std::strerror(r)); + SILK_ERROR("epoll_ctl ADD failed: %s", std::strerror(r)); return r; } return 0; @@ -233,7 +233,7 @@ int Epoll::del(int fd) noexcept if (r) { r = errno; - SILK_ERROR("epoll_ctl DEL failed: {}", std::strerror(r)); + SILK_ERROR("epoll_ctl DEL failed: %s", std::strerror(r)); return r; } return 0; @@ -247,7 +247,7 @@ int Epoll::wait(epoll_event * events, int maxEvents, int timeoutMs, int * outCou int r = errno; if (r != EINTR) { - SILK_ERROR("epoll_wait failed: {}", std::strerror(r)); + SILK_ERROR("epoll_wait failed: %s", std::strerror(r)); } return r; } @@ -334,7 +334,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out int r = ::inet_pton(AF_INET, host, &addr.sin_addr); if (r != 1) { - SILK_ERROR("inet_pton failed: invalid address {}", host); + SILK_ERROR("inet_pton failed: invalid address %s", host); return EINVAL; } @@ -345,7 +345,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (fd < 0) { r = errno; - SILK_ERROR("socket failed: {}", std::strerror(r)); + SILK_ERROR("socket failed: %s", std::strerror(r)); return r; } @@ -354,7 +354,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (r) { r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -363,7 +363,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (r) { r = errno; - SILK_ERROR("connect failed: {}", std::strerror(r)); + SILK_ERROR("connect failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -372,7 +372,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (flags < 0) { r = errno; - SILK_ERROR("fcntl F_GETFL failed: {}", std::strerror(r)); + SILK_ERROR("fcntl F_GETFL failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -381,7 +381,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (r) { r = errno; - SILK_ERROR("fcntl F_SETFL O_NONBLOCK failed: {}", std::strerror(r)); + SILK_ERROR("fcntl F_SETFL O_NONBLOCK failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -405,7 +405,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn int r = ::inet_pton(AF_INET, host, &addr.sin_addr); if (r != 1) { - SILK_ERROR("inet_pton failed: invalid address {}", host); + SILK_ERROR("inet_pton failed: invalid address %s", host); return EINVAL; } } @@ -414,7 +414,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (fd < 0) { int r = errno; - SILK_ERROR("socket failed: {}", std::strerror(r)); + SILK_ERROR("socket failed: %s", std::strerror(r)); return r; } @@ -423,7 +423,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (r) { r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -432,7 +432,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (r) { r = errno; - SILK_ERROR("setsockopt SO_REUSEADDR failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt SO_REUSEADDR failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -444,7 +444,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (r) { r = errno; - SILK_ERROR("setsockopt SO_REUSEPORT failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt SO_REUSEPORT failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -453,7 +453,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (r) { r = errno; - SILK_ERROR("bind failed: {}", std::strerror(r)); + SILK_ERROR("bind failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -462,7 +462,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (r) { r = errno; - SILK_ERROR("listen failed: {}", std::strerror(r)); + SILK_ERROR("listen failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -485,7 +485,7 @@ int TcpConnection::accept(TcpConnection * out) noexcept if (r) { r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -603,7 +603,7 @@ Server::Server(const ServerConfig & cfg) for (Worker & worker : workers) { int r = TcpConnection::listen(cfg.host.c_str(), cfg.port, LISTEN_BACKLOG, &worker.listener); - SILK_ASSERT(!r, "listen failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "listen failed: %s", std::strerror(r)); } } @@ -622,7 +622,7 @@ void Server::start() for (Worker & worker : workers) { int r = Event::create(&worker.stopEvent); - SILK_ASSERT(!r, "Event::create failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "Event::create failed: %s", std::strerror(r)); worker.thread = std::thread(workerMain, WorkerParams{this, &worker}); } @@ -693,7 +693,7 @@ bool Server::drive(Connection * conn, uint32_t msgSize) noexcept } if (!isExpectedShutdown(r)) { - SILK_ERROR("read failed: {}", std::strerror(r)); + SILK_ERROR("read failed: %s", std::strerror(r)); } return false; } @@ -721,7 +721,7 @@ bool Server::drive(Connection * conn, uint32_t msgSize) noexcept } if (!isExpectedShutdown(r)) { - SILK_ERROR("write failed: {}", std::strerror(r)); + SILK_ERROR("write failed: %s", std::strerror(r)); } return false; } @@ -734,7 +734,7 @@ void Server::workerMain(WorkerParams params) noexcept Epoll epoll; int r = Epoll::create(&epoll); - SILK_ASSERT(!r, "Epoll::create failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "Epoll::create failed: %s", std::strerror(r)); ListenerTag listenerTag; StopTag stopTag; @@ -755,7 +755,7 @@ void Server::workerMain(WorkerParams params) noexcept { continue; } - SILK_ASSERT(!r, "epoll_wait failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "epoll_wait failed: %s", std::strerror(r)); for (int i = 0; i < eventCount; ++i) { @@ -782,7 +782,7 @@ void Server::workerMain(WorkerParams params) noexcept } if (!isExpectedShutdown(ar)) { - SILK_ERROR("accept failed: {}", std::strerror(ar)); + SILK_ERROR("accept failed: %s", std::strerror(ar)); } break; } @@ -931,7 +931,7 @@ void Client::start() for (Connection & connection : connections) { int r = TcpConnection::connect(cfg.host.c_str(), cfg.port, &connection.conn); - SILK_ASSERT(!r, "connect failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "connect failed: %s", std::strerror(r)); SILK_ASSERT(cfg.msgSize >= sizeof(uint32_t)); connection.buf = std::make_unique(cfg.msgSize); std::memset(connection.buf.get(), 0xAB, cfg.msgSize); @@ -946,7 +946,7 @@ void Client::start() { Worker & worker = workers[i]; int r = Event::create(&worker.stopEvent); - SILK_ASSERT(!r, "Event::create failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "Event::create failed: %s", std::strerror(r)); worker.connections = connections.data() + connIdx; worker.connCount = base + (i < extra ? 1 : 0); connIdx += worker.connCount; @@ -1036,7 +1036,7 @@ bool Client::drive(Connection * conn, const ClientConfig & cfg, uint64_t warmupE } if (!isExpectedShutdown(r)) { - SILK_ERROR("write failed: {}", std::strerror(r)); + SILK_ERROR("write failed: %s", std::strerror(r)); } return false; } @@ -1074,7 +1074,7 @@ bool Client::drive(Connection * conn, const ClientConfig & cfg, uint64_t warmupE } if (!isExpectedShutdown(r)) { - SILK_ERROR("read failed: {}", std::strerror(r)); + SILK_ERROR("read failed: %s", std::strerror(r)); } return false; } @@ -1087,7 +1087,7 @@ void Client::workerMain(WorkerParams params) noexcept Epoll epoll; int r = Epoll::create(&epoll); - SILK_ASSERT(!r, "Epoll::create failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "Epoll::create failed: %s", std::strerror(r)); StopTag stopTag; r = epoll.add(worker->stopEvent.getFd(), EPOLLIN, &stopTag); @@ -1113,7 +1113,7 @@ void Client::workerMain(WorkerParams params) noexcept { continue; } - SILK_ASSERT(!r, "epoll_wait failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "epoll_wait failed: %s", std::strerror(r)); uint64_t warmupEndCycles = client->warmupEndCycles.load(std::memory_order_relaxed); @@ -1231,7 +1231,7 @@ static void runServer(int argc, char ** argv) sigset_t mask = blockSignals(); silk::initialize(); - SILK_INFO("starting server on {}:{} with {} thread(s)", cfg.host, cfg.port, cfg.threads); + SILK_INFO("starting server on %s:%u with %u thread(s)", cfg.host.c_str(), cfg.port, cfg.threads); Server server(cfg); server.start(); @@ -1313,7 +1313,8 @@ static void runClient(int argc, char ** argv) sigset_t mask = blockSignals(); silk::initialize(); - SILK_INFO("starting client on {}:{} with {} thread(s) and {} connection(s)", cfg.host, cfg.port, cfg.threads, cfg.numConnections); + SILK_INFO( + "starting client on %s:%u with %u thread(s) and %u connection(s)", cfg.host.c_str(), cfg.port, cfg.threads, cfg.numConnections); Client client(cfg); client.start(); @@ -1322,13 +1323,13 @@ static void runClient(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } diff --git a/src/perf/net-perf.cpp b/src/perf/net-perf.cpp index fb5e39c..619d617 100644 --- a/src/perf/net-perf.cpp +++ b/src/perf/net-perf.cpp @@ -17,7 +17,6 @@ #include #include #include -#include #include #include #include @@ -115,7 +114,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (::inet_pton(AF_INET, host, &addr.sin_addr) != 1) { - SILK_ERROR("inet_pton failed: invalid address {}", host); + SILK_ERROR("inet_pton failed: invalid address %s", host); return EINVAL; } @@ -123,7 +122,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (fd < 0) { int r = errno; - SILK_ERROR("socket failed: {}", std::strerror(r)); + SILK_ERROR("socket failed: %s", std::strerror(r)); return r; } @@ -131,7 +130,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value))) { int r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -142,7 +141,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out r = errno; if (r != EINPROGRESS) { - SILK_ERROR("connect failed: {}", std::strerror(r)); + SILK_ERROR("connect failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -150,7 +149,7 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out r = silk::FiberScheduler::poll(fd, POLLOUT); if (r) { - SILK_ERROR("poll failed: {}", std::strerror(r)); + SILK_ERROR("poll failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -161,13 +160,13 @@ int TcpConnection::connect(const char * host, uint16_t port, TcpConnection * out if (::getsockopt(fd, SOL_SOCKET, SO_ERROR, &r, &len)) { r = errno; - SILK_ERROR("getsockopt SO_ERROR failed: {}", std::strerror(r)); + SILK_ERROR("getsockopt SO_ERROR failed: %s", std::strerror(r)); ::close(fd); return r; } if (r) { - SILK_ERROR("connect error: {}", std::strerror(r)); + SILK_ERROR("connect error: %s", std::strerror(r)); ::close(fd); return r; } @@ -188,7 +187,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn } else if (::inet_pton(AF_INET, host, &addr.sin_addr) != 1) { - SILK_ERROR("inet_pton failed: invalid address {}", host); + SILK_ERROR("inet_pton failed: invalid address %s", host); return EINVAL; } @@ -196,7 +195,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (fd < 0) { int r = errno; - SILK_ERROR("socket failed: {}", std::strerror(r)); + SILK_ERROR("socket failed: %s", std::strerror(r)); return r; } @@ -204,7 +203,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value))) { int r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -212,7 +211,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (::setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &value, sizeof(value))) { int r = errno; - SILK_ERROR("setsockopt SO_REUSEADDR failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt SO_REUSEADDR failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -220,7 +219,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (::bind(fd, reinterpret_cast(&addr), sizeof(addr))) { int r = errno; - SILK_ERROR("bind failed: {}", std::strerror(r)); + SILK_ERROR("bind failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -228,7 +227,7 @@ int TcpConnection::listen(const char * host, uint16_t port, int backlog, TcpConn if (::listen(fd, backlog)) { int r = errno; - SILK_ERROR("listen failed: {}", std::strerror(r)); + SILK_ERROR("listen failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -264,7 +263,7 @@ int TcpConnection::accept(TcpConnection * out) noexcept if (::setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &value, sizeof(value))) { int r = errno; - SILK_ERROR("setsockopt TCP_NODELAY failed: {}", std::strerror(r)); + SILK_ERROR("setsockopt TCP_NODELAY failed: %s", std::strerror(r)); ::close(fd); return r; } @@ -443,7 +442,7 @@ Server::Server(const ServerConfig & cfg) : cfg(cfg) { int r = TcpConnection::listen(cfg.host.c_str(), cfg.port, LISTEN_BACKLOG, &listener); - SILK_ASSERT(!r, "listen failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "listen failed: %s", std::strerror(r)); } Server::~Server() = default; @@ -451,7 +450,7 @@ Server::~Server() = default; void Server::start() { int r = silk::FiberScheduler::run(acceptFiberMain, {this}, &acceptFuture); - SILK_ASSERT(!r, "cannot start fiber: {}", std::strerror(r)); + SILK_ASSERT(!r, "cannot start fiber: %s", std::strerror(r)); acceptStarted = true; } @@ -490,7 +489,7 @@ int Server::acceptFiberMain(AcceptFiberParams * params) noexcept delete connection; if (!isExpectedShutdown(r)) { - SILK_ERROR("accept failed: {}", strerror(r)); + SILK_ERROR("accept failed: %s", strerror(r)); } break; } @@ -500,7 +499,7 @@ int Server::acceptFiberMain(AcceptFiberParams * params) noexcept r = silk::FiberScheduler::run(serverFiberMain, {server, connection}, &connection->future); if (r) { - SILK_ERROR("cannot start fiber: {}", std::strerror(r)); + SILK_ERROR("cannot start fiber: %s", std::strerror(r)); break; } } @@ -523,7 +522,7 @@ int Server::serverFiberMain(ServerFiberParams * params) noexcept { if (!isExpectedShutdown(r)) { - SILK_ERROR("read failed: {}", strerror(r)); + SILK_ERROR("read failed: %s", strerror(r)); } break; } @@ -544,7 +543,7 @@ int Server::serverFiberMain(ServerFiberParams * params) noexcept { if (!isExpectedShutdown(r)) { - SILK_ERROR("write failed: {}", strerror(r)); + SILK_ERROR("write failed: %s", strerror(r)); } break; } @@ -619,13 +618,13 @@ void Client::start() for (Connection & connection : connections) { int r = TcpConnection::connect(cfg.host.c_str(), cfg.port, &connection.conn); - SILK_ASSERT(!r, "connect failed: {}", std::strerror(r)); + SILK_ASSERT(!r, "connect failed: %s", std::strerror(r)); } for (Connection & connection : connections) { int r = silk::FiberScheduler::run(clientFiberMain, {this, &connection}, &connection.future); - SILK_ASSERT(!r, "cannot start fiber: {}", std::strerror(r)); + SILK_ASSERT(!r, "cannot start fiber: %s", std::strerror(r)); } warmupEndCycles.store(silk::Tsc::getCycles() + silk::Tsc::nanosecondsToCycles(cfg.warmupNs), std::memory_order_relaxed); @@ -678,7 +677,7 @@ int Client::clientFiberMain(ClientFiberParams * params) noexcept { if (!isExpectedShutdown(r)) { - SILK_ERROR("write failed: {}", strerror(r)); + SILK_ERROR("write failed: %s", strerror(r)); } break; } @@ -688,7 +687,7 @@ int Client::clientFiberMain(ClientFiberParams * params) noexcept { if (!isExpectedShutdown(r)) { - SILK_ERROR("read failed: {}", strerror(r)); + SILK_ERROR("read failed: %s", strerror(r)); } break; } @@ -783,7 +782,7 @@ static void runServer(int argc, char ** argv) silk::FiberScheduler::Options options{.enableProfiler = cfg.printCounters}; silk::FiberScheduler::initialize(&options); - SILK_INFO("starting server on {}:{}", cfg.host, cfg.port); + SILK_INFO("starting server on %s:%u", cfg.host.c_str(), cfg.port); Server server(cfg); server.start(); @@ -869,7 +868,7 @@ static void runClient(int argc, char ** argv) silk::FiberScheduler::Options options{.enableProfiler = cfg.printCounters}; silk::FiberScheduler::initialize(&options); - SILK_INFO("starting client on {}:{}", cfg.host, cfg.port); + SILK_INFO("starting client on %s:%u", cfg.host.c_str(), cfg.port); Client client(cfg); client.start(); @@ -878,13 +877,13 @@ static void runClient(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } diff --git a/src/perf/s3-perf.cpp b/src/perf/s3-perf.cpp index 83c3152..34822d9 100644 --- a/src/perf/s3-perf.cpp +++ b/src/perf/s3-perf.cpp @@ -323,7 +323,7 @@ const char * PocoHttpClient::getMethod(Aws::Http::HttpMethod method) case Aws::Http::HttpMethod::HTTP_TRACE: return "TRACE"; } - SILK_ASSERT(false); + SILK_FAIL("unknown HTTP method", "value=%d", static_cast(method)); } void PocoHttpClient::writeHeaders(Poco::Net::HTTPRequest & pocoReq, const Aws::Http::HeaderValueCollection & headers) @@ -514,7 +514,7 @@ int FiberExecutor::execFiberMain(ExecParams * params) noexcept // The SDK wraps tasks in std::packaged_task, which captures exceptions // into the promise before rethrowing. The session thread sees the error // via callable.get(). We catch here only to satisfy noexcept. - SILK_ERROR("fiber executor task exception: {}", e.what()); + SILK_ERROR("fiber executor task exception: %s", e.what()); } return 0; } @@ -703,7 +703,7 @@ void S3Bench::runSession(Session * session) // endpoint or a transient failure every session exits after one bad outcome, // and the run produces no useful latency data. failedSessions exposes the // count so the caller can warn. - SILK_ERROR("S3 request failed: {}", slots[head].error->GetMessage()); + SILK_ERROR("S3 request failed: %s", slots[head].error->GetMessage().c_str()); session->failed = true; head = (head + 1) % cfg.ioDepth; break; @@ -829,13 +829,13 @@ int main(int argc, char ** argv) if (cfg.warmupNs > 0) { - SILK_INFO("warming up for {}...", formatDuration(cfg.warmupNs)); + SILK_INFO("warming up for %s...", formatDuration(cfg.warmupNs).c_str()); signalled = sigwaitFor(mask, cfg.warmupNs); } if (!signalled) { - SILK_INFO("measuring for {}...", formatDuration(cfg.durationNs)); + SILK_INFO("measuring for %s...", formatDuration(cfg.durationNs).c_str()); sigwaitFor(mask, cfg.durationNs); } @@ -847,7 +847,7 @@ int main(int argc, char ** argv) uint32_t failedSessions = bench.failedSessions(); if (failedSessions > 0) { - SILK_WARN("{}/{} sessions exited early due to S3 errors", failedSessions, cfg.numJobs); + SILK_WARN("%u/%u sessions exited early due to S3 errors", failedSessions, cfg.numJobs); } auto latencies = bench.collectLatencies(); diff --git a/src/profiler/main.cpp b/src/profiler/main.cpp index a759557..02d9ff8 100644 --- a/src/profiler/main.cpp +++ b/src/profiler/main.cpp @@ -120,8 +120,8 @@ int main(int argc, char ** argv) if (!hasBpf || !hasPerfmon) { - SILK_ERROR("missing required capabilities (CAP_BPF={}, CAP_PERFMON={})", hasBpf, hasPerfmon); - SILK_ERROR("run once: sudo setcap cap_bpf,cap_perfmon,cap_syslog+eip {}", argv[0]); + SILK_ERROR("missing required capabilities (CAP_BPF=%d, CAP_PERFMON=%d)", hasBpf, hasPerfmon); + SILK_ERROR("run once: sudo setcap cap_bpf,cap_perfmon,cap_syslog+eip %s", argv[0]); return 1; } @@ -133,7 +133,7 @@ int main(int argc, char ** argv) int r = symbolizer.readSelfMappings(); if (r) { - SILK_ERROR("readSelfMappings: {}", strerror(r)); + SILK_ERROR("readSelfMappings: %s", strerror(r)); return r; } @@ -141,7 +141,7 @@ int main(int argc, char ** argv) r = symbolizer.readMappings(targetPid); if (r) { - SILK_ERROR("readMappings: {}", strerror(r)); + SILK_ERROR("readMappings: %s", strerror(r)); return r; } @@ -155,7 +155,7 @@ int main(int argc, char ** argv) else { SILK_WARN("CAP_SYSLOG missing -- kernel frames will appear as hex addresses"); - SILK_WARN("run once: sudo setcap cap_bpf,cap_perfmon,cap_syslog+eip {}", argv[0]); + SILK_WARN("run once: sudo setcap cap_bpf,cap_perfmon,cap_syslog+eip %s", argv[0]); } } @@ -164,17 +164,17 @@ int main(int argc, char ** argv) r = profiler.start(); if (r) { - SILK_ERROR("profiler start failed: {}", strerror(r)); + SILK_ERROR("profiler start failed: %s", strerror(r)); return r; } if (durationSec > 0) { - SILK_INFO("profiling pid {} at {} Hz for {} seconds", targetPid, sampleHz, durationSec); + SILK_INFO("profiling pid %u at %u Hz for %u seconds", targetPid, sampleHz, durationSec); } else { - SILK_INFO("profiling pid {} at {} Hz -- Ctrl+C to stop", targetPid, sampleHz); + SILK_INFO("profiling pid %u at %u Hz -- Ctrl+C to stop", targetPid, sampleHz); } uint64_t waitNs = durationSec > 0 ? (uint64_t)durationSec * 1'000'000'000ULL : UINT64_MAX; @@ -189,7 +189,7 @@ int main(int argc, char ** argv) } catch (const std::exception & ex) { - SILK_ERROR("collect: {}", ex.what()); + SILK_ERROR("collect: %s", ex.what()); return 1; } diff --git a/src/profiler/profiler.cpp b/src/profiler/profiler.cpp index a57f45d..380cc17 100644 --- a/src/profiler/profiler.cpp +++ b/src/profiler/profiler.cpp @@ -148,7 +148,7 @@ int Profiler::start() noexcept // CPU offline continue; } - SILK_WARN("perf_event_open cpu {}: {}", cpu, strerror(r)); + SILK_WARN("perf_event_open cpu %d: %s", cpu, strerror(r)); continue; } @@ -156,7 +156,7 @@ int Profiler::start() noexcept if (!link) { int r = errno; - SILK_WARN("attach perf_event cpu {}: {}", cpu, strerror(r)); + SILK_WARN("attach perf_event cpu %d: %s", cpu, strerror(r)); ::close(fd); continue; } diff --git a/src/profiler/symbolizer.cpp b/src/profiler/symbolizer.cpp index b04e86f..099c465 100644 --- a/src/profiler/symbolizer.cpp +++ b/src/profiler/symbolizer.cpp @@ -8,7 +8,6 @@ #include #include #include -#include #include #include @@ -21,7 +20,7 @@ static int parseMapsFile(const char * path, Callback callback) noexcept if (!f) { int r = errno; - SILK_ERROR("open {}: {}", path, ::strerror(r)); + SILK_ERROR("open %s: %s", path, ::strerror(r)); return r; } @@ -82,7 +81,7 @@ int Symbolizer::readKallsyms() noexcept if (!f) { int r = errno; - SILK_ERROR("open /proc/kallsyms: {}", ::strerror(r)); + SILK_ERROR("open /proc/kallsyms: %s", ::strerror(r)); return r; } @@ -138,7 +137,9 @@ const std::string & Symbolizer::resolve(uint64_t addr) } if (result.empty()) { - result = std::format("0x{:x}", addr); + char buf[32]; + std::snprintf(buf, sizeof(buf), "0x%lx", addr); + result = buf; } auto [it2, _] = cache.emplace(addr, std::move(result)); return it2->second; @@ -172,7 +173,7 @@ const std::string & Symbolizer::resolve(uint64_t addr) if (!state) { - SILK_WARN("0x{:x}: no backtrace state for {}", addr, m.path); + SILK_WARN("0x%lx: no backtrace state for %s", addr, m.path.c_str()); break; } @@ -232,18 +233,27 @@ const std::string & Symbolizer::resolve(uint64_t addr) { if (mappingFound) { - SILK_DEBUG("0x{:x}: in mapping but not symbolized (elfAddr=0x{:x} {})", addr, mappingElfAddr, mappingPath); + SILK_DEBUG( + "0x%lx: in mapping but not symbolized (elfAddr=0x%lx %.*s)", + addr, + mappingElfAddr, + static_cast(mappingPath.size()), + mappingPath.data()); std::string_view base = mappingPath; if (auto slash = base.rfind('/'); slash != std::string_view::npos) { base = base.substr(slash + 1); } - result = std::format("{}+0x{:x}", base, mappingElfAddr); + char buf[256]; + std::snprintf(buf, sizeof(buf), "%.*s+0x%lx", static_cast(base.size()), base.data(), mappingElfAddr); + result = buf; } else { - SILK_DEBUG("0x{:x}: no mapping (library loaded after readMappings?)", addr); - result = std::format("0x{:x}", addr); + SILK_DEBUG("0x%lx: no mapping (library loaded after readMappings?)", addr); + char buf[32]; + std::snprintf(buf, sizeof(buf), "0x%lx", addr); + result = buf; } } @@ -257,11 +267,11 @@ void Symbolizer::backtraceErrorCb(void * data, const char * msg, int errnum) if (errnum) { - SILK_ERROR("libbacktrace: {} ({})", msg, ::strerror(errnum)); + SILK_ERROR("libbacktrace: %s (%s)", msg, ::strerror(errnum)); } else { - SILK_ERROR("libbacktrace: {}", msg); + SILK_ERROR("libbacktrace: %s", msg); } } diff --git a/src/util/assert.cpp b/src/util/assert.cpp index e39f2ac..4f3e29c 100644 --- a/src/util/assert.cpp +++ b/src/util/assert.cpp @@ -2,15 +2,12 @@ #include +#include #include #include -#include +#include #if defined(SILK_USE_LIBBACKTRACE) -# include -# include -# include - # include # include #endif // SILK_USE_LIBBACKTRACE @@ -35,14 +32,13 @@ static backtrace_state * btState = backtrace_create_state(nullptr, 1, btCreateEr struct Context { - std::ostringstream * out; int frame = 0; }; static int btCallback(void * data, uintptr_t pc, const char * filename, int lineno, const char * function) noexcept { Context * ctx = static_cast(data); - (*ctx->out) << "#" << ctx->frame++ << " " << std::format("{:#018x}", pc) << " in " << COLOR_YELLOW; + std::fprintf(stderr, "#%d %#018lx in %s", ctx->frame++, static_cast(pc), COLOR_YELLOW); int status = 0; char * demangled = function ? abi::__cxa_demangle(function, nullptr, nullptr, &status) : nullptr; @@ -51,24 +47,24 @@ static int btCallback(void * data, uintptr_t pc, const char * filename, int line const char * paren = std::strchr(demangled, '('); if (paren) { - (*ctx->out) << std::string_view(demangled, paren - demangled); - (*ctx->out) << COLOR_RESET << " " << paren; + std::fwrite(demangled, 1, static_cast(paren - demangled), stderr); + std::fprintf(stderr, "%s %s", COLOR_RESET, paren); } else { - (*ctx->out) << demangled << COLOR_RESET << " ()"; + std::fprintf(stderr, "%s%s ()", demangled, COLOR_RESET); } } else { - (*ctx->out) << (function ? function : "??") << COLOR_RESET << " ()"; + std::fprintf(stderr, "%s%s ()", function ? function : "??", COLOR_RESET); } if (filename) { - (*ctx->out) << " at " << COLOR_GREEN << filename << COLOR_RESET << ":" << lineno; + std::fprintf(stderr, " at %s%s%s:%d", COLOR_GREEN, filename, COLOR_RESET, lineno); } - (*ctx->out) << "\n"; + std::fputc('\n', stderr); std::free(demangled); return 0; @@ -76,28 +72,34 @@ static int btCallback(void * data, uintptr_t pc, const char * filename, int line static void btErrorCallback(void * data, const char * msg, int err) noexcept { - Context * ctx = static_cast(data); - (*ctx->out) << " backtrace error " << err << ": " << msg << "\n"; + SILK_UNUSED(data); + std::fprintf(stderr, " backtrace error %d: %s\n", err, msg); } #endif // SILK_USE_LIBBACKTRACE -void assertFail(const char * message, const char * file, int line, const char * details) noexcept +void assertFail(const char * message, const char * file, int line, const char * fmt, ...) noexcept { - std::ostringstream out; - out << COLOR_RED << file << ":" << line << " " << message; - if (details) + ::flockfile(stderr); + + std::fprintf(stderr, "%s%s:%d %s", COLOR_RED, file, line, message); + if (fmt) { - out << " -- " << details; + std::fputs(" -- ", stderr); + va_list ap; + va_start(ap, fmt); + std::vfprintf(stderr, fmt, ap); + va_end(ap); } - out << COLOR_RESET << "\n"; + std::fprintf(stderr, "%s\n", COLOR_RESET); #if defined(SILK_USE_LIBBACKTRACE) - Context ctx{&out, 0}; + Context ctx; backtrace_full(btState, 0, btCallback, btErrorCallback, &ctx); #endif - std::fputs(out.str().c_str(), stderr); + ::funlockfile(stderr); + std::fflush(stderr); std::abort(); } diff --git a/src/util/logger.cpp b/src/util/logger.cpp index 53083ee..b34fe2c 100644 --- a/src/util/logger.cpp +++ b/src/util/logger.cpp @@ -1,20 +1,16 @@ #include +#include #include +#include #include -#include namespace silk { -static constexpr std::string_view LEVEL_NAMES[] = {"DEBUG", "INFO ", "WARN ", "ERROR"}; +static constexpr const char * LEVEL_NAMES[] = {"DEBUG", "INFO ", "WARN ", "ERROR"}; -void Logger::setLevel(LogLevel level) noexcept -{ - currentLevel.store(level, std::memory_order_relaxed); -} - -void Logger::log(LogLevel level, std::string_view file, int line, std::string_view message) noexcept +void Logger::log(LogLevel level, const char * file, int line, const char * message) noexcept { timespec ts; ::clock_gettime(CLOCK_REALTIME, &ts); @@ -24,7 +20,7 @@ void Logger::log(LogLevel level, std::string_view file, int line, std::string_vi std::fprintf( stderr, - "%04d-%02d-%02d %02d:%02d:%02d.%03ld [%s] %.*s:%d: %.*s\n", + "%04d-%02d-%02d %02d:%02d:%02d.%03ld [%s] %s:%d: %s\n", t.tm_year + 1900, t.tm_mon + 1, t.tm_mday, @@ -32,12 +28,46 @@ void Logger::log(LogLevel level, std::string_view file, int line, std::string_vi t.tm_min, t.tm_sec, ts.tv_nsec / 1'000'000, - LEVEL_NAMES[static_cast(level)].data(), - static_cast(file.size()), - file.data(), + LEVEL_NAMES[static_cast(level)], + file, line, - static_cast(message.size()), - message.data()); + message); +} + +void Logger::logf(LogLevel level, const char * file, int line, const char * fmt, ...) noexcept +{ + // Format into a small stack buffer, falling back to malloc on overflow, + // then forward to the pre-formatted log for the actual emission. + + char stackBody[256]; + char * body = stackBody; + char * heapBody = nullptr; + + va_list ap; + va_start(ap, fmt); + va_list ap2; + va_copy(ap2, ap); + int n = std::vsnprintf(stackBody, sizeof(stackBody), fmt, ap); + va_end(ap); + if (n < 0) + { + n = 0; + } + + if (n >= static_cast(sizeof(stackBody))) + { + heapBody = static_cast(std::malloc(static_cast(n) + 1)); + if (heapBody) + { + std::vsnprintf(heapBody, static_cast(n) + 1, fmt, ap2); + body = heapBody; + } + } + va_end(ap2); + + log(level, file, line, body); + + std::free(heapBody); } } // namespace silk diff --git a/src/util/tsc.cpp b/src/util/tsc.cpp index 7c06dfb..6304ad8 100644 --- a/src/util/tsc.cpp +++ b/src/util/tsc.cpp @@ -3,7 +3,6 @@ #include #include -#include #if defined(__x86_64__) # include