SlideShare a Scribd company logo
1 of 21
1

                       www.chenshuo.com




          EFFICIENT LOGGING IN
          MULTITHREADED C++ SERVER
2012/06    Shuo Chen
Show me the code
2


       C++ logging library in muduo 0.5.0
         http://code.google.com/p/muduo      (release)
         github.com/chenshuo/muduo           (latest)
         github.com/chenshuo/recipes/tree/master/logging

       Performance on i5-2500
         1,000,000+ log messages per second
         Max throughput 100+MiB/s

         1us~1.6us latency per message for async logging



    2012/06                                      www.chenshuo.com
Two meanings of log
3


       Diagnostic log                 Transaction log
         log4j,logback, slf4j           Write-ahead log

         log4cxx, log4cpp,              Binlog,redo log
          log4cplus, glog, g2log,        Journaling
          Pantheios, ezlogger            Log-structured FS


       Here we mean diagnostic log/logging
         Textual,
                 human readable
         grep/sed/awk friendly


    2012/06                                          www.chenshuo.com
Features of common logging library
4


       Multiple log levels, enable/disable at runtime
         TRACE,   DEBUG, INFO, WARN, ERROR, FATAL
       Flexibilities are not all necessary!
         Appenders, layouts,    filters
       Many possible destinations? ie. Appender
         There is   one true destination, really
       Configure log line format at runtime? ie. Layout
         You   won’t change format during life time of a project
       Muduo logging is configured at compile time
         No xml config file, but a few lines of code in main()
    2012/06                                           www.chenshuo.com
What to log in distributed system
5


       Everything! All the time!
         http://highscalability.com/log-everything-all-time

       Log must be fast
         Tensof thousands messages per sec is normal
         without noticeable performance penalty

         Should never block normal execution flow

       Log data could be big
         up   to 1GB per minute, for one process on one host
      An efficient logging library is a prerequisite for
       any non-trivial server-side program www.chenshuo.com
    2012/06
Frontend and backend of log lib
6


       Frontend formats log messages
       Backend sends log messages to destination (file)
       The interface between could be as simple as
           void output_log(const char* msg, int len)
       However, in a multithreaded program, the most
        difficult part is neither frontend nor backend, but
        transfer log data from frontend to backend
         Multiple     producers (frontend), one consumer
               Low latency / low CPU overhead   for frontend
               High throughput for backend
    2012/06                                                 www.chenshuo.com
Frontend should be easy to use
7


       Two styles in C++, C/Java function vs. C++ stream
         printlog(“Received %d  bytes from %s”, len, client);
         LOG << “Received ” << len << “ bytes from ” << client;

       print*() can be made type safe, but cumbersome
         You can’t pass non-POD objects as (...) arguments
         Pantheios uses overloaded function templates

       LOG is easier to use IMO, no placeholder in fmt str
         When  logging level is disabled, the whole statement
          can be made a nop, almost no runtime overhead at all
               http://www.drdobbs.com/cpp/201804215
    2012/06                                            www.chenshuo.com
Why muduo::LogStream ?
8


       std::ostream is too slow and not thread-safe
         One      ostringstream object per log msg is expensive
       LogStream is fast because
         No     formatting, no manipulators, no i18n or l10n
            Output integers, doubles, pointers, strings
            Fmt class is provided, though

         Fixed-size      buffer allocated on stack, no malloc call
            Also limit the max log msg to 4000      bytes, same as glog
         See     benchmark result at
               www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html
    2012/06    muduo/base/test/LogStream_bench.cc          www.chenshuo.com
Log line format is also fixed
9


       You don’t want to change output format at
        runtime, do you?
         One log message per line, easy for grep
         date time(UTC) thread-id level message source
        20120603 08:02:46.125770Z 23261 INFO Hello - test.cc:51
        20120603 08:02:46.126926Z 23261 WARN World - test.cc:52
        20120603 08:02:46.126997Z 23261 ERROR Error - test.cc:53

       No overhead of parsing format string all the time
         Further   more, the date time string is cached in 1 sec
       TRACE and DEBUG levels are disabled by default
         Turn them on with environment variable www.chenshuo.com
    2012/06
The one true destination: LogFile
10


        Local file, with rolling & timestamp in log filename
        It is a joke to write large amount of log messages to
          SMTP,   Database, Network (FTP, “log server”)
        The purpose of logging is to investigate what has
         happened in case of system failure or malfunction
          Network   could fail, how to log that event?
        Log to network may also double bandwidth usage
          Be   aware of log to network mapped file system
        What if disk fails? The host is not usable anyway
          Check dmesg and other kernel logs
     2012/06                                              www.chenshuo.com
Performance requirement
11


        Suppose PC server with SATA disks, no RAID
          110MB/s   7200rpm single disk
          Logging to local disk, 110 bytes per log message

          1000k log messages per second with IO buffer

          Target for a “high-performance” logging library

        For a busy server with 100k qps, logging every
         request should not take too much CPU time
          100k   log msgs per second can only serve 10k qps
        The log library should be able to write 100MB/s
          And   lasts for seconds (at peak time of course)
     2012/06                                           www.chenshuo.com
Performance of muduo logging
12


        ~100-byte msgs, single thread, synchronous log
        E5320                    i5-2500

        nop (msgs/s, bytes/s)  nop (msgs/s, bytes/s)
          971k/s,   107.6MiB/s        2422k/s,   256.2MiB/s
        /dev/null                   /dev/null
          912k/s,   101.1MiB/s        2342k/s,   247.7MiB/s
        /tmp/log                    /tmp/log
          810k/s,   =89.8MiB/s        2130k/s,   225.3MiB/s
        1,000,000+ msgs per sec, saturate disk bandwidth
     2012/06                                         www.chenshuo.com
Other trick for postmortem
13


        Log output must be buffered
          can’t   afford fflush(3)ing every time
        What if program crashes, there must be some
         unwritten log messages in core file, how to find ?
        Put a cookie (a sentry value) at beginning of
         message/buffer
          Cookie can be an address of function, to be unique
          Also set cookie to some other function in dtor

        Identify messages with gdb find command
     2012/06                                        www.chenshuo.com
Logging in multithreaded program
14


        Logging must be thread-safe (no interleaving)
        And efficient
        Better to log to one file per process, not per thread
          Easierfor reading log, not jump around files
          The OS kernel has to serialize writing anyway

        Thread-safe is easy, efficient is not that easy
          Global lock   and blocking writing are bad ideas
        One background thread gathers log messages and
         write them to disk. Aka. asynchronous logging.
     2012/06                                          www.chenshuo.com
Asynchronous logging is a must
15


        Aka. Non-blocking logging
        Disk IO can block for seconds, occasionally
          Cause      timeouts in distributed system
                and cascade effects, eg. false alarms of deadlock, etc.

        Absolutely no disk IO in normal execution flow
                Very important for non-blocking network programming,
                check my other slides
        We need a “queue” to pass log data efficiently
          Not     necessarily a traditional blocking queue,
                no need to notify consumer every time there is
     2012/06    something to write                             www.chenshuo.com
What if messages queue up?
16


        Program writes log faster than disk bandwidth?
          Itqueues first in OS cache
          Then in the process, memory usage increase rapidly

        In case of overload, the logging library should
         not crash or OOM, drop messages instead
          Send   alerts via network if necessary


        Not a problem in synchronous logging
          Blocking-IO is   easy/good for bandwidth throttling
     2012/06                                         www.chenshuo.com
Double buffering for the queue
17


        Basic idea: two buffers, swap them when one is full
          Allbusiness threads write to one buffer, memcpy only
          Log thread writes the other buffer to disk

        Improvement: four buffers, no waiting in most case
        Critical code in critical sections, next two pages
          typedef boost::ptr_vector<LargeBuffer> BufferVector;
          typedef BufferVector::auto_type   BufferPtr;
          muduo::MutexLock   mutex_;
          muduo::Condition   cond_;
          BufferPtr          currentBuffer_;
          BufferPtr          nextBuffer_;
          BufferVector       buffers_;
     2012/06                                              www.chenshuo.com
void AsyncLogging::append(const char* logline, int len)
     {
       muduo::MutexLockGuard lock(mutex_);
       if (currentBuffer_->avail() > len)
       { // most common case: buffer is not full, copy data here
         currentBuffer_->append(logline, len);
       }
       else // buffer is full, push it, and find next spare buffer
       {
         buffers_.push_back(currentBuffer_.release());

           if (nextBuffer_) // is there is one already, use it
           {
             currentBuffer_ = boost::ptr_container::move(nextBuffer_);
           }
           else // allocate a new one
           {
             currentBuffer_.reset(new Buffer); // Rarely happens
           }
           currentBuffer_->append(logline, len);
           cond_.notify();
       }
18   } 2012/06                                             www.chenshuo.com
// in log thread
     BufferPtr newBuffer1(new Buffer);
     BufferPtr newBuffer2(new Buffer);
     boost::ptr_vector<Buffer> buffersToWrite(16);
     while (running_)
     {
       // swap out what need to be written, keep CS short
       {
         muduo::MutexLockGuard lock(mutex_);
         cond_.waitForSeconds(flushInterval_);
         buffers_.push_back(currentBuffer_.release());
         currentBuffer_ = boost::ptr_container::move(newBuffer1);
         buffersToWrite.swap(buffers_);
         if (!nextBuffer_)
         {
           nextBuffer_ = boost::ptr_container::move(newBuffer2);
         }
       }
       // output buffersToWrite, re-fill newBuffer1/2
     }
     // final note: bzero() each buffer initially to avoid page faults

19   2012/06                                             www.chenshuo.com
Alternative solutions?
20


         Use normal muduo::BlockingQueue<string> or
          BoundedBlockingQueue<string> as the queue
           Allocate memory for every log message, you need a
            good malloc that optimized for multithreading
           Replace stack buffer with heap buffer in LogStream

           Instead of copying data, passing pointer might be faster
              But as I tested, copying data is 3x faster for small msgs ~4k
              That’s why muduo only provides one    AsyncLogging class
         More buffers, reduce lock contention
           Like   ConcurrentHashMap, buckets hashed by thread id
         2012/06                                              www.chenshuo.com
Conclusion
21


        Muduo logging library is fairly speedy
        It provides the most fundamental features
           No   bells and whistles, no unnecessary flexibilities
        Frontend: LogStream and Logging classes
           LOG_INFO    << "Hello";
         20120603 08:02:46.125770Z 23261 INFO    Hello - test.cc:51
        Backend: LogFile class, rolling & timestamped
             logfile_test.20120603-144022.hostname.3605.log
        For multithreaded, use AsyncLogging class
           Check   examples in muduo/base/tests for how to use
     2012/06                                            www.chenshuo.com

More Related Content

What's hot

Embedded c & working with avr studio
Embedded c & working with avr studioEmbedded c & working with avr studio
Embedded c & working with avr studio
Nitesh Singh
 
8086-instruction-set-ppt
 8086-instruction-set-ppt 8086-instruction-set-ppt
8086-instruction-set-ppt
jemimajerome
 

What's hot (20)

Embedded c & working with avr studio
Embedded c & working with avr studioEmbedded c & working with avr studio
Embedded c & working with avr studio
 
Instruction types
Instruction typesInstruction types
Instruction types
 
Processor Organization
Processor OrganizationProcessor Organization
Processor Organization
 
Rtos concepts
Rtos conceptsRtos concepts
Rtos concepts
 
SPI Protocol in LPC2148
SPI  Protocol in LPC2148SPI  Protocol in LPC2148
SPI Protocol in LPC2148
 
Pipelining slides
Pipelining slides Pipelining slides
Pipelining slides
 
8086-instruction-set-ppt
 8086-instruction-set-ppt 8086-instruction-set-ppt
8086-instruction-set-ppt
 
Embedded System Programming on ARM Cortex M3 and M4 Course
Embedded System Programming on ARM Cortex M3 and M4 CourseEmbedded System Programming on ARM Cortex M3 and M4 Course
Embedded System Programming on ARM Cortex M3 and M4 Course
 
Instruction set
Instruction setInstruction set
Instruction set
 
The Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast StorageThe Linux Block Layer - Built for Fast Storage
The Linux Block Layer - Built for Fast Storage
 
Transactional Memory
Transactional MemoryTransactional Memory
Transactional Memory
 
Fibre Channel over Ethernet (FCoE), iSCSI and the Converged Data Center
Fibre Channel over Ethernet (FCoE), iSCSI and the Converged Data CenterFibre Channel over Ethernet (FCoE), iSCSI and the Converged Data Center
Fibre Channel over Ethernet (FCoE), iSCSI and the Converged Data Center
 
Design and Implementation of Axi-Apb Bridge based on Amba 4.0
Design and Implementation of Axi-Apb Bridge based on Amba 4.0Design and Implementation of Axi-Apb Bridge based on Amba 4.0
Design and Implementation of Axi-Apb Bridge based on Amba 4.0
 
Socket System Calls
Socket System CallsSocket System Calls
Socket System Calls
 
Communication Protocols (UART, SPI,I2C)
Communication Protocols (UART, SPI,I2C)Communication Protocols (UART, SPI,I2C)
Communication Protocols (UART, SPI,I2C)
 
Basic Linux Internals
Basic Linux InternalsBasic Linux Internals
Basic Linux Internals
 
SPI Protocol
SPI ProtocolSPI Protocol
SPI Protocol
 
Ch8 (1) morris mano
Ch8 (1) morris manoCh8 (1) morris mano
Ch8 (1) morris mano
 
Electronics Microcontrollers for IoT applications
Electronics Microcontrollers for IoT applicationsElectronics Microcontrollers for IoT applications
Electronics Microcontrollers for IoT applications
 
Binary and hex input/output (in 8086 assembuly langyage)
Binary and hex input/output (in 8086 assembuly langyage)Binary and hex input/output (in 8086 assembuly langyage)
Binary and hex input/output (in 8086 assembuly langyage)
 

Viewers also liked

Datetime - Julian Date
Datetime - Julian DateDatetime - Julian Date
Datetime - Julian Date
Shuo Chen
 
Essentials of Multithreaded System Programming in C++
Essentials of Multithreaded System Programming in C++Essentials of Multithreaded System Programming in C++
Essentials of Multithreaded System Programming in C++
Shuo Chen
 

Viewers also liked (7)

Muduo network library
Muduo network libraryMuduo network library
Muduo network library
 
Zurg part 1
Zurg part 1Zurg part 1
Zurg part 1
 
Where destructors meet threads
Where destructors meet threadsWhere destructors meet threads
Where destructors meet threads
 
Datetime - Julian Date
Datetime - Julian DateDatetime - Julian Date
Datetime - Julian Date
 
Multithreading Fundamentals
Multithreading FundamentalsMultithreading Fundamentals
Multithreading Fundamentals
 
Essentials of Multithreaded System Programming in C++
Essentials of Multithreaded System Programming in C++Essentials of Multithreaded System Programming in C++
Essentials of Multithreaded System Programming in C++
 
Enterprise PHP Architecture through Design Patterns and Modularization (Midwe...
Enterprise PHP Architecture through Design Patterns and Modularization (Midwe...Enterprise PHP Architecture through Design Patterns and Modularization (Midwe...
Enterprise PHP Architecture through Design Patterns and Modularization (Midwe...
 

Similar to Efficient logging in multithreaded C++ server

Porting C++ apps to FLASCC
Porting C++ apps to FLASCCPorting C++ apps to FLASCC
Porting C++ apps to FLASCC
Pavel Nakaznenko
 
Varnish http accelerator
Varnish http acceleratorVarnish http accelerator
Varnish http accelerator
no no
 

Similar to Efficient logging in multithreaded C++ server (20)

Open HFT libraries in @Java
Open HFT libraries in @JavaOpen HFT libraries in @Java
Open HFT libraries in @Java
 
Технологии работы с дисковыми хранилищами и файловыми системами Windows Serve...
Технологии работы с дисковыми хранилищами и файловыми системами Windows Serve...Технологии работы с дисковыми хранилищами и файловыми системами Windows Serve...
Технологии работы с дисковыми хранилищами и файловыми системами Windows Serve...
 
On Centralizing Logs
On Centralizing LogsOn Centralizing Logs
On Centralizing Logs
 
What Have We Lost - A look at some historical techniques
What Have We Lost - A look at some historical techniquesWhat Have We Lost - A look at some historical techniques
What Have We Lost - A look at some historical techniques
 
os
osos
os
 
Low level java programming
Low level java programmingLow level java programming
Low level java programming
 
Tuning Solr and its Pipeline for Logs: Presented by Rafał Kuć & Radu Gheorghe...
Tuning Solr and its Pipeline for Logs: Presented by Rafał Kuć & Radu Gheorghe...Tuning Solr and its Pipeline for Logs: Presented by Rafał Kuć & Radu Gheorghe...
Tuning Solr and its Pipeline for Logs: Presented by Rafał Kuć & Radu Gheorghe...
 
Tuning Solr & Pipeline for Logs
Tuning Solr & Pipeline for LogsTuning Solr & Pipeline for Logs
Tuning Solr & Pipeline for Logs
 
Experience In Building Scalable Web Sites Through Infrastructure's View
Experience In Building Scalable Web Sites Through Infrastructure's ViewExperience In Building Scalable Web Sites Through Infrastructure's View
Experience In Building Scalable Web Sites Through Infrastructure's View
 
Porting C++ apps to FLASCC
Porting C++ apps to FLASCCPorting C++ apps to FLASCC
Porting C++ apps to FLASCC
 
Varnish http accelerator
Varnish http acceleratorVarnish http accelerator
Varnish http accelerator
 
Luxun a Persistent Messaging System Tailored for Big Data Collecting & Analytics
Luxun a Persistent Messaging System Tailored for Big Data Collecting & AnalyticsLuxun a Persistent Messaging System Tailored for Big Data Collecting & Analytics
Luxun a Persistent Messaging System Tailored for Big Data Collecting & Analytics
 
NIO.pdf
NIO.pdfNIO.pdf
NIO.pdf
 
Log Management Systems
Log Management SystemsLog Management Systems
Log Management Systems
 
Wish list from PostgreSQL - Linux Kernel Summit 2009
Wish list from PostgreSQL - Linux Kernel Summit 2009Wish list from PostgreSQL - Linux Kernel Summit 2009
Wish list from PostgreSQL - Linux Kernel Summit 2009
 
notes2 memory_cpu
notes2 memory_cpunotes2 memory_cpu
notes2 memory_cpu
 
Deployment Strategies (Mongo Austin)
Deployment Strategies (Mongo Austin)Deployment Strategies (Mongo Austin)
Deployment Strategies (Mongo Austin)
 
Mongo performance tuning: tips and tricks
Mongo performance tuning: tips and tricksMongo performance tuning: tips and tricks
Mongo performance tuning: tips and tricks
 
Nagios Conference 2012 - Dan Wittenberg - Case Study: Scaling Nagios Core at ...
Nagios Conference 2012 - Dan Wittenberg - Case Study: Scaling Nagios Core at ...Nagios Conference 2012 - Dan Wittenberg - Case Study: Scaling Nagios Core at ...
Nagios Conference 2012 - Dan Wittenberg - Case Study: Scaling Nagios Core at ...
 
Kafka on ZFS: Better Living Through Filesystems
Kafka on ZFS: Better Living Through Filesystems Kafka on ZFS: Better Living Through Filesystems
Kafka on ZFS: Better Living Through Filesystems
 

Recently uploaded

Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
WSO2
 

Recently uploaded (20)

Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdfRising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
Rising Above_ Dubai Floods and the Fortitude of Dubai International Airport.pdf
 
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
Apidays New York 2024 - The Good, the Bad and the Governed by David O'Neill, ...
 
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
Web Form Automation for Bonterra Impact Management (fka Social Solutions Apri...
 
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
Apidays New York 2024 - Accelerating FinTech Innovation by Vasa Krishnan, Fin...
 
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ..."I see eyes in my soup": How Delivery Hero implemented the safety system for ...
"I see eyes in my soup": How Delivery Hero implemented the safety system for ...
 
Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...Apidays New York 2024 - The value of a flexible API Management solution for O...
Apidays New York 2024 - The value of a flexible API Management solution for O...
 
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
Emergent Methods: Multi-lingual narrative tracking in the news - real-time ex...
 
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUKSpring Boot vs Quarkus the ultimate battle - DevoxxUK
Spring Boot vs Quarkus the ultimate battle - DevoxxUK
 
[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf[BuildWithAI] Introduction to Gemini.pdf
[BuildWithAI] Introduction to Gemini.pdf
 
MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024MINDCTI Revenue Release Quarter One 2024
MINDCTI Revenue Release Quarter One 2024
 
Architecting Cloud Native Applications
Architecting Cloud Native ApplicationsArchitecting Cloud Native Applications
Architecting Cloud Native Applications
 
2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...2024: Domino Containers - The Next Step. News from the Domino Container commu...
2024: Domino Containers - The Next Step. News from the Domino Container commu...
 
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, AdobeApidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
Apidays New York 2024 - Scaling API-first by Ian Reasor and Radu Cotescu, Adobe
 
Corporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptxCorporate and higher education May webinar.pptx
Corporate and higher education May webinar.pptx
 
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
Biography Of Angeliki Cooney | Senior Vice President Life Sciences | Albany, ...
 
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin WoodPolkadot JAM Slides - Token2049 - By Dr. Gavin Wood
Polkadot JAM Slides - Token2049 - By Dr. Gavin Wood
 
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemkeProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
ProductAnonymous-April2024-WinProductDiscovery-MelissaKlemke
 
Boost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdfBoost Fertility New Invention Ups Success Rates.pdf
Boost Fertility New Invention Ups Success Rates.pdf
 
CNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In PakistanCNIC Information System with Pakdata Cf In Pakistan
CNIC Information System with Pakdata Cf In Pakistan
 
AWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of TerraformAWS Community Day CPH - Three problems of Terraform
AWS Community Day CPH - Three problems of Terraform
 

Efficient logging in multithreaded C++ server

  • 1. 1 www.chenshuo.com EFFICIENT LOGGING IN MULTITHREADED C++ SERVER 2012/06 Shuo Chen
  • 2. Show me the code 2  C++ logging library in muduo 0.5.0  http://code.google.com/p/muduo (release)  github.com/chenshuo/muduo (latest)  github.com/chenshuo/recipes/tree/master/logging  Performance on i5-2500  1,000,000+ log messages per second  Max throughput 100+MiB/s  1us~1.6us latency per message for async logging 2012/06 www.chenshuo.com
  • 3. Two meanings of log 3  Diagnostic log  Transaction log  log4j,logback, slf4j  Write-ahead log  log4cxx, log4cpp,  Binlog,redo log log4cplus, glog, g2log,  Journaling Pantheios, ezlogger  Log-structured FS  Here we mean diagnostic log/logging  Textual, human readable  grep/sed/awk friendly 2012/06 www.chenshuo.com
  • 4. Features of common logging library 4  Multiple log levels, enable/disable at runtime  TRACE, DEBUG, INFO, WARN, ERROR, FATAL  Flexibilities are not all necessary!  Appenders, layouts, filters  Many possible destinations? ie. Appender  There is one true destination, really  Configure log line format at runtime? ie. Layout  You won’t change format during life time of a project  Muduo logging is configured at compile time  No xml config file, but a few lines of code in main() 2012/06 www.chenshuo.com
  • 5. What to log in distributed system 5  Everything! All the time!  http://highscalability.com/log-everything-all-time  Log must be fast  Tensof thousands messages per sec is normal  without noticeable performance penalty  Should never block normal execution flow  Log data could be big  up to 1GB per minute, for one process on one host  An efficient logging library is a prerequisite for any non-trivial server-side program www.chenshuo.com 2012/06
  • 6. Frontend and backend of log lib 6  Frontend formats log messages  Backend sends log messages to destination (file)  The interface between could be as simple as  void output_log(const char* msg, int len)  However, in a multithreaded program, the most difficult part is neither frontend nor backend, but transfer log data from frontend to backend  Multiple producers (frontend), one consumer  Low latency / low CPU overhead for frontend  High throughput for backend 2012/06 www.chenshuo.com
  • 7. Frontend should be easy to use 7  Two styles in C++, C/Java function vs. C++ stream  printlog(“Received %d bytes from %s”, len, client);  LOG << “Received ” << len << “ bytes from ” << client;  print*() can be made type safe, but cumbersome  You can’t pass non-POD objects as (...) arguments  Pantheios uses overloaded function templates  LOG is easier to use IMO, no placeholder in fmt str  When logging level is disabled, the whole statement can be made a nop, almost no runtime overhead at all  http://www.drdobbs.com/cpp/201804215 2012/06 www.chenshuo.com
  • 8. Why muduo::LogStream ? 8  std::ostream is too slow and not thread-safe  One ostringstream object per log msg is expensive  LogStream is fast because  No formatting, no manipulators, no i18n or l10n  Output integers, doubles, pointers, strings  Fmt class is provided, though  Fixed-size buffer allocated on stack, no malloc call  Also limit the max log msg to 4000 bytes, same as glog  See benchmark result at  www.cnblogs.com/Solstice/archive/2011/07/17/2108715.html 2012/06  muduo/base/test/LogStream_bench.cc www.chenshuo.com
  • 9. Log line format is also fixed 9  You don’t want to change output format at runtime, do you?  One log message per line, easy for grep  date time(UTC) thread-id level message source 20120603 08:02:46.125770Z 23261 INFO Hello - test.cc:51 20120603 08:02:46.126926Z 23261 WARN World - test.cc:52 20120603 08:02:46.126997Z 23261 ERROR Error - test.cc:53  No overhead of parsing format string all the time  Further more, the date time string is cached in 1 sec  TRACE and DEBUG levels are disabled by default  Turn them on with environment variable www.chenshuo.com 2012/06
  • 10. The one true destination: LogFile 10  Local file, with rolling & timestamp in log filename  It is a joke to write large amount of log messages to  SMTP, Database, Network (FTP, “log server”)  The purpose of logging is to investigate what has happened in case of system failure or malfunction  Network could fail, how to log that event?  Log to network may also double bandwidth usage  Be aware of log to network mapped file system  What if disk fails? The host is not usable anyway  Check dmesg and other kernel logs 2012/06 www.chenshuo.com
  • 11. Performance requirement 11  Suppose PC server with SATA disks, no RAID  110MB/s 7200rpm single disk  Logging to local disk, 110 bytes per log message  1000k log messages per second with IO buffer  Target for a “high-performance” logging library  For a busy server with 100k qps, logging every request should not take too much CPU time  100k log msgs per second can only serve 10k qps  The log library should be able to write 100MB/s  And lasts for seconds (at peak time of course) 2012/06 www.chenshuo.com
  • 12. Performance of muduo logging 12  ~100-byte msgs, single thread, synchronous log  E5320  i5-2500  nop (msgs/s, bytes/s)  nop (msgs/s, bytes/s)  971k/s, 107.6MiB/s  2422k/s, 256.2MiB/s  /dev/null  /dev/null  912k/s, 101.1MiB/s  2342k/s, 247.7MiB/s  /tmp/log  /tmp/log  810k/s, =89.8MiB/s  2130k/s, 225.3MiB/s  1,000,000+ msgs per sec, saturate disk bandwidth 2012/06 www.chenshuo.com
  • 13. Other trick for postmortem 13  Log output must be buffered  can’t afford fflush(3)ing every time  What if program crashes, there must be some unwritten log messages in core file, how to find ?  Put a cookie (a sentry value) at beginning of message/buffer  Cookie can be an address of function, to be unique  Also set cookie to some other function in dtor  Identify messages with gdb find command 2012/06 www.chenshuo.com
  • 14. Logging in multithreaded program 14  Logging must be thread-safe (no interleaving)  And efficient  Better to log to one file per process, not per thread  Easierfor reading log, not jump around files  The OS kernel has to serialize writing anyway  Thread-safe is easy, efficient is not that easy  Global lock and blocking writing are bad ideas  One background thread gathers log messages and write them to disk. Aka. asynchronous logging. 2012/06 www.chenshuo.com
  • 15. Asynchronous logging is a must 15  Aka. Non-blocking logging  Disk IO can block for seconds, occasionally  Cause timeouts in distributed system  and cascade effects, eg. false alarms of deadlock, etc.  Absolutely no disk IO in normal execution flow  Very important for non-blocking network programming, check my other slides  We need a “queue” to pass log data efficiently  Not necessarily a traditional blocking queue,  no need to notify consumer every time there is 2012/06 something to write www.chenshuo.com
  • 16. What if messages queue up? 16  Program writes log faster than disk bandwidth?  Itqueues first in OS cache  Then in the process, memory usage increase rapidly  In case of overload, the logging library should not crash or OOM, drop messages instead  Send alerts via network if necessary  Not a problem in synchronous logging  Blocking-IO is easy/good for bandwidth throttling 2012/06 www.chenshuo.com
  • 17. Double buffering for the queue 17  Basic idea: two buffers, swap them when one is full  Allbusiness threads write to one buffer, memcpy only  Log thread writes the other buffer to disk  Improvement: four buffers, no waiting in most case  Critical code in critical sections, next two pages typedef boost::ptr_vector<LargeBuffer> BufferVector; typedef BufferVector::auto_type BufferPtr; muduo::MutexLock mutex_; muduo::Condition cond_; BufferPtr currentBuffer_; BufferPtr nextBuffer_; BufferVector buffers_; 2012/06 www.chenshuo.com
  • 18. void AsyncLogging::append(const char* logline, int len) { muduo::MutexLockGuard lock(mutex_); if (currentBuffer_->avail() > len) { // most common case: buffer is not full, copy data here currentBuffer_->append(logline, len); } else // buffer is full, push it, and find next spare buffer { buffers_.push_back(currentBuffer_.release()); if (nextBuffer_) // is there is one already, use it { currentBuffer_ = boost::ptr_container::move(nextBuffer_); } else // allocate a new one { currentBuffer_.reset(new Buffer); // Rarely happens } currentBuffer_->append(logline, len); cond_.notify(); } 18 } 2012/06 www.chenshuo.com
  • 19. // in log thread BufferPtr newBuffer1(new Buffer); BufferPtr newBuffer2(new Buffer); boost::ptr_vector<Buffer> buffersToWrite(16); while (running_) { // swap out what need to be written, keep CS short { muduo::MutexLockGuard lock(mutex_); cond_.waitForSeconds(flushInterval_); buffers_.push_back(currentBuffer_.release()); currentBuffer_ = boost::ptr_container::move(newBuffer1); buffersToWrite.swap(buffers_); if (!nextBuffer_) { nextBuffer_ = boost::ptr_container::move(newBuffer2); } } // output buffersToWrite, re-fill newBuffer1/2 } // final note: bzero() each buffer initially to avoid page faults 19 2012/06 www.chenshuo.com
  • 20. Alternative solutions? 20  Use normal muduo::BlockingQueue<string> or BoundedBlockingQueue<string> as the queue  Allocate memory for every log message, you need a good malloc that optimized for multithreading  Replace stack buffer with heap buffer in LogStream  Instead of copying data, passing pointer might be faster  But as I tested, copying data is 3x faster for small msgs ~4k  That’s why muduo only provides one AsyncLogging class  More buffers, reduce lock contention  Like ConcurrentHashMap, buckets hashed by thread id 2012/06 www.chenshuo.com
  • 21. Conclusion 21  Muduo logging library is fairly speedy  It provides the most fundamental features  No bells and whistles, no unnecessary flexibilities  Frontend: LogStream and Logging classes  LOG_INFO << "Hello"; 20120603 08:02:46.125770Z 23261 INFO Hello - test.cc:51  Backend: LogFile class, rolling & timestamped  logfile_test.20120603-144022.hostname.3605.log  For multithreaded, use AsyncLogging class  Check examples in muduo/base/tests for how to use 2012/06 www.chenshuo.com