1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 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 /** 8 * IOInterposeObserver recording statistics of main-thread I/O during execution, 9 * aimed at consumption by TelemetryImpl 10 */ 11 12 #ifndef TelemetryIOInterposeObserver_h__ 13 #define TelemetryIOInterposeObserver_h__ 14 15 #include "core/TelemetryCommon.h" 16 #include "jsapi.h" 17 #include "mozilla/IOInterposer.h" 18 #include "nsBaseHashtable.h" 19 #include "nsClassHashtable.h" 20 #include "nsHashKeys.h" 21 #include "nsTArray.h" 22 #include "nsTHashtable.h" 23 24 namespace mozilla { 25 namespace Telemetry { 26 27 class TelemetryIOInterposeObserver : public IOInterposeObserver { 28 /** File-level statistics structure */ 29 struct FileStats { FileStatsFileStats30 FileStats() 31 : creates(0), reads(0), writes(0), fsyncs(0), stats(0), totalTime(0) {} 32 uint32_t creates; /** Number of create/open operations */ 33 uint32_t reads; /** Number of read operations */ 34 uint32_t writes; /** Number of write operations */ 35 uint32_t fsyncs; /** Number of fsync operations */ 36 uint32_t stats; /** Number of stat operations */ 37 double totalTime; /** Accumulated duration of all operations */ 38 }; 39 40 struct SafeDir { SafeDirSafeDir41 SafeDir(const nsAString& aPath, const nsAString& aSubstName) 42 : mPath(aPath), mSubstName(aSubstName) {} SizeOfExcludingThisSafeDir43 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const { 44 return mPath.SizeOfExcludingThisIfUnshared(aMallocSizeOf) + 45 mSubstName.SizeOfExcludingThisIfUnshared(aMallocSizeOf); 46 } 47 nsString mPath; /** Path to the directory */ 48 nsString mSubstName; /** Name to substitute with */ 49 }; 50 51 public: 52 explicit TelemetryIOInterposeObserver(nsIFile* aXreDir); 53 54 /** 55 * An implementation of Observe that records statistics of all 56 * file IO operations. 57 */ 58 void Observe(Observation& aOb) override; 59 60 /** 61 * Reflect recorded file IO statistics into Javascript 62 */ 63 bool ReflectIntoJS(JSContext* cx, JS::Handle<JSObject*> rootObj); 64 65 /** 66 * Adds a path for inclusion in main thread I/O report. 67 * @param aPath Directory path 68 * @param aSubstName Name to substitute for aPath for privacy reasons 69 */ 70 void AddPath(const nsAString& aPath, const nsAString& aSubstName); 71 72 /** 73 * Get size of hash table with file stats 74 */ 75 size_t SizeOfIncludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 76 77 size_t SizeOfExcludingThis(mozilla::MallocSizeOf aMallocSizeOf) const; 78 79 private: 80 enum Stage { STAGE_STARTUP = 0, STAGE_NORMAL, STAGE_SHUTDOWN, NUM_STAGES }; NextStage(Stage aStage)81 static inline Stage NextStage(Stage aStage) { 82 switch (aStage) { 83 case STAGE_STARTUP: 84 return STAGE_NORMAL; 85 case STAGE_NORMAL: 86 return STAGE_SHUTDOWN; 87 case STAGE_SHUTDOWN: 88 return STAGE_SHUTDOWN; 89 default: 90 return NUM_STAGES; 91 } 92 } 93 94 struct FileStatsByStage { 95 FileStats mStats[NUM_STAGES]; 96 }; 97 typedef nsBaseHashtableET<nsStringHashKey, FileStatsByStage> FileIOEntryType; 98 99 // Statistics for each filename 100 Common::AutoHashtable<FileIOEntryType> mFileStats; 101 // Container for allowed directories 102 nsTArray<SafeDir> mSafeDirs; 103 Stage mCurStage; 104 105 /** 106 * Reflect a FileIOEntryType object to a Javascript property on obj with 107 * filename as key containing array: 108 * [totalTime, creates, reads, writes, fsyncs, stats] 109 */ 110 static bool ReflectFileStats(FileIOEntryType* entry, JSContext* cx, 111 JS::Handle<JSObject*> obj); 112 }; 113 114 } // namespace Telemetry 115 } // namespace mozilla 116 117 #endif // TelemetryIOInterposeObserver_h__ 118