Skip to content
Commits on Source (7)
......@@ -34,6 +34,9 @@ build/*
# Codelite
.codelite
# KDevelop
*.kdev4
# .orig files
*.orig
......@@ -46,6 +49,7 @@ example/*
!example/example.sln
!example/example.vcxproj
!example/CMakeLists.txt
!example/meson.build
!example/multisink.cpp
!example/jni
......@@ -66,3 +70,14 @@ install_manifest.txt
# idea
.idea/
cmake-build-*/
*.db
*.ipch
*.filters
*.db-wal
*.opendb
*.db-shm
*.vcxproj
*.tcl
*.user
*.sln
......@@ -5,6 +5,7 @@
sudo: required
language: cpp
# gcc 4.8
addons: &gcc48
apt:
packages:
......@@ -12,6 +13,7 @@ addons: &gcc48
sources:
- ubuntu-toolchain-r-test
# gcc 7.0
addons: &gcc7
apt:
packages:
......@@ -19,6 +21,7 @@ addons: &gcc7
sources:
- ubuntu-toolchain-r-test
# Clang 3.5
addons: &clang35
apt:
packages:
......@@ -27,13 +30,15 @@ addons: &clang35
- ubuntu-toolchain-r-test
- llvm-toolchain-precise-3.5
addons: &clang6
# Clang 7.0
addons: &clang70
apt:
packages:
- clang-6.0
- clang-7
sources:
- ubuntu-toolchain-r-test
- llvm-toolchain-trusty-6.0
- llvm-toolchain-trusty-7
matrix:
......@@ -60,23 +65,12 @@ matrix:
os: linux
addons: *clang35
# Test clang-6.0: C++11, Build=Debug, ASAN=On
- env: CLANG_VERSION=6.0 BUILD_TYPE=Debug CPP=11 ASAN=On TSAN=Off
os: linux
addons: *clang6
# Test clang-7.0: C++11, Build=Debug, ASAN=On
- env: CLANG_VERSION=7 BUILD_TYPE=Debug CPP=11 ASAN=On TSAN=Off
dist: bionic
- env: CLANG_VERSION=6.0 BUILD_TYPE=Release CPP=11 ASAN=On TSAN=Off
os: linux
addons: *clang6
# Test clang-6.0: C++11, Build=Debug, TSAN=On
- env: CLANG_VERSION=6.0 BUILD_TYPE=Debug CPP=11 ASAN=Off TSAN=On
os: linux
addons: *clang6
- env: CLANG_VERSION=6.0 BUILD_TYPE=Release CPP=11 ASAN=Off TSAN=On
os: linux
addons: *clang6
- env: CLANG_VERSION=7 BUILD_TYPE=Release CPP=11 ASAN=On TSAN=Off
dist: bionic
# osx
- env: BUILD_TYPE=Release CPP=11 ASAN=Off TSAN=Off
......@@ -84,7 +78,6 @@ matrix:
before_script:
- if [ -n "$GCC_VERSION" ]; then export CXX="g++-${GCC_VERSION}" CC="gcc-${GCC_VERSION}"; fi
- if [ -n "$CLANG_VERSION" ]; then export CXX="clang++-${CLANG_VERSION}" CC="clang-${CLANG_VERSION}"; fi
......@@ -102,11 +95,13 @@ script:
--warn-uninitialized \
-DCMAKE_BUILD_TYPE=$BUILD_TYPE \
-DCMAKE_CXX_STANDARD=$CPP \
-DSPDLOG_BUILD_EXAMPLES=ON \
-DSPDLOG_BUILD_EXAMPLE=ON \
-DSPDLOG_BUILD_EXAMPLE_HO=ON \
-DSPDLOG_BUILD_BENCH=OFF \
-DSPDLOG_BUILD_TESTS=ON \
-DSPDLOG_SANITIZE_ADDRESS=$ASAN \
-DSPDLOG_SANITIZE_THREAD=$TSAN
-DSPDLOG_BUILD_TESTS_HO=OFf \
-DSPDLOG_SANITIZE_ADDRESS=$ASAN
- make VERBOSE=1 -j2
- ctest -j2 --output-on-failure
......
#
# Copyright(c) 2015 Ruslan Baratov.
# Copyright(c) 2019 spdlog authors
# Distributed under the MIT License (http://opensource.org/licenses/MIT)
#
cmake_minimum_required(VERSION 3.1)
project(spdlog VERSION 1.3.1 LANGUAGES CXX)
include(CMakeDependentOption)
cmake_minimum_required(VERSION 3.2)
#---------------------------------------------------------------------------------------
# Start spdlog project
#---------------------------------------------------------------------------------------
include(GNUInstallDirs)
include(cmake/utils.cmake)
include(cmake/ide.cmake)
spdlog_extract_version()
#---------------------------------------------------------------------------------------
# set default build to release
# Set default build to release
#---------------------------------------------------------------------------------------
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose Release or Debug" FORCE)
endif()
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
project(spdlog VERSION ${SPDLOG_VERSION} LANGUAGES CXX)
message(STATUS "Build spdlog: ${SPDLOG_VERSION}")
#---------------------------------------------------------------------------------------
# compiler config
# Compiler config
#---------------------------------------------------------------------------------------
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang")
add_compile_options("-Wall")
add_compile_options("-Wextra")
add_compile_options("-Wconversion")
add_compile_options("-pedantic")
add_compile_options("-Wfatal-errors")
#---------------------------------------------------------------------------------------
# Set SPDLOG_MASTER_PROJECT to ON if we are building spdlog
#---------------------------------------------------------------------------------------
# Check if spdlog is being used directly or via add_subdirectory, but allow overriding
if (NOT DEFINED SPDLOG_MASTER_PROJECT)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(SPDLOG_MASTER_PROJECT ON)
else()
set(SPDLOG_MASTER_PROJECT OFF)
endif()
endif ()
# build shared option
if(NOT WIN32)
option(SPDLOG_BUILD_SHARED "Build shared library" OFF)
endif()
# example options
option(SPDLOG_BUILD_EXAMPLE "Build example" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_EXAMPLE_HO "Build header only example" OFF)
# testing options
option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_TESTS_HO "Build tests using the header only version" OFF)
# bench options
option(SPDLOG_BUILD_BENCH "Build benchmarks (Requires https://github.com/google/benchmark.git to be installed)" OFF)
# sanitizer options
option(SPDLOG_SANITIZE_ADDRESS "Enable address sanitizer in tests" OFF)
# install options
option(SPDLOG_INSTALL "Generate the install target" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
if(WIN32)
option(SPDLOG_WCHAR_SUPPORT "Support wchar api" OFF)
endif()
option(SPDLOG_NO_EXCEPTIONS "Compile with -fno-exceptions. Call abort() on any spdlog exceptions" OFF)
find_package(Threads REQUIRED)
message(STATUS "Build type: " ${CMAKE_BUILD_TYPE})
#---------------------------------------------------------------------------------------
# address sanitizers check
# Static/Shared library (shared not supported in windows yet)
#---------------------------------------------------------------------------------------
include(cmake/sanitizers.cmake)
set(SPDLOG_SRCS
src/spdlog.cpp
src/stdout_sinks.cpp
src/fmt.cpp
src/color_sinks.cpp
src/file_sinks.cpp
src/async.cpp)
set(SPDLOG_CFLAGS "${PROJECT_NAME}")
if (SPDLOG_BUILD_SHARED)
if(WIN32)
message(FATAL_ERROR "spdlog shared lib is not yet supported under windows")
endif()
add_library(spdlog SHARED ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
else()
add_library(spdlog STATIC ${SPDLOG_SRCS} ${SPDLOG_ALL_HEADERS})
endif()
add_library(spdlog::spdlog ALIAS spdlog)
target_compile_definitions(spdlog PUBLIC SPDLOG_COMPILED_LIB)
target_include_directories(spdlog PUBLIC
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
target_link_libraries(spdlog PUBLIC Threads::Threads)
spdlog_enable_warnings(spdlog)
set_target_properties(spdlog PROPERTIES VERSION ${SPDLOG_VERSION} SOVERSION ${SPDLOG_VERSION_MAJOR})
set_target_properties(spdlog PROPERTIES DEBUG_POSTFIX d)
#---------------------------------------------------------------------------------------
# spdlog target
# Header only version
#---------------------------------------------------------------------------------------
add_library(spdlog INTERFACE)
add_library(spdlog::spdlog ALIAS spdlog)
add_library(spdlog_header_only INTERFACE)
add_library(spdlog::spdlog_header_only ALIAS spdlog_header_only)
# Check if spdlog is being used directly or via add_subdirectory
set(SPDLOG_MASTER_PROJECT OFF)
if (CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR)
set(SPDLOG_MASTER_PROJECT ON)
endif()
target_include_directories(spdlog_header_only INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>")
target_link_libraries(spdlog_header_only INTERFACE Threads::Threads)
option(SPDLOG_BUILD_EXAMPLES "Build examples" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_BENCH "Build benchmarks" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_BUILD_TESTS "Build tests" ${SPDLOG_MASTER_PROJECT})
option(SPDLOG_FMT_EXTERNAL "Use external fmt library instead of bundled" OFF)
#---------------------------------------------------------------------------------------
# Use fmt package if using exertnal fmt
#---------------------------------------------------------------------------------------
if(SPDLOG_FMT_EXTERNAL)
find_package(fmt REQUIRED CONFIG)
if (NOT TARGET fmt::fmt)
find_package(fmt REQUIRED)
endif ()
target_include_directories(
spdlog
INTERFACE
"$<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>"
"$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>"
)
set(SPDLOG_CFLAGS "${SPDLOG_CFLAGS} -DSPDLOG_FMT_EXTERNAL")
if(SPDLOG_FMT_EXTERNAL)
target_compile_definitions(spdlog INTERFACE SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog INTERFACE fmt::fmt)
target_compile_definitions(spdlog PUBLIC SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog PUBLIC fmt::fmt)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_FMT_EXTERNAL)
target_link_libraries(spdlog_header_only INTERFACE fmt::fmt)
endif()
if(SPDLOG_WCHAR_SUPPORT)
target_compile_definitions(spdlog PUBLIC SPDLOG_WCHAR_TO_UTF8_SUPPORT)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_WCHAR_TO_UTF8_SUPPORT)
endif()
if(SPDLOG_NO_EXCEPTIONS)
target_compile_definitions(spdlog PUBLIC SPDLOG_NO_EXCEPTIONS)
target_compile_definitions(spdlog_header_only INTERFACE SPDLOG_NO_EXCEPTIONS)
if(NOT MSVC)
target_compile_options(spdlog PRIVATE -fno-exceptions)
endif()
endif()
set(HEADER_BASE "${CMAKE_CURRENT_SOURCE_DIR}/include")
if(SPDLOG_BUILD_EXAMPLES)
#---------------------------------------------------------------------------------------
# Build binaries
#---------------------------------------------------------------------------------------
if(SPDLOG_BUILD_EXAMPLE OR SPDLOG_BUILD_EXAMPLE_HO)
message(STATUS "Generating examples")
add_subdirectory(example)
endif()
if(SPDLOG_BUILD_TESTS)
include(CTest)
if(SPDLOG_BUILD_TESTS OR SPDLOG_BUILD_TESTS_HO)
message(STATUS "Generating tests")
enable_testing()
add_subdirectory(tests)
endif()
if(SPDLOG_BUILD_BENCH)
message(STATUS "Generating benchmarks")
add_subdirectory(bench)
endif()
#---------------------------------------------------------------------------------------
# Install/export targets and files
# Install
#---------------------------------------------------------------------------------------
# set files and directories
set(config_install_dir "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}")
set(include_install_dir "${CMAKE_INSTALL_INCLUDEDIR}")
if (SPDLOG_INSTALL)
message(STATUS "Generating install")
set(project_config_in "${CMAKE_CURRENT_LIST_DIR}/cmake/spdlogConfig.cmake.in")
set(project_config_out "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfig.cmake")
set(config_targets_file "spdlogConfigTargets.cmake")
set(version_config_file "${CMAKE_CURRENT_BINARY_DIR}/spdlogConfigVersion.cmake")
set(export_dest_dir "${CMAKE_INSTALL_LIBDIR}/spdlog/cmake")
set(pkgconfig_install_dir "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
set(version_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
set(project_config "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_NAME}Config.cmake")
set(targets_config "${PROJECT_NAME}Targets.cmake")
set(pkg_config "${CMAKE_BINARY_DIR}/${PROJECT_NAME}.pc")
set(targets_export_name "${PROJECT_NAME}Targets")
set(namespace "${PROJECT_NAME}::")
# generate package version file
#---------------------------------------------------------------------------------------
# Include files
#---------------------------------------------------------------------------------------
install(DIRECTORY include/ DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}" PATTERN "fmt/bundled" EXCLUDE)
install(TARGETS spdlog spdlog_header_only EXPORT spdlog DESTINATION "${CMAKE_INSTALL_LIBDIR}/spdlog")
if(NOT SPDLOG_FMT_EXTERNAL)
install(DIRECTORY include/${PROJECT_NAME}/fmt/bundled/
DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/fmt/bundled/")
endif()
#---------------------------------------------------------------------------------------
# Package and version files
#---------------------------------------------------------------------------------------
configure_file("cmake/${PROJECT_NAME}.pc.in" "${pkg_config}" @ONLY)
install(FILES "${pkg_config}" DESTINATION "${pkgconfig_install_dir}")
install(EXPORT spdlog
DESTINATION ${export_dest_dir}
NAMESPACE spdlog::
FILE ${config_targets_file})
include(CMakePackageConfigHelpers)
write_basic_package_version_file(
"${version_config}" COMPATIBILITY SameMajorVersion
)
# configure pkg config file
configure_file("cmake/spdlog.pc.in" "${pkg_config}" @ONLY)
# configure spdlogConfig.cmake file
configure_file("cmake/Config.cmake.in" "${project_config}" @ONLY)
# install targets
install(
TARGETS spdlog
EXPORT "${targets_export_name}"
)
# install headers
install(
DIRECTORY "${HEADER_BASE}/${PROJECT_NAME}"
DESTINATION "${include_install_dir}"
)
# install project config and version file
install(
FILES "${project_config}" "${version_config}"
DESTINATION "${config_install_dir}"
)
# install pkg config file
install(
FILES "${pkg_config}"
DESTINATION "${pkgconfig_install_dir}"
)
# install targets config file
install(
EXPORT "${targets_export_name}"
NAMESPACE "${namespace}"
DESTINATION "${config_install_dir}"
FILE ${targets_config}
)
# export build directory targets file
export(
EXPORT ${targets_export_name}
NAMESPACE "${namespace}"
FILE ${targets_config}
)
# register project in CMake user registry
export(PACKAGE ${PROJECT_NAME})
file(GLOB_RECURSE spdlog_include_SRCS "${HEADER_BASE}/*.h")
add_custom_target(spdlog_headers_for_ide SOURCES ${spdlog_include_SRCS})
configure_file("${project_config_in}" "${project_config_out}" @ONLY)
write_basic_package_version_file("${version_config_file}" COMPATIBILITY SameMajorVersion)
install(FILES
"${project_config_out}"
"${version_config_file}" DESTINATION "${export_dest_dir}")
#---------------------------------------------------------------------------------------
# Support creation of installable packages
#---------------------------------------------------------------------------------------
include(cmake/spdlogCPack.cmake)
endif ()
spdlog is header only library.
Just copy the files to your build tree and use a C++11 compiler
Header only version:
==================================================================
Just copy the files to your build tree and use a C++11 compiler.
Or use CMake:
add_executable(example_header_only example.cpp)
target_link_libraries(example_header_only spdlog::spdlog_header_only)
Compiled library version:
==================================================================
CMake:
add_executable(example example.cpp)
target_link_libraries(example spdlog::spdlog)
Or copy src/spdlog.cpp to your build tree and pass the -DSPDLOG_COMPILED_LIB to the compiler.
Tested on:
gcc 4.8.1 and above
clang 3.5
Visual Studio 2013
gcc 4.8 flags: --std==c++11 -pthread -O3 -flto -Wl,--no-as-needed
gcc 4.9 flags: --std=c++11 -pthread -O3 -flto
see the makefile in the example folder
# spdlog
Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.org/gabime/spdlog.svg?branch=master)](https://travis-ci.org/gabime/spdlog)&nbsp; [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true)](https://ci.appveyor.com/project/gabime/spdlog)
Very fast, header-only/compiled, C++ logging library. [![Build Status](https://travis-ci.org/gabime/spdlog.svg?branch=master)](https://travis-ci.org/gabime/spdlog)&nbsp; [![Build status](https://ci.appveyor.com/api/projects/status/d2jnxclg20vd0o50?svg=true)](https://ci.appveyor.com/project/gabime/spdlog)
## Install
#### Just copy the headers:
#### Header only version
Copy the source [folder](https://github.com/gabime/spdlog/tree/v1.x/include/spdlog) to your build tree and use a C++11 compiler.
#### Static lib version (recommended - much faster compile times, v1.4.0)
```console
$ git clone https://github.com/gabime/spdlog.git
$ cd spdlog && mkdir build && cd build
$ cmake .. && make -j
```
* Copy the source [folder](https://github.com/gabime/spdlog/tree/v1.x/include/spdlog) to your build tree and use a C++11 compiler.
see example [CMakeLists.txt](https://github.com/gabime/spdlog/blob/v1.x/example/CMakeLists.txt) on how to use.
#### Or use your favorite package manager:
## Platforms
* Linux, FreeBSD, OpenBSD, Solaris, AIX
* Windows (msvc 2013+, cygwin)
* macOS (clang 3.5+)
* Android
* Ubuntu: `apt-get install libspdlog-dev`
## Package managers:
* Homebrew: `brew install spdlog`
* FreeBSD: `cd /usr/ports/devel/spdlog/ && make install clean`
* Fedora: `yum install spdlog`
......@@ -19,17 +31,11 @@ Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.
* Arch Linux: `yaourt -S spdlog-git`
* vcpkg: `vcpkg install spdlog`
## Platforms
* Linux, FreeBSD, OpenBSD, Solaris, AIX
* Windows (msvc 2013+, cygwin)
* macOS (clang 3.5+)
* Android
## Features
* Very fast (see [benchmarks](#benchmarks) below).
* Headers only, just copy and use.
* Headers only, just copy and use. Or use as a compiled library.
* Feature rich formatting, using the excellent [fmt](https://github.com/fmtlib/fmt) library.
* **New!** [Backtrace](#backtrace-support) support - store debug or other messages in a ring buffer and display later on demand.
* Fast asynchronous mode (optional)
* [Custom](https://github.com/gabime/spdlog/wiki/3.-Custom-formatting) formatting.
* Multi/Single threaded loggers.
......@@ -41,45 +47,15 @@ Very fast, header only, C++ logging library. [![Build Status](https://travis-ci.
* Windows debugger (```OutputDebugString(..)```)
* Easily extendable with custom log targets (just implement a single function in the [sink](include/spdlog/sinks/sink.h) interface).
* Severity based filtering - threshold levels can be modified in runtime as well as in compile time.
* Binary data logging.
## Benchmarks
Below are some [benchmarks](https://github.com/gabime/spdlog/blob/v1.x/bench/bench.cpp) done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
#### Synchronous mode
```
*******************************************************************************
Single thread, 1,000,000 iterations
*******************************************************************************
basic_st... Elapsed: 0.181652 5,505,042/sec
rotating_st... Elapsed: 0.181781 5,501,117/sec
daily_st... Elapsed: 0.187595 5,330,630/sec
null_st... Elapsed: 0.0504704 19,813,602/sec
*******************************************************************************
10 threads sharing same logger, 1,000,000 iterations
*******************************************************************************
basic_mt... Elapsed: 0.616035 1,623,284/sec
rotating_mt... Elapsed: 0.620344 1,612,008/sec
daily_mt... Elapsed: 0.648353 1,542,369/sec
null_mt... Elapsed: 0.151972 6,580,166/sec
```
#### Asynchronous mode
```
*******************************************************************************
10 threads sharing same logger, 1,000,000 iterations
*******************************************************************************
async... Elapsed: 0.350066 2,856,606/sec
async... Elapsed: 0.314865 3,175,960/sec
async... Elapsed: 0.349851 2,858,358/sec
```
## Usage samples
#### Basic usage
```c++
#include "spdlog/spdlog.h"
#include "spdlog/sinks/basic_file_sink.h"
int main()
{
spdlog::info("Welcome to spdlog!");
......@@ -102,6 +78,9 @@ int main()
SPDLOG_TRACE("Some trace message with param {}", {});
SPDLOG_DEBUG("Some debug message");
// Set the default logger to file logger
auto file_logger = spdlog::basic_logger_mt("basic_logger", "logs/basic.txt");
spdlog::set_default_logger(file_logger);
}
```
#### create stdout/stderr logger object
......@@ -157,15 +136,20 @@ void daily_example()
```
---
#### Cloning loggers
#### Backtrace support
```c++
// clone a logger and give it new name.
// Useful for creating subsystem loggers from some "root" logger
void clone_example()
// Loggers can store in a ring buffer all messages (including debug/trace) and display later on demand.
// When needed, call dump_backtrace() to see them
spdlog::enable_backtrace(32); // create ring buffer with capacity of 32 messages
// or my_logger->enable_backtrace(32)..
for(int i = 0; i < 100; i++)
{
auto network_logger = spdlog::get("root")->clone("network");
network_logger->info("Logging network stuff..");
spdlog::debug("Backtrace message {}", i); // not logged yet..
}
// e.g. if some error happened:
spdlog::dump_backtrace(); // log them now! show the last 32 messages
// or my_logger->dump_backtrace(32)..
```
---
......@@ -178,9 +162,8 @@ spdlog::flush_every(std::chrono::seconds(3));
```
---
#### Binary logging
#### Log binary data in hex
```c++
// log binary data as hex.
// many types of std::container<char> types can be used.
// ranges are supported too.
// format flags:
......@@ -310,10 +293,64 @@ void syslog_example()
void android_example()
{
std::string tag = "spdlog-android";
auto android_logger = spdlog::android_logger("android", tag);
auto android_logger = spdlog::android_logger_mt("android", tag);
android_logger->critical("Use \"adb shell logcat\" to view this message.");
}
```
## Benchmarks
Below are some [benchmarks](https://github.com/gabime/spdlog/blob/v1.x/bench/bench.cpp) done in Ubuntu 64 bit, Intel i7-4770 CPU @ 3.40GHz
#### Synchronous mode
```
[info] **************************************************************
[info] Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.17 secs 5,777,626/sec
[info] rotating_st Elapsed: 0.18 secs 5,475,894/sec
[info] daily_st Elapsed: 0.20 secs 5,062,659/sec
[info] empty_logger Elapsed: 0.07 secs 14,127,300/sec
[info] **************************************************************
[info] C-string (400 bytes). Single thread, 1,000,000 iterations
[info] **************************************************************
[info] basic_st Elapsed: 0.41 secs 2,412,483/sec
[info] rotating_st Elapsed: 0.72 secs 1,389,196/sec
[info] daily_st Elapsed: 0.42 secs 2,393,298/sec
[info] null_st Elapsed: 0.04 secs 27,446,957/sec
[info] **************************************************************
[info] 10 threads sharing same logger, 1,000,000 iterations
[info] **************************************************************
[info] basic_mt Elapsed: 0.60 secs 1,659,613/sec
[info] rotating_mt Elapsed: 0.62 secs 1,612,493/sec
[info] daily_mt Elapsed: 0.61 secs 1,638,305/sec
[info] null_mt Elapsed: 0.16 secs 6,272,758/sec
```
#### ASynchronous mode
```
[info] -------------------------------------------------
[info] Messages : 1,000,000
[info] Threads : 10
[info] Queue : 8,192 slots
[info] Queue memory : 8,192 x 272 = 2,176 KB
[info] Total iters : 3
[info] -------------------------------------------------
[info]
[info] *********************************
[info] Queue Overflow Policy: block
[info] *********************************
[info] Elapsed: 1.70784 secs 585,535/sec
[info] Elapsed: 1.69805 secs 588,910/sec
[info] Elapsed: 1.7026 secs 587,337/sec
[info]
[info] *********************************
[info] Queue Overflow Policy: overrun
[info] *********************************
[info] Elapsed: 0.372816 secs 2,682,285/sec
[info] Elapsed: 0.379758 secs 2,633,255/sec
[info] Elapsed: 0.373532 secs 2,677,147/sec
```
## Documentation
Documentation can be found in the [wiki](https://github.com/gabime/spdlog/wiki/1.-QuickStart) pages.
......@@ -26,7 +26,7 @@ build_script:
set PATH=C:\mingw-w64\i686-5.3.0-posix-dwarf-rt_v4-rev0\mingw32\bin;%PATH%
cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_BUILD_BENCH=OFF
cmake .. -G %GENERATOR% -DCMAKE_BUILD_TYPE=%BUILD_TYPE% -DSPDLOG_WCHAR_SUPPORT=ON -DSPDLOG_BUILD_EXAMPLE=ON -DSPDLOG_BUILD_EXAMPLE_HO=ON -DSPDLOG_BUILD_TESTS=ON -DSPDLOG_BUILD_TESTS_HO=OFF
cmake --build . --config %BUILD_TYPE%
......
# *************************************************************************/
# * Copyright (c) 2015 Ruslan Baratov. */
# * */
# * Permission is hereby granted, free of charge, to any person obtaining */
# * a copy of this software and associated documentation files (the */
# * "Software"), to deal in the Software without restriction, including */
# * without limitation the rights to use, copy, modify, merge, publish, */
# * distribute, sublicense, and/or sell copies of the Software, and to */
# * permit persons to whom the Software is furnished to do so, subject to */
# * the following conditions: */
# * */
# * The above copyright notice and this permission notice shall be */
# * included in all copies or substantial portions of the Software. */
# * */
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# *************************************************************************/
# Copyright(c) 2019 spdlog authors
# Distributed under the MIT License (http://opensource.org/licenses/MIT)
cmake_minimum_required(VERSION 3.1)
project(SpdlogBench CXX)
project(spdlog_bench CXX)
if(NOT TARGET spdlog)
# Stand-alone build
......@@ -33,16 +13,16 @@ find_package(Threads REQUIRED)
find_package(benchmark CONFIG REQUIRED)
add_executable(bench bench.cpp)
target_link_libraries(bench PRIVATE spdlog::spdlog Threads::Threads)
spdlog_enable_warnings(bench)
target_link_libraries(bench PRIVATE spdlog::spdlog)
add_executable(async_bench async_bench.cpp)
target_link_libraries(async_bench PRIVATE spdlog::spdlog Threads::Threads)
target_link_libraries(async_bench PRIVATE spdlog::spdlog)
add_executable(latency latency.cpp)
target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog Threads::Threads)
target_link_libraries(latency PRIVATE benchmark::benchmark spdlog::spdlog)
add_executable(formatter-bench formatter-bench.cpp)
target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog Threads::Threads)
target_link_libraries(formatter-bench PRIVATE benchmark::benchmark spdlog::spdlog)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/logs")
CXX ?= g++
CXXFLAGS = -march=native -Wall -Wextra -pedantic -Wconversion -std=c++11 -pthread -I../include -fmax-errors=1
CXX_RELEASE_FLAGS = -O3 -flto -Wl,--no-as-needed
binaries=bench async_bench latency formatter-bench
all: $(binaries)
bench: bench.cpp
$(CXX) bench.cpp -o bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
async_bench: async_bench.cpp
$(CXX) async_bench.cpp -o async_bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS)
latency: latency.cpp
$(CXX) latency.cpp -o latency $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark
formatter-bench: formatter-bench.cpp
$(CXX) formatter-bench.cpp -o formatter-bench $(CXXFLAGS) $(CXX_RELEASE_FLAGS) -lbenchmark
.PHONY: clean
clean:
rm -f *.o logs/* latecy_logs $(binaries)
rebuild: clean all
......@@ -26,6 +26,11 @@ using namespace utils;
void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count);
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4996) // disable fopen warning under msvc
#endif // _MSC_VER
int count_lines(const char *filename)
{
int counter = 0;
......@@ -40,19 +45,36 @@ int count_lines(const char *filename)
return counter;
}
void verify_file(const char *filename, int expected_count)
{
spdlog::info("Verifying {} to contain {:n} line..", filename, expected_count);
auto count = count_lines(filename);
if (count != expected_count)
{
spdlog::error("Test failed. {} has {:n} lines instead of {:n}", filename, count, expected_count);
exit(1);
}
spdlog::info("Line count OK ({:n})\n", count);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
int main(int argc, char *argv[])
{
int howmany = 1000000;
int queue_size = howmany + 2;
int queue_size = std::min(howmany + 2, 8192);
int threads = 10;
int iters = 3;
try
{
spdlog::set_pattern("[%^%l%$] %v");
if (argc == 1)
{
spdlog::set_pattern("%v");
spdlog::info("Usage: {} <message_count> <threads> <q_size> <iterations>", argv[0]);
return 0;
}
......@@ -62,37 +84,54 @@ int main(int argc, char *argv[])
if (argc > 2)
threads = atoi(argv[2]);
if (argc > 3)
{
queue_size = atoi(argv[3]);
if (queue_size > 500000)
{
spdlog::error("Max queue size allowed: 500,000");
exit(1);
}
}
if (argc > 4)
iters = atoi(argv[4]);
auto slot_size = sizeof(spdlog::details::async_msg);
spdlog::info("-------------------------------------------------");
spdlog::info("Messages: {:14n}", howmany);
spdlog::info("Threads : {:14n}", threads);
spdlog::info("Queue : {:14n}", queue_size);
spdlog::info("Iters : {:>14n}", iters);
spdlog::info("Messages : {:n}", howmany);
spdlog::info("Threads : {:n}", threads);
spdlog::info("Queue : {:n} slots", queue_size);
spdlog::info("Queue memory : {:n} x {} = {:n} KB ", queue_size, slot_size, (queue_size * slot_size) / 1024);
spdlog::info("Total iters : {:n}", iters);
spdlog::info("-------------------------------------------------");
const char *filename = "logs/basic_async.log";
spdlog::info("");
spdlog::info("*********************************");
spdlog::info("Queue Overflow Policy: block");
spdlog::info("*********************************");
for (int i = 0; i < iters; i++)
{
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto logger = std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::block);
bench_mt(howmany, std::move(logger), threads);
auto count = count_lines(filename);
if (count != howmany)
{
spdlog::error("Test failed. {} has {:n} lines instead of {:n}", filename, count, howmany);
exit(1);
// verify_file(filename, howmany);
}
else
spdlog::info("");
spdlog::info("*********************************");
spdlog::info("Queue Overflow Policy: overrun");
spdlog::info("*********************************");
// do same test but discard oldest if queue is full instead of blocking
filename = "logs/basic_async-overrun.log";
for (int i = 0; i < iters; i++)
{
spdlog::info("Line count OK ({:n})\n", count);
}
auto tp = std::make_shared<details::thread_pool>(queue_size, 1);
auto file_sink = std::make_shared<spdlog::sinks::basic_file_sink_mt>(filename, true);
auto logger =
std::make_shared<async_logger>("async_logger", std::move(file_sink), std::move(tp), async_overflow_policy::overrun_oldest);
bench_mt(howmany, std::move(logger), threads);
}
spdlog::shutdown();
}
......@@ -102,7 +141,6 @@ int main(int argc, char *argv[])
perror("Last error");
return 1;
}
return 0;
}
......
......@@ -7,7 +7,6 @@
// bench.cpp : spdlog benchmarks
//
#include "spdlog/spdlog.h"
#include "spdlog/async.h"
#include "spdlog/sinks/basic_file_sink.h"
#include "spdlog/sinks/daily_file_sink.h"
#include "spdlog/sinks/null_sink.h"
......@@ -31,81 +30,99 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count
void bench_default_api(int howmany, std::shared_ptr<spdlog::logger> log);
void bench_c_string(int howmany, std::shared_ptr<spdlog::logger> log);
int main(int argc, char *argv[])
{
spdlog::default_logger()->set_pattern("[%^%l%$] %v");
int howmany = 1000000;
int queue_size = howmany + 2;
int threads = 10;
size_t file_size = 30 * 1024 * 1024;
size_t rotating_files = 5;
static size_t file_size = 30 * 1024 * 1024;
static size_t rotating_files = 5;
try
void bench_threaded_logging(int threads, int iters)
{
if (argc > 1)
howmany = atoi(argv[1]);
if (argc > 2)
threads = atoi(argv[2]);
if (argc > 3)
queue_size = atoi(argv[3]);
spdlog::info("**************************************************************");
spdlog::info("Single thread, {:n} iterations", howmany);
spdlog::info("Multi threaded: {:n} threads, {:n} messages", threads, iters);
spdlog::info("**************************************************************");
auto basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_st.log", true);
bench(howmany, std::move(basic_st));
basic_st.reset();
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
bench(howmany, std::move(rotating_st));
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
bench_mt(iters, std::move(basic_mt), threads);
auto basic_mt_tracing = spdlog::basic_logger_mt("basic_mt/backtrace-on", "logs/basic_mt.log", true);
basic_mt_tracing->enable_backtrace(32);
bench_mt(iters, std::move(basic_mt_tracing), threads);
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
bench(howmany, std::move(daily_st));
spdlog::info("");
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
bench_mt(iters, std::move(rotating_mt), threads);
auto rotating_mt_tracing = spdlog::rotating_logger_mt("rotating_mt/backtrace-on", "logs/rotating_mt.log", file_size, rotating_files);
rotating_mt_tracing->enable_backtrace(32);
bench_mt(iters, std::move(rotating_mt_tracing), threads);
bench(howmany, spdlog::create<null_sink_st>("null_st"));
spdlog::info("");
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
bench_mt(iters, std::move(daily_mt), threads);
auto daily_mt_tracing = spdlog::daily_logger_mt("daily_mt/backtrace-on", "logs/daily_mt.log");
daily_mt_tracing->enable_backtrace(32);
bench_mt(iters, std::move(daily_mt_tracing), threads);
spdlog::info("");
auto empty_logger = std::make_shared<spdlog::logger>("level-off");
empty_logger->set_level(spdlog::level::off);
bench(iters, empty_logger);
auto empty_logger_tracing = std::make_shared<spdlog::logger>("level-off/backtrace-on");
empty_logger_tracing->set_level(spdlog::level::off);
empty_logger_tracing->enable_backtrace(32);
bench(iters, empty_logger_tracing);
}
void bench_single_threaded(int iters)
{
spdlog::info("**************************************************************");
spdlog::info("C-string (400 bytes). Single thread, {:n} iterations", howmany);
spdlog::info("Single threaded: {:n} messages", iters);
spdlog::info("**************************************************************");
basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_cs.log", true);
bench_c_string(howmany, std::move(basic_st));
rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_cs.log", file_size, rotating_files);
bench_c_string(howmany, std::move(rotating_st));
daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_cs.log");
bench_c_string(howmany, std::move(daily_st));
bench_c_string(howmany, spdlog::create<null_sink_st>("null_st"));
auto basic_st = spdlog::basic_logger_st("basic_st", "logs/basic_st.log", true);
bench(iters, std::move(basic_st));
spdlog::info("**************************************************************");
spdlog::info("{:n} threads sharing same logger, {:n} iterations", threads, howmany);
spdlog::info("**************************************************************");
auto basic_st_tracing = spdlog::basic_logger_st("basic_st/backtrace-on", "logs/basic_st.log", true);
bench(iters, std::move(basic_st_tracing));
auto basic_mt = spdlog::basic_logger_mt("basic_mt", "logs/basic_mt.log", true);
bench_mt(howmany, std::move(basic_mt), threads);
spdlog::info("");
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "logs/rotating_st.log", file_size, rotating_files);
bench(iters, std::move(rotating_st));
auto rotating_st_tracing = spdlog::rotating_logger_st("rotating_st/backtrace-on", "logs/rotating_st.log", file_size, rotating_files);
rotating_st_tracing->enable_backtrace(32);
bench(iters, std::move(rotating_st_tracing));
auto rotating_mt = spdlog::rotating_logger_mt("rotating_mt", "logs/rotating_mt.log", file_size, rotating_files);
bench_mt(howmany, std::move(rotating_mt), threads);
spdlog::info("");
auto daily_st = spdlog::daily_logger_st("daily_st", "logs/daily_st.log");
bench(iters, std::move(daily_st));
auto daily_st_tracing = spdlog::daily_logger_st("daily_st/backtrace-on", "logs/daily_st.log");
daily_st_tracing->enable_backtrace(32);
bench(iters, std::move(daily_st_tracing));
spdlog::info("");
auto empty_logger = std::make_shared<spdlog::logger>("level-off");
empty_logger->set_level(spdlog::level::off);
bench(iters, empty_logger);
auto empty_logger_tracing = std::make_shared<spdlog::logger>("level-off/backtrace-on");
empty_logger_tracing->set_level(spdlog::level::off);
empty_logger_tracing->enable_backtrace(32);
bench(iters, empty_logger_tracing);
}
auto daily_mt = spdlog::daily_logger_mt("daily_mt", "logs/daily_mt.log");
bench_mt(howmany, std::move(daily_mt), threads);
bench_mt(howmany, spdlog::create<null_sink_mt>("null_mt"), threads);
int main(int argc, char *argv[])
{
spdlog::set_automatic_registration(false);
spdlog::default_logger()->set_pattern("[%^%l%$] %v");
int iters = 250000;
int threads = 4;
try
{
spdlog::info("**************************************************************");
spdlog::info("Asyncronous.. {:n} threads sharing same logger, {:n} iterations", threads, howmany);
spdlog::info("**************************************************************");
if (argc > 1)
iters = atoi(argv[1]);
if (argc > 2)
threads = atoi(argv[2]);
for (int i = 0; i < 3; ++i)
{
spdlog::init_thread_pool(static_cast<size_t>(queue_size), 1);
auto as = spdlog::basic_logger_mt<spdlog::async_factory>("async", "logs/basic_async.log", true);
bench_mt(howmany, std::move(as), threads);
}
bench_single_threaded(iters);
bench_threaded_logging(1, iters);
bench_threaded_logging(threads, iters);
}
catch (std::exception &ex)
{
......@@ -127,7 +144,7 @@ void bench(int howmany, std::shared_ptr<spdlog::logger> log)
auto delta = high_resolution_clock::now() - start;
auto delta_d = duration_cast<duration<double>>(delta).count();
spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::drop(log->name());
}
......@@ -153,7 +170,7 @@ void bench_mt(int howmany, std::shared_ptr<spdlog::logger> log, int thread_count
auto delta = high_resolution_clock::now() - start;
auto delta_d = duration_cast<duration<double>>(delta).count();
spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::drop(log->name());
}
......@@ -172,7 +189,7 @@ void bench_default_api(int howmany, std::shared_ptr<spdlog::logger> log)
auto delta_d = duration_cast<duration<double>>(delta).count();
spdlog::drop(log->name());
spdlog::set_default_logger(std::move(orig_default));
spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
}
void bench_c_string(int howmany, std::shared_ptr<spdlog::logger> log)
......@@ -195,5 +212,5 @@ void bench_c_string(int howmany, std::shared_ptr<spdlog::logger> log)
auto delta_d = duration_cast<duration<double>>(delta).count();
spdlog::drop(log->name());
spdlog::set_default_logger(std::move(orig_default));
spdlog::info("{:<16} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
spdlog::info("{:<30} Elapsed: {:0.2f} secs {:>16n}/sec", log->name(), delta_d, int(howmany / delta_d));
}
......@@ -8,27 +8,15 @@
#include "spdlog/spdlog.h"
#include "spdlog/details/pattern_formatter.h"
void bench_scoped_pad(benchmark::State &state, size_t wrapped_size, spdlog::details::padding_info padinfo)
{
fmt::memory_buffer dest;
for (auto _ : state)
{
{
spdlog::details::scoped_pad p(wrapped_size, padinfo, dest);
benchmark::DoNotOptimize(p);
dest.clear();
}
}
}
void bench_formatter(benchmark::State &state, std::string pattern)
{
auto formatter = spdlog::details::make_unique<spdlog::pattern_formatter>(pattern);
fmt::memory_buffer dest;
spdlog::memory_buf_t dest;
std::string logger_name = "logger-name";
const char *text = "Hello. This is some message with length of 80 ";
spdlog::details::log_msg msg(&logger_name, spdlog::level::info, text);
spdlog::source_loc source_loc{"a/b/c/d/myfile.cpp", 123, "some_func()"};
spdlog::details::log_msg msg(source_loc, logger_name, spdlog::level::info, text);
for (auto _ : state)
{
......@@ -41,7 +29,7 @@ void bench_formatter(benchmark::State &state, std::string pattern)
void bench_formatters()
{
// basic patterns(single flag)
std::string all_flags = "+vtPnlLaAbBcCYDmdHIMSefFprRTXzEi%";
std::string all_flags = "+vtPnlLaAbBcCYDmdHIMSefFprRTXzEisg@luioO%";
std::vector<std::string> basic_patterns;
for (auto &flag : all_flags)
{
......
......@@ -90,29 +90,50 @@ int main(int argc, char *argv[])
disabled_logger->set_level(spdlog::level::off);
benchmark::RegisterBenchmark("disabled-at-compile-time", bench_disabled_macro, disabled_logger);
benchmark::RegisterBenchmark("disabled-at-runtime", bench_logger, disabled_logger);
// with backtrace of 64
auto tracing_disabled_logger = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
tracing_disabled_logger->enable_backtrace(64);
benchmark::RegisterBenchmark("disabled-at-runtime/backtrace", bench_logger, tracing_disabled_logger);
auto null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
benchmark::RegisterBenchmark("null_sink_st (500_bytes c_str)", bench_c_string, std::move(null_logger_st));
benchmark::RegisterBenchmark("null_sink_st", bench_logger, null_logger_st);
// with backtrace of 64
auto tracing_null_logger_st = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_st>());
tracing_null_logger_st->enable_backtrace(64);
benchmark::RegisterBenchmark("null_sink_st/backtrace", bench_logger, tracing_null_logger_st);
// basic_st
auto basic_st = spdlog::basic_logger_st("basic_st", "latency_logs/basic_st.log", true);
benchmark::RegisterBenchmark("basic_st", bench_logger, std::move(basic_st))->UseRealTime();
spdlog::drop("basic_st");
// with backtrace of 64
auto tracing_basic_st = spdlog::basic_logger_st("tracing_basic_st", "latency_logs/tracing_basic_st.log", true);
tracing_basic_st->enable_backtrace(64);
benchmark::RegisterBenchmark("basic_st/backtrace", bench_logger, std::move(tracing_basic_st))->UseRealTime();
spdlog::drop("tracing_basic_st");
// rotating st
auto rotating_st = spdlog::rotating_logger_st("rotating_st", "latency_logs/rotating_st.log", file_size, rotating_files);
benchmark::RegisterBenchmark("rotating_st", bench_logger, std::move(rotating_st))->UseRealTime();
spdlog::drop("rotating_st");
// with backtrace of 64
auto tracing_rotating_st =
spdlog::rotating_logger_st("tracing_rotating_st", "latency_logs/tracing_rotating_st.log", file_size, rotating_files);
benchmark::RegisterBenchmark("rotating_st/backtrace", bench_logger, std::move(tracing_rotating_st))->UseRealTime();
spdlog::drop("tracing_rotating_st");
// daily st
auto daily_st = spdlog::daily_logger_mt("daily_st", "latency_logs/daily_st.log");
benchmark::RegisterBenchmark("daily_st", bench_logger, std::move(daily_st))->UseRealTime();
spdlog::drop("daily_st");
auto tracing_daily_st = spdlog::daily_logger_mt("tracing_daily_st", "latency_logs/daily_st.log");
benchmark::RegisterBenchmark("daily_st/backtrace", bench_logger, std::move(tracing_daily_st))->UseRealTime();
spdlog::drop("tracing_daily_st");
// //
// // Multi threaded bench, 10 loggers using same logger concurrently
// //
//
// Multi threaded bench, 10 loggers using same logger concurrently
//
auto null_logger_mt = std::make_shared<spdlog::logger>("bench", std::make_shared<null_sink_mt>());
benchmark::RegisterBenchmark("null_sink_mt", bench_logger, null_logger_mt)->Threads(n_threads)->UseRealTime();
......@@ -138,6 +159,11 @@ int main(int argc, char *argv[])
"async_logger", std::make_shared<null_sink_mt>(), std::move(tp), spdlog::async_overflow_policy::overrun_oldest);
benchmark::RegisterBenchmark("async_logger", bench_logger, async_logger)->Threads(n_threads)->UseRealTime();
auto async_logger_tracing = std::make_shared<spdlog::async_logger>(
"async_logger_tracing", std::make_shared<null_sink_mt>(), std::move(tp), spdlog::async_overflow_policy::overrun_oldest);
async_logger_tracing->enable_backtrace(32);
benchmark::RegisterBenchmark("async_logger/tracing", bench_logger, async_logger_tracing)->Threads(n_threads)->UseRealTime();
benchmark::Initialize(&argc, argv);
benchmark::RunSpecifiedBenchmarks();
}
# Ignore everything in this directory
*
# Except this file
!.gitignore
#!/bin/sh
if [ $# -lt 1 ]; then
echo "usage: $0 <program>"
fi
PROG=$1
if [ ! -x "$PROG" ]; then
echo $PROG not found or not executable.
exit 1
fi
$* &
PID=$!
while `kill -0 $PID 2>/dev/null`; do
ps -eo size,pid,user,pcpu,command --sort -size | awk '{ line=1 ; hr=$1/1024 ; printf("%13.2f Mb ",hr); } { for ( x=4 ; x<=NF ; x++ ) { printf("%s ",$x) } print "" }' | grep -v grep | grep -v $0 | grep $PROG
done
benchmark = dependency('benchmark')
bench_matrix = [
['bench', [spdlog_dep], []],
['async_bench', [spdlog_dep], []],
['formatter-bench', [spdlog_dep, benchmark], ['all']],
['latency', [spdlog_dep, benchmark], []],
]
foreach i : bench_matrix
bench_exe = executable(i[0], i[0] + '.cpp', dependencies: i[1])
benchmark('bench_' + i[0], bench_exe, args: i[2])
endforeach
run_command(find_program('mkdir'), meson.current_build_dir() + '/logs')
#!/bin/bash
clang-tidy example/example.cpp -- -I ./include
# *************************************************************************/
# * Copyright (c) 2015 Ruslan Baratov. */
# * */
# * Permission is hereby granted, free of charge, to any person obtaining */
# * a copy of this software and associated documentation files (the */
# * "Software"), to deal in the Software without restriction, including */
# * without limitation the rights to use, copy, modify, merge, publish, */
# * distribute, sublicense, and/or sell copies of the Software, and to */
# * permit persons to whom the Software is furnished to do so, subject to */
# * the following conditions: */
# * */
# * The above copyright notice and this permission notice shall be */
# * included in all copies or substantial portions of the Software. */
# * */
# * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
# * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
# * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
# * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
# * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
# * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
# * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
# *************************************************************************/
set(SPDLOG_FMT_EXTERNAL @SPDLOG_FMT_EXTERNAL@)
include("${CMAKE_CURRENT_LIST_DIR}/@targets_export_name@.cmake")
if(SPDLOG_FMT_EXTERNAL)
include(CMakeFindDependencyMacro)
find_dependency(fmt CONFIG)
endif()
#---------------------------------------------------------------------------------------
# IDE support for headers
#---------------------------------------------------------------------------------------
set(SPDLOG_HEADERS_DIR "${CMAKE_CURRENT_LIST_DIR}/../include")
file(GLOB SPDLOG_TOP_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/*.h")
file(GLOB SPDLOG_DETAILS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/details/*.h")
file(GLOB SPDLOG_SINKS_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/sinks/*.h")
file(GLOB SPDLOG_FMT_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/*.h")
file(GLOB SPDLOG_FMT_BUNDELED_HEADERS "${SPDLOG_HEADERS_DIR}/spdlog/fmt/bundled/*.h")
set(SPDLOG_ALL_HEADERS ${SPDLOG_TOP_HEADERS} ${SPDLOG_DETAILS_HEADERS} ${SPDLOG_SINKS_HEADERS} ${SPDLOG_FMT_HEADERS} ${SPDLOG_FMT_BUNDELED_HEADERS})
source_group("Header Files\\spdlog" FILES ${SPDLOG_TOP_HEADERS})
source_group("Header Files\\spdlog\\details" FILES ${SPDLOG_DETAILS_HEADERS})
source_group("Header Files\\spdlog\\sinks" FILES ${SPDLOG_SINKS_HEADERS})
source_group("Header Files\\spdlog\\fmt" FILES ${SPDLOG_FMT_HEADERS})
source_group("Header Files\\spdlog\\fmt\\bundled\\" FILES ${SPDLOG_FMT_BUNDELED_HEADERS})
if(SPDLOG_SANITIZE_THREAD AND SPDLOG_SANITIZE_ADDRESS)
message(FATAL_ERROR "AddressSanitizer is not compatible with ThreadSanitizer.")
endif()
if(SPDLOG_SANITIZE_ADDRESS)
message(STATUS "AddressSanitizer enabled")
set(SANITIZER_FLAGS "-fsanitize=address,undefined")
add_compile_options("-fno-sanitize=signed-integer-overflow")
endif()
if(SPDLOG_SANITIZE_THREAD)
message(STATUS "ThreadSanitizer enabled")
set(SANITIZER_FLAGS "-fsanitize=thread")
endif()
if(SPDLOG_SANITIZE_THREAD OR SPDLOG_SANITIZE_ADDRESS)
add_compile_options(${SANITIZER_FLAGS})
add_compile_options("-fno-sanitize-recover=all")
add_compile_options("-fno-omit-frame-pointer")
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${SANITIZER_FLAGS} -fuse-ld=gold")
endif()