Coverage for /Syzygy/agent/asan/stack_capture_cache.h

CoverageLines executed / instrumented / missingexe / inst / missLanguageGroup
100.0%16160.C++source

Line-by-line coverage:

   1    :  // Copyright 2012 Google Inc. All Rights Reserved.
   2    :  //
   3    :  // Licensed under the Apache License, Version 2.0 (the "License");
   4    :  // you may not use this file except in compliance with the License.
   5    :  // You may obtain a copy of the License at
   6    :  //
   7    :  //     http://www.apache.org/licenses/LICENSE-2.0
   8    :  //
   9    :  // Unless required by applicable law or agreed to in writing, software
  10    :  // distributed under the License is distributed on an "AS IS" BASIS,
  11    :  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12    :  // See the License for the specific language governing permissions and
  13    :  // limitations under the License.
  14    :  
  15    :  #ifndef SYZYGY_AGENT_ASAN_STACK_CAPTURE_CACHE_H_
  16    :  #define SYZYGY_AGENT_ASAN_STACK_CAPTURE_CACHE_H_
  17    :  
  18    :  #include "base/hash_tables.h"
  19    :  #include "base/synchronization/lock.h"
  20    :  #include "syzygy/agent/asan/stack_capture.h"
  21    :  
  22    :  namespace agent {
  23    :  namespace asan {
  24    :  
  25    :  // Forward declaration.
  26    :  class AsanLogger;
  27    :  class StackCapture;
  28    :  
  29    :  // A class which manages a thread-safe cache of unique stack traces, by ID.
  30    :  class StackCaptureCache {
  31    :   public:
  32    :    // The size of a page of stack captures, in bytes. This should be in the
  33    :    // hundreds of KB or low MBs so that we have an efficient pooled allocator
  34    :    // that can store hundreds to thousands of stack captures, yet whose
  35    :    // incremental growth is not too large.
  36    :    static const size_t kCachePageSize = 1024 * 1024;
  37    :  
  38    :    // The type used to uniquely identify a stack.
  39    :    typedef StackCapture::StackId StackId;
  40    :  
  41    :    // Forward declaration.
  42    :    class CachePage;
  43    :  
  44    :    // TODO(chrisha): Plumb a command-line parameter through to control the
  45    :    //     max depth of stack traces in the StackCaptureCache. This should get us
  46    :    //     significant memory savings in the stack trace cache.
  47    :  
  48    :    // Initializes a new stack capture cache.
  49    :    // @param logger The logger to use.
  50    :    // @param max_num_frames The maximum number of frames to be used by the
  51    :    //     StackCapture objects in this cache.
  52    :    explicit StackCaptureCache(AsanLogger* logger);
  53    :    StackCaptureCache(AsanLogger* logger, size_t max_num_frames);
  54    :  
  55    :    // Destroys a stack capture cache.
  56    :    ~StackCaptureCache();
  57    :  
  58    :    // @returns the current maximum number of frames supported by saved stack
  59    :    //     traces.
  60  E :    size_t max_num_frames() const { return max_num_frames_; }
  61    :  
  62    :    // Sets the current maximum number of frames supported by saved stack traces.
  63    :    // @param max_num_frames The maximum number of frames to set.
  64  E :    void set_max_num_frames(size_t max_num_frames) {
  65  E :      max_num_frames_ = max_num_frames;
  66  E :    }
  67    :  
  68    :    // @returns the default compression reporting period value.
  69  E :    static size_t GetDefaultCompressionReportingPeriod() {
  70  E :      return kDefaultCompressionReportingPeriod;
  71  E :    }
  72    :  
  73    :    // Sets a new (global) compression reporting period value. Note that this
  74    :    // method is not thread safe. It is expected to be called once at startup,
  75    :    // or not at all.
  76  E :    static void set_compression_reporting_period(size_t period) {
  77  E :      compression_reporting_period_ = period;
  78  E :    }
  79    :  
  80    :    // @returns the current (global) compression reporting period value. It is
  81    :    //     expected that this value is a constant after initialization.
  82  E :    static size_t compression_reporting_period() {
  83  E :      return compression_reporting_period_;
  84  E :    }
  85    :  
  86    :    // Save (or retrieve) the stack capture (the first @p num_frames elements
  87    :    // from  @p frames) into the cache using @p stack_id as the key.
  88    :    // @param stack_id a unique identifier for this stack trace. It is expected
  89    :    //     that identical stack traces will have the same @p stack_id.
  90    :    // @param frames an array of stack frame pointers.
  91    :    // @param num_frames the number of valid elements in @p frames. Note that
  92    :    //     at most StackCapture::kMaxNumFrames will be saved.
  93    :    // @param stack_capture The initialized stack capture to save.
  94    :    // @returns a pointer to the saved stack capture.
  95    :    const StackCapture* SaveStackTrace(StackId stack_id,
  96    :                                       const void* const* frames,
  97    :                                       size_t num_frames);
  98    :    const StackCapture* SaveStackTrace(const StackCapture& stack_capture);
  99    :  
 100    :    // Logs the current stack capture cache compression ratio. This method is
 101    :    // thread safe.
 102    :    void LogCompressionRatio() const;
 103    :  
 104    :   protected:
 105    :    // The container type in which we store the cached stacks. This enforces
 106    :    // uniqueness based on their hash value, nothing more.
 107    :    typedef base::hash_set<const StackCapture*,
 108    :                           StackCapture::HashCompare> StackSet;
 109    :  
 110    :    // @returns The compression ratio achieved by the stack capture cache. This
 111    :    //     is the percentage of total allocation stack traces actually stored in
 112    :    //     the cache. This method must be called while holding lock_.
 113    :    double GetCompressionRatioUnlocked() const;
 114    :  
 115    :    // Implementation function for logging the compression ratio.
 116    :    void LogCompressionRatioImpl(double ratio) const;
 117    :  
 118    :    // The default number of iterations between each compression ratio report.
 119    :    // Zero (0) means do not report.
 120    :    static const size_t kDefaultCompressionReportingPeriod = 0;
 121    :  
 122    :    // The number of allocations between reports of the stack trace cache
 123    :    // compression ratio. Zero (0) means do not report. Values like 1 million
 124    :    // seem to be pretty good with Chrome.
 125    :    static size_t compression_reporting_period_;
 126    :  
 127    :    // Logger instance to which to report the compression ratio.
 128    :    AsanLogger* const logger_;
 129    :  
 130    :    // A lock to protect the known stacks set from concurrent access.
 131    :    mutable base::Lock lock_;
 132    :  
 133    :    // The max depth of the stack traces to allocate. This can change, but it
 134    :    // doesn't really make sense to do so.
 135    :    size_t max_num_frames_;
 136    :  
 137    :    // The set of known stacks. Accessed under lock_.
 138    :    StackSet known_stacks_;
 139    :  
 140    :    // The current page from which new stack captures are allocated.
 141    :    // Accessed under lock_.
 142    :    CachePage* current_page_;
 143    :  
 144    :    // The total number of stack allocations requested. Accessed under lock_.
 145    :    uint64 total_allocations_;
 146    :  
 147    :    // The total number of stack allocations requested. Accessed under lock_.
 148    :    uint64 cached_allocations_;
 149    :  
 150    :   private:
 151    :    DISALLOW_COPY_AND_ASSIGN(StackCaptureCache);
 152    :  };
 153    :  
 154    :  // A page of preallocated stack trace capture objects to be populated
 155    :  // and stored in the known stacks cache set.
 156    :  class StackCaptureCache::CachePage {
 157    :   public:
 158  E :    explicit CachePage(CachePage* link) : next_page_(link), bytes_used_(0) {
 159  E :    }
 160    :  
 161    :    ~CachePage();
 162    :  
 163    :    // Allocates a stack capture from this cache page if possible.
 164    :    // @param max_num_frames The maximum number of frames the object needs to be
 165    :    //     able to store.
 166    :    // @returns a new StackCapture, or NULL if the page is full.
 167    :    StackCapture* GetNextStackCapture(size_t max_num_frames);
 168    :  
 169    :    // Releases the most recently allocated stack capture back to the page.
 170    :    // @param stack_capture The stack capture to return. This must be the most
 171    :    //     recently allocated capture as returned by GetNextStackCapture.
 172    :    void ReleaseStackCapture(StackCapture* stack_capture);
 173    :  
 174    :    // @returns the number of bytes used in this page. This is mainly a hook
 175    :    //     for unittesting.
 176  E :    size_t bytes_used() const { return bytes_used_; }
 177    :  
 178    :   protected:
 179    :    // The cache pages from a linked list, which allows for easy cleanup
 180    :    // when the cache is destroyed.
 181    :    CachePage* next_page_;
 182    :  
 183    :    // The number of bytes used, also equal to the byte offset of the next
 184    :    // StackCapture object to be allocated.
 185    :    size_t bytes_used_;
 186    :  
 187    :    // A page's worth of data, which will be allocated as StackCapture objects.
 188    :    uint8 data_[kCachePageSize];
 189    :  
 190    :   private:
 191    :    DISALLOW_COPY_AND_ASSIGN(CachePage);
 192    :  };
 193    :  
 194    :  }  // namespace asan
 195    :  }  // namespace agent
 196    :  
 197    :  #endif  // SYZYGY_AGENT_ASAN_STACK_CAPTURE_CACHE_H_

Coverage information generated Thu Mar 14 11:53:36 2013.