libfoedus-core
FOEDUS Core Library
Debug-Support functionalities

Debug-Support functionalities. More...

Detailed Description

Debug-Support functionalities.

The engine provides API to turn on/of various debug-support functionalities.

Debug Logging with glog
We use the flexible debug-logging framework, Google-logging, or glog for short. Everyone who writes code in libfoedus should be familiar with glog. For example, use it as follows.
#include <glog/logging.h>
void your_func() {
VLOG(1) << "Entered your_func()"; // verbose debug log with level 1
LOG(INFO) << "some info. some_var=" << some_var; // debug log in INFO level
if (some_error_happened) {
LOG(ERROR) << "error!"; // debug log in ERROR level
}
}
Where Debug Logs are output
With the default settings, all logs are written to /tmp/libfoedus.'level', such as /tmp/libfoedus.INFO. LOG(ERROR) and LOG(FATAL) are also copied to stderr. Logs of specific execution are written to another file, /tmp/libfoedus.'hostname'.'user name'.log.'severity level'.'date'.'time'.'pid', such as: /tmp/libfoedus.hkimura-z820.kimurhid.log.INFO.20140406-215444.26946
DLOG and DVLOG
DLOG() and DVLOG() are completely disabled and wiped from our binary if our cmake build level is RELEASE or RELWITHDBGINFO. Most of our code each user transaction goes through should use only DLOG or DVLOG in its critical path.
Debug Logging Configurations
Although we don't expose glog classes themselves in our APIs, we provide our own APIs to configure them at both start-time and run-time for easier development. The start-time configuration is foedus::debugging::DebuggingOptions (foedus::EngineOptions::debug_). The run-time configuration APIs are provided by foedus::debugging::DebuggingSupports, which you can obtain via foedus::Engine::get_debug().
Debug Logging Level House-Rules
  • LOG(FATAL) is used where we are not ready for graceful shutdown. Eventually there should be none except asserting code bugs.
  • LOG(ERROR) is the default level for problemetic cases. Most error logging would be this. Do not use DLOG(ERROR). Instead always use LOG(ERROR).
  • LOG(WARNING) should be used only for expected and minor user-triggered errors. If it's either unexpected or major (eg out-of-disk is a user error, but worth raising as an error), use LOG(ERROR). You can use DLOG(WARNING) to avoid affecting performance in critical places.
  • For normal events that happen only once or a few times over very long time (seconds or more), then use LOG(INFO). For example, module initializations logs.
  • For more frequent normal events (hundreds/thousands per second), use DLOG(INFO).
  • For debug-messages that YOU wouldn't want to see unless you are writing code in that module, use VLOG. VLOG level 0: ~tens per second, 1: ~hundreds per second, 2: ~thousand per second. If it's more than thousand per second, do NOT use VLOG. It means (at least) that many level checkings per second! Use DLOG/DVLOG then.
Performance Counters
See foedus::debugging::StopWatch, foedus::debugging::RdtscWatch, and related methods.
Collaboration diagram for Debug-Support functionalities:

Files

file  fwd.hpp
 Forward declarations of classes in debugging package.
 
file  rdtsc.hpp
 Implements an RDTSC (Real-time time stamp counter) wait to emulate latency on slower devices.
 

Classes

struct  foedus::debugging::DebuggingOptions
 Set of options for debugging support. More...
 
struct  foedus::debugging::DebuggingSupports::PapiCounters
 
class  foedus::debugging::DebuggingSupports
 APIs to support debugging functionalities. More...
 
class  foedus::debugging::RdtscWatch
 A RDTSC-based low-overhead stop watch. More...
 
class  foedus::debugging::StopWatch
 A high-resolution stop watch. More...
 

Functions

uint64_t foedus::debugging::get_rdtsc ()
 Returns the current CPU cycle via x86 RDTSC. More...
 
void foedus::debugging::wait_rdtsc_cycles (uint64_t cycles)
 Wait until the given CPU cycles elapse. More...
 

Class Documentation

struct foedus::debugging::DebuggingSupports::PapiCounters

Definition at line 37 of file debugging_supports.hpp.

Class Members
long long int counters_[128] wanna use int64_t, but to align with PAPI...

Function Documentation

uint64_t foedus::debugging::get_rdtsc ( )
inline

Returns the current CPU cycle via x86 RDTSC.

Definition at line 35 of file rdtsc.hpp.

Referenced by foedus::memory::SharedMemory::alloc(), foedus::debugging::RdtscWatch::start(), foedus::debugging::RdtscWatch::stop(), and foedus::debugging::wait_rdtsc_cycles().

35  {
36 #ifndef __aarch64__
37  // x86.
38  uint32_t low, high;
39  asm volatile("rdtsc" : "=a" (low), "=d" (high));
40  return (static_cast<uint64_t>(high) << 32) | low;
41 #else // __aarch64__
42  // AArch64. "cntvct_el0" gives read-only physical 64bit timer.
43  // http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0488d/ch09s03s01.html
44  uint64_t ret;
45  asm volatile("isb; mrs %0, cntvct_el0" : "=r" (ret));
46  return ret;
47 #endif // __aarch64__
48 }

Here is the caller graph for this function:

void foedus::debugging::wait_rdtsc_cycles ( uint64_t  cycles)
inline

Wait until the given CPU cycles elapse.

Parameters
[in]cyclesCPU cycles to wait for

In case of context switch to a different CPU that has a very different timing (esp on NUMA), we also check if the RDTSC value is not bogus. In that case, we exit the wait. This is also a safety net for wrap-around. Anyways, it's a rare case.

Definition at line 60 of file rdtsc.hpp.

References foedus::debugging::get_rdtsc().

Referenced by foedus::fs::DirectIoFile::read_raw(), foedus::fs::DirectIoFile::seek(), foedus::fs::DirectIoFile::write_raw(), and foedus::assorted::SpinlockStat::yield_backoff().

60  {
61  uint64_t cycle_error = get_rdtsc() - cycles;
62  uint64_t cycle_until = get_rdtsc() + cycles;
63  while (true) {
64  uint64_t current = get_rdtsc();
65  if (current >= cycle_until || current <= cycle_error) {
66  break;
67  }
68  }
69 }
uint64_t get_rdtsc()
Returns the current CPU cycle via x86 RDTSC.
Definition: rdtsc.hpp:35

Here is the call graph for this function:

Here is the caller graph for this function: