diff --git a/build/gcc/makefile b/build/gcc/makefile index a58236d2..b99c7bf7 100644 --- a/build/gcc/makefile +++ b/build/gcc/makefile @@ -1,4 +1,5 @@ SRC_DIR=../../src + _SOURCES = factory.cpp formatters.cpp line_logger.cpp os.cpp SOURCES = $(patsubst %,$(SRC_DIR)/%,$(_SOURCES)) @@ -8,8 +9,8 @@ OBJS_DEBUG = $(patsubst %.cpp,debug/%.o,$(_SOURCES)) CXX = g++ CXXFLAGS = -march=native -Wall -std=c++11 -pthread -I../../include -CXX_RELEASE_FLAGS = -O2 -flto -CXX_DEBUG_FLAGS= -g -ggdb +CXX_RELEASE_FLAGS = -O2 -flto +CXX_DEBUG_FLAGS= -g OUTLIB_RELEASE = libc11log.a OUTLIB_DEBUG = libc11log-debug.a @@ -31,7 +32,6 @@ debug: mkdirs build-debug mkdirs: @mkdir -p release debug - build-release: $(OBJS_RELEASE) ar rs $(OUTLIB_RELEASE) $^ $(CXX) $(SRC_DIR)/test.cpp $(OUTLIB_RELEASE) -o $(TEST_RELEASE) $(CXXFLAGS) @@ -40,15 +40,17 @@ build-debug: $(OBJS_DEBUG) ar rs $(OUTLIB_DEBUG) $^ $(CXX) $(SRC_DIR)/test.cpp $(OUTLIB_DEBUG) -o $(TEST_DEBUG) $(CXXFLAGS) + release/%.o: $(SRC_DIR)/%.cpp $(CXX) -c $< -o $@ $(CXXFLAGS) + -debug/%.o: $(SRC_DIR)/%.cpp + +debug/%.o: $(SRC_DIR)/%.cpp $(CXX) -c $< -o $@ $(CXXFLAGS) clean: rm -rf release debug daily.* $(TEST_RELEASE) $(TEST_DEBUG) $(OUTLIB_RELEASE) $(OUTLIB_DEBUG) rebuild: clean all - diff --git a/include/c11log/details/blocking_queue.h b/include/c11log/details/blocking_queue.h index 4a9cbb15..61db9ba0 100644 --- a/include/c11log/details/blocking_queue.h +++ b/include/c11log/details/blocking_queue.h @@ -14,6 +14,7 @@ namespace c11log { namespace details { + template class blocking_queue { public: @@ -58,7 +59,7 @@ public: // If the queue is full, block the calling thread until there is room. void push(const T& item) { - while (!push(item, std::chrono::hours::max())); + while (!push(item, one_hour)); } // Pop a copy of the front item in the queue into the given item ref. @@ -87,7 +88,7 @@ public: // If the queue is empty, block the calling thread util there is item to pop. void pop(T& item) { - while (!pop(item, std::chrono::hours::max())); + while (!pop(item, one_hour)); } // Clear the queue @@ -102,7 +103,10 @@ private: std::queue q_; std::mutex mutex_; std::condition_variable item_pushed_cond_; - std::condition_variable item_popped_cond_; + std::condition_variable item_popped_cond_; + static constexpr auto one_hour = std::chrono::seconds(3); + }; + +} } -} \ No newline at end of file diff --git a/include/c11log/details/os.h b/include/c11log/details/os.h index e8088ec1..7aa70e39 100644 --- a/include/c11log/details/os.h +++ b/include/c11log/details/os.h @@ -10,8 +10,8 @@ namespace c11log namespace os { std::tm localtime(const std::time_t &time_t); - std::tm localtime(); + std::tm localtime(); } } -} \ No newline at end of file +} diff --git a/include/c11log/sinks/async_sink.h b/include/c11log/sinks/async_sink.h index 0780794c..773f77d3 100644 --- a/include/c11log/sinks/async_sink.h +++ b/include/c11log/sinks/async_sink.h @@ -60,8 +60,9 @@ inline void c11log::sinks::async_sink::sink_it_(const std::string& msg) inline void c11log::sinks::async_sink::thread_loop_() { + constexpr auto pop_timeout = std::chrono::seconds(1); std::string msg; - auto pop_timeout = std::chrono::seconds(1); + while (active_) { if (q_.pop(msg, pop_timeout)) diff --git a/src/formatters.cpp b/src/formatters.cpp index 2a27d908..ad9c3745 100644 --- a/src/formatters.cpp +++ b/src/formatters.cpp @@ -9,8 +9,7 @@ void c11log::formatters::format_time(const c11log::formatters::timepoint& tp, st //get ms //auto duration = tp.time_since_epoch(); //int millis = static_cast(std::chrono::duration_cast(duration).count() % 1000); - - + char buf[64]; auto size = sprintf(buf, "[%d-%02d-%02d %02d:%02d:%02d]", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, diff --git a/src/test.cpp b/src/test.cpp index 4a16f557..63a41049 100644 --- a/src/test.cpp +++ b/src/test.cpp @@ -2,6 +2,8 @@ // #include "stdafx.h" +#include + #include "c11log/logger.h" #include "c11log/sinks/async_sink.h" #include "c11log/sinks/file_sinks.h" @@ -10,44 +12,130 @@ #include "utils.h" +std::atomic push_count, pop_count; +std::atomic active; +using Q = c11log::details::blocking_queue; +using std::chrono::seconds; + +void pusher(Q* q) +{ + while(active) + { + //if(q->push("Hello", seconds(10))) + q->push("hello"); + ++push_count; + } + +} +void popper(Q* q) +{ + std::string output; + while(active) + { + //if(q->pop(output, seconds(10))) + q->pop(output); + ++pop_count; + } +} + +void testq(int size, int pushers, int poppers) +{ + + active = true; + Q q{static_cast(size)}; + + for(int i = 0; i < poppers; i++) + new std::thread(std::bind(popper, &q)); + + for(int i = 0; i < pushers; i++) + new std::thread(std::bind(pusher, &q)); + + + + while(active) + { + using std::endl; + using std::cout; + using utils::format; + + push_count = 0; + pop_count = 0; + std::this_thread::sleep_for(seconds(1)); + cout << "Pushes/sec =\t" << format(push_count.load()) << endl; + cout << "Pops/sec =\t" << format(pop_count.load()) << endl; + cout << "Total/sec =\t" << format(push_count+pop_count) << endl << endl; + cout << "Queue size =\t" << format(q.size()) << endl; + cout << "---------------------------------------------------------------------" << endl; + } + + +} int main(int argc, char* argv[]) { - using namespace std::chrono; - int nthreads = argc > 1 ? atoi(argv[1]) : 1; - int nlines = argc > 2 ? atoi(argv[2]) : 1000000; + if(argc !=4) + { + std::cerr << "Usage: " << argv[0] << " qsize, pushers, poppers" << std::endl; + return 0; + } + int qsize = atoi(argv[1]); + int pushers = atoi(argv[2]); + int poppers = atoi(argv[3]); + testq(qsize, pushers, poppers); + + /* + using namespace std::chrono; + + + int nthreads = argc > 1 ? atoi(argv[1]) : 1; + int nlines = argc > 2 ? atoi(argv[2]) : 100000; + + + auto null_sink = std::make_shared(); auto stdout_sink = std::make_shared(); - auto async = std::make_shared(100); + auto async = std::make_shared(1000); //auto fsink = std::make_shared("newlog", "txt", 1024*1024*10 , 2); - auto fsink = std::make_shared("daily", "txt"); + //auto fsink = std::make_shared("daily", "txt"); - async->add_sink(fsink); - //async->add_sink(null_sink); + //async->add_sink(fsink); + async->add_sink(null_sink); - c11log::logger logger("test"); - logger.add_sink(async); - + //console logger + auto &console = c11log::get_logger("console"); + console.add_sink(stdout_sink); + //c11log::details::blocking_queue q(1000); + //auto q_ptr = &q; std::vector threads; std::cout << "Starting " << nthreads << " threads x " << utils::format(nlines) << " lines each.." << std::endl; for (int i = 0; i < nthreads; i++) - { - auto t = new std::thread([&logger, nlines]() { - - for(int i = 0 ; i < nlines; ++i) - { - logger.info() << "Hello from thread " << std::this_thread::get_id() << "\tcounter: " << i ; - } - + { + auto logger = std::make_shared("test"); + logger->add_sink(async); + + auto t = new std::thread([logger, nlines, i]() { + auto &console = c11log::get_logger("console"); + for(int j = 0 ; j < nlines; ++j) + { + logger->info() << "Hello from thread #" << i << "\tcounter: " << j ; + if(j % 2000 == 0) + console.info() << "Hello from thread " << i << "\tcounter: " << j; + } }); threads.push_back(t); + //std::this_thread::sleep_for(milliseconds(2)); } auto stime = steady_clock::now(); + int thread_joined = 0; for(auto t:threads) + { t->join(); + std::cout << "Joined " << ++thread_joined << " threads" << std::endl; + } + auto delta = steady_clock::now() - stime; auto delta_seconds = duration_cast(delta).count()/1000.0; @@ -55,8 +143,7 @@ int main(int argc, char* argv[]) std::cout << "Total: " << utils::format(total) << " = " << utils::format(total/delta_seconds) << "/sec" << std::endl; async->shutdown(seconds(1)); - - return 0; + */ }