LCOV - code coverage report
Current view: top level - js/src/vm - TraceLoggingGraph.h (source / functions) Hit Total Coverage
Test: output.info Lines: 0 48 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
       2             :  * vim: set ts=8 sts=4 et sw=4 tw=99:
       3             :  * This Source Code Form is subject to the terms of the Mozilla Public
       4             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       5             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #ifndef TraceLoggingGraph_h
       8             : #define TraceLoggingGraph_h
       9             : 
      10             : #include "mozilla/MemoryReporting.h"
      11             : 
      12             : #include "js/TypeDecls.h"
      13             : #include "vm/MutexIDs.h"
      14             : #include "vm/TraceLoggingTypes.h"
      15             : 
      16             : /*
      17             :  * The output of a tracelogging session is saved in /tmp/tl-data.json.
      18             :  * The format of that file is a JS array per tracelogger (=thread), with a map
      19             :  * containing:
      20             :  *  - dict:   Name of the file containing a json table with the log text.
      21             :  *            All other files only contain a index to this table when logging.
      22             :  *  - events: Name of the file containing a flat list of log events saved
      23             :  *            in binary format.
      24             :  *            (64bit: Time Stamp Counter, 32bit index to dict)
      25             :  *  - tree:   Name of the file containing the events with duration. The content
      26             :  *            is already in a tree data structure. This is also saved in a
      27             :  *            binary file.
      28             :  *  - treeFormat: The format used to encode the tree. By default "64,64,31,1,32".
      29             :  *                There are currently no other formats to save the tree.
      30             :  *     - 64,64,31,1,32 signifies how many bytes are used for the different
      31             :  *       parts of the tree.
      32             :  *       => 64 bits: Time Stamp Counter of start of event.
      33             :  *       => 64 bits: Time Stamp Counter of end of event.
      34             :  *       => 31 bits: Index to dict file containing the log text.
      35             :  *       =>  1 bit:  Boolean signifying if this entry has children.
      36             :  *                   When true, the child can be found just right after this entry.
      37             :  *       => 32 bits: Containing the ID of the next event on the same depth
      38             :  *                   or 0 if there isn't an event on the same depth anymore.
      39             :  *
      40             :  *        /-> The position in the file. Id is this divided by size of entry.
      41             :  *        |   So in this case this would be 1 (192bits per entry).
      42             :  *        |                              /-> Indicates there are children. The
      43             :  *        |                              |   first child is located at current
      44             :  *        |                              |   ID + 1. So 1 + 1 in this case: 2.
      45             :  *        |                              |   Or 0x00180 in the tree file.
      46             :  *        |                              | /-> Next event on the same depth is
      47             :  *        |                              | |    located at 4. So 0x00300 in the
      48             :  *        |                              | |    tree file.
      49             :  *       0x0000C0: [start, end, dictId, 1, 4]
      50             :  *
      51             :  *
      52             :  *       Example:
      53             :  *                          0x0: [start, end, dictId, 1, 0]
      54             :  *                                        |
      55             :  *                      /----------------------------------\
      56             :  *                      |                                  |
      57             :  *       0xC0: [start, end, dictId, 0, 2]      0x180 [start, end, dictId, 1, 0]
      58             :  *                                                      |
      59             :  *                                  /----------------------------------\
      60             :  *                                  |                                  |
      61             :  *         0x240: [start, end, dictId, 0, 4]    0x300 [start, end, dictId, 0, 0]
      62             :  */
      63             : 
      64             : namespace js {
      65             : void DestroyTraceLoggerGraphState();
      66             : size_t SizeOfTraceLogGraphState(mozilla::MallocSizeOf mallocSizeOf);
      67             : } // namespace js
      68             : 
      69             : class TraceLoggerGraphState
      70             : {
      71             :     uint32_t numLoggers;
      72             :     uint32_t pid_;
      73             : 
      74             :     // File pointer to the "tl-data.json" file. (Explained above).
      75             :     FILE* out;
      76             : 
      77             : #ifdef DEBUG
      78             :     bool initialized;
      79             : #endif
      80             : 
      81             :   public:
      82             :     js::Mutex lock;
      83             : 
      84             :   public:
      85           0 :     TraceLoggerGraphState()
      86           0 :       : numLoggers(0)
      87             :       , pid_(0)
      88             :       , out(nullptr)
      89             : #ifdef DEBUG
      90             :       , initialized(false)
      91             : #endif
      92           0 :       , lock(js::mutexid::TraceLoggerGraphState)
      93           0 :     {}
      94             : 
      95             :     bool init();
      96             :     ~TraceLoggerGraphState();
      97             : 
      98             :     uint32_t nextLoggerId();
      99           0 :     uint32_t pid() { return pid_; }
     100             : 
     101             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     102           0 :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const {
     103           0 :         return mallocSizeOf(this) + sizeOfExcludingThis(mallocSizeOf);
     104             :     }
     105             : };
     106             : 
     107             : class TraceLoggerGraph
     108             : {
     109             :     // The layout of the tree in memory and in the log file. Readable by JS
     110             :     // using TypedArrays.
     111             :     struct TreeEntry {
     112             :         uint64_t start_;
     113             :         uint64_t stop_;
     114             :         union {
     115             :             struct {
     116             :                 uint32_t textId_: 31;
     117             :                 uint32_t hasChildren_: 1;
     118             :             } s;
     119             :             uint32_t value_;
     120             :         } u;
     121             :         uint32_t nextId_;
     122             : 
     123             :         TreeEntry(uint64_t start, uint64_t stop, uint32_t textId, bool hasChildren,
     124             :                   uint32_t nextId)
     125             :         {
     126             :             start_ = start;
     127             :             stop_ = stop;
     128             :             u.s.textId_ = textId;
     129             :             u.s.hasChildren_ = hasChildren;
     130             :             nextId_ = nextId;
     131             :         }
     132           0 :         TreeEntry()
     133           0 :         { }
     134             :         uint64_t start() {
     135             :             return start_;
     136             :         }
     137             :         uint64_t stop() {
     138             :             return stop_;
     139             :         }
     140           0 :         uint32_t textId() {
     141           0 :             return u.s.textId_;
     142             :         }
     143           0 :         bool hasChildren() {
     144           0 :             return u.s.hasChildren_;
     145             :         }
     146             :         uint32_t nextId() {
     147             :             return nextId_;
     148             :         }
     149           0 :         void setStart(uint64_t start) {
     150           0 :             start_ = start;
     151           0 :         }
     152           0 :         void setStop(uint64_t stop) {
     153           0 :             stop_ = stop;
     154           0 :         }
     155           0 :         void setTextId(uint32_t textId) {
     156           0 :             MOZ_ASSERT(textId < uint32_t(1 << 31));
     157           0 :             u.s.textId_ = textId;
     158           0 :         }
     159           0 :         void setHasChildren(bool hasChildren) {
     160           0 :             u.s.hasChildren_ = hasChildren;
     161           0 :         }
     162           0 :         void setNextId(uint32_t nextId) {
     163           0 :             nextId_ = nextId;
     164           0 :         }
     165             :     };
     166             : 
     167             :     // Helper structure for keeping track of the current entries in
     168             :     // the tree. Pushed by `start(id)`, popped by `stop(id)`. The active flag
     169             :     // is used to know if a subtree doesn't need to get logged.
     170             :     struct StackEntry {
     171             :         uint32_t treeId_;
     172             :         uint32_t lastChildId_;
     173             :         struct {
     174             :             uint32_t textId_: 31;
     175             :             uint32_t active_: 1;
     176             :         } s;
     177             :         StackEntry(uint32_t treeId, uint32_t lastChildId, bool active = true)
     178             :           : treeId_(treeId), lastChildId_(lastChildId)
     179             :         {
     180             :             s.textId_ = 0;
     181             :             s.active_ = active;
     182             :         }
     183           0 :         uint32_t treeId() {
     184           0 :             return treeId_;
     185             :         }
     186           0 :         uint32_t lastChildId() {
     187           0 :             return lastChildId_;
     188             :         }
     189             :         uint32_t textId() {
     190             :             return s.textId_;
     191             :         }
     192           0 :         bool active() {
     193           0 :             return s.active_;
     194             :         }
     195           0 :         void setTreeId(uint32_t treeId) {
     196           0 :             treeId_ = treeId;
     197           0 :         }
     198           0 :         void setLastChildId(uint32_t lastChildId) {
     199           0 :             lastChildId_ = lastChildId;
     200           0 :         }
     201             :         void setTextId(uint32_t textId) {
     202             :             MOZ_ASSERT(textId < uint32_t(1<<31));
     203             :             s.textId_ = textId;
     204             :         }
     205           0 :         void setActive(bool active) {
     206           0 :             s.active_ = active;
     207           0 :         }
     208             :     };
     209             : 
     210             :   public:
     211           0 :     TraceLoggerGraph() {}
     212             :     ~TraceLoggerGraph();
     213             : 
     214             :     bool init(uint64_t timestamp);
     215             : 
     216             :     // Link a textId with a particular text.
     217             :     void addTextId(uint32_t id, const char* text);
     218             : 
     219             :     // Create a tree out of all the given events.
     220             :     void log(ContinuousSpace<EventEntry>& events);
     221             : 
     222           0 :     static size_t treeSizeFlushLimit() {
     223             :         // Allow tree size to grow to 100MB.
     224           0 :         return 100 * 1024 * 1024 / sizeof(TreeEntry);
     225             :     }
     226             : 
     227           0 :     uint32_t nextTextId() { return nextTextId_; }
     228             : 
     229             :     size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     230             :     size_t sizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf) const;
     231             : 
     232             :   private:
     233             :     bool failed = false;
     234             :     bool enabled = false;
     235             :     uint32_t nextTextId_ = 0;
     236             : 
     237             :     FILE* dictFile = nullptr;
     238             :     FILE* treeFile = nullptr;
     239             :     FILE* eventFile = nullptr;
     240             : 
     241             :     ContinuousSpace<TreeEntry> tree;
     242             :     ContinuousSpace<StackEntry> stack;
     243             :     uint32_t treeOffset = 0;
     244             : 
     245             :     // Helper functions that convert a TreeEntry in different endianness
     246             :     // in place.
     247             :     void entryToBigEndian(TreeEntry* entry);
     248             :     void entryToSystemEndian(TreeEntry* entry);
     249             : 
     250             :     // Helper functions to get/save a tree from file.
     251             :     bool getTreeEntry(uint32_t treeId, TreeEntry* entry);
     252             :     bool saveTreeEntry(uint32_t treeId, TreeEntry* entry);
     253             : 
     254             :     // Return the first StackEntry that is active.
     255             :     StackEntry& getActiveAncestor();
     256             : 
     257             :     // This contains the meat of startEvent, except the test for enough space,
     258             :     // the test if tracelogger is enabled and the timestamp computation.
     259             :     void startEvent(uint32_t id, uint64_t timestamp);
     260             :     bool startEventInternal(uint32_t id, uint64_t timestamp);
     261             : 
     262             :     // Update functions that can adjust the items in the tree,
     263             :     // both in memory or already written to disk.
     264             :     bool updateHasChildren(uint32_t treeId, bool hasChildren = true);
     265             :     bool updateNextId(uint32_t treeId, uint32_t nextId);
     266             :     bool updateStop(uint32_t treeId, uint64_t timestamp);
     267             : 
     268             :     // Flush the tree.
     269             :     bool flush();
     270             : 
     271             :     // Stop a tree event.
     272             :     void stopEvent(uint32_t id, uint64_t timestamp);
     273             :     void stopEvent(uint64_t timestamp);
     274             : 
     275             :     // Log an (non-tree) event.
     276             :     void logTimestamp(uint32_t id, uint64_t timestamp);
     277             : 
     278             :     // Disable logging and forcefully report all not yet stopped tree events
     279             :     // as stopped.
     280             :     void disable(uint64_t timestamp);
     281             : };
     282             : 
     283             : #endif /* TraceLoggingGraph_h */

Generated by: LCOV version 1.13