tools/profiler/TableTicker.h

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/tools/profiler/TableTicker.h	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,224 @@
     1.4 +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#ifndef TableTicker_h
    1.10 +#define TableTicker_h
    1.11 +
    1.12 +#include "platform.h"
    1.13 +#include "ProfileEntry.h"
    1.14 +#include "mozilla/Mutex.h"
    1.15 +#include "IntelPowerGadget.h"
    1.16 +
    1.17 +static bool
    1.18 +hasFeature(const char** aFeatures, uint32_t aFeatureCount, const char* aFeature) {
    1.19 +  for(size_t i = 0; i < aFeatureCount; i++) {
    1.20 +    if (strcmp(aFeatures[i], aFeature) == 0)
    1.21 +      return true;
    1.22 +  }
    1.23 +  return false;
    1.24 +}
    1.25 +
    1.26 +static bool
    1.27 +threadSelected(ThreadInfo* aInfo, char** aThreadNameFilters, uint32_t aFeatureCount) {
    1.28 +  if (aFeatureCount == 0) {
    1.29 +    return true;
    1.30 +  }
    1.31 +
    1.32 +  for (uint32_t i = 0; i < aFeatureCount; ++i) {
    1.33 +    const char* filterPrefix = aThreadNameFilters[i];
    1.34 +    if (strncmp(aInfo->Name(), filterPrefix, strlen(filterPrefix)) == 0) {
    1.35 +      return true;
    1.36 +    }
    1.37 +  }
    1.38 +
    1.39 +  return false;
    1.40 +}
    1.41 +
    1.42 +extern TimeStamp sLastTracerEvent;
    1.43 +extern int sFrameNumber;
    1.44 +extern int sLastFrameNumber;
    1.45 +extern unsigned int sCurrentEventGeneration;
    1.46 +extern unsigned int sLastSampledEventGeneration;
    1.47 +
    1.48 +class BreakpadSampler;
    1.49 +
    1.50 +class TableTicker: public Sampler {
    1.51 + public:
    1.52 +  TableTicker(double aInterval, int aEntrySize,
    1.53 +              const char** aFeatures, uint32_t aFeatureCount,
    1.54 +              const char** aThreadNameFilters, uint32_t aFilterCount)
    1.55 +    : Sampler(aInterval, true, aEntrySize)
    1.56 +    , mPrimaryThreadProfile(nullptr)
    1.57 +    , mSaveRequested(false)
    1.58 +    , mUnwinderThread(false)
    1.59 +    , mFilterCount(aFilterCount)
    1.60 +#if defined(XP_WIN)
    1.61 +    , mIntelPowerGadget(nullptr)
    1.62 +#endif
    1.63 +  {
    1.64 +    mUseStackWalk = hasFeature(aFeatures, aFeatureCount, "stackwalk");
    1.65 +
    1.66 +    //XXX: It's probably worth splitting the jank profiler out from the regular profiler at some point
    1.67 +    mJankOnly = hasFeature(aFeatures, aFeatureCount, "jank");
    1.68 +    mProfileJS = hasFeature(aFeatures, aFeatureCount, "js");
    1.69 +    mProfileJava = hasFeature(aFeatures, aFeatureCount, "java");
    1.70 +    mProfilePower = hasFeature(aFeatures, aFeatureCount, "power");
    1.71 +    mProfileThreads = hasFeature(aFeatures, aFeatureCount, "threads");
    1.72 +    mUnwinderThread = hasFeature(aFeatures, aFeatureCount, "unwinder") || sps_version2();
    1.73 +    mAddLeafAddresses = hasFeature(aFeatures, aFeatureCount, "leaf");
    1.74 +    mPrivacyMode = hasFeature(aFeatures, aFeatureCount, "privacy");
    1.75 +    mAddMainThreadIO = hasFeature(aFeatures, aFeatureCount, "mainthreadio");
    1.76 +
    1.77 +#if defined(XP_WIN)
    1.78 +    if (mProfilePower) {
    1.79 +      mIntelPowerGadget = new IntelPowerGadget();
    1.80 +      mProfilePower = mIntelPowerGadget->Init();
    1.81 +    }
    1.82 +#endif
    1.83 +
    1.84 +    // Deep copy aThreadNameFilters
    1.85 +    mThreadNameFilters = new char*[aFilterCount];
    1.86 +    for (uint32_t i = 0; i < aFilterCount; ++i) {
    1.87 +      mThreadNameFilters[i] = strdup(aThreadNameFilters[i]);
    1.88 +    }
    1.89 +
    1.90 +    sStartTime = TimeStamp::Now();
    1.91 +
    1.92 +    {
    1.93 +      mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
    1.94 +
    1.95 +      // Create ThreadProfile for each registered thread
    1.96 +      for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
    1.97 +        ThreadInfo* info = sRegisteredThreads->at(i);
    1.98 +
    1.99 +        RegisterThread(info);
   1.100 +      }
   1.101 +
   1.102 +      SetActiveSampler(this);
   1.103 +    }
   1.104 +  }
   1.105 +
   1.106 +  ~TableTicker() {
   1.107 +    if (IsActive())
   1.108 +      Stop();
   1.109 +
   1.110 +    SetActiveSampler(nullptr);
   1.111 +
   1.112 +    // Destroy ThreadProfile for all threads
   1.113 +    {
   1.114 +      mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
   1.115 +
   1.116 +      for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
   1.117 +        ThreadInfo* info = sRegisteredThreads->at(i);
   1.118 +        ThreadProfile* profile = info->Profile();
   1.119 +        if (profile) {
   1.120 +          delete profile;
   1.121 +          info->SetProfile(nullptr);
   1.122 +        }
   1.123 +      }
   1.124 +    }
   1.125 +#if defined(XP_WIN)
   1.126 +    delete mIntelPowerGadget;
   1.127 +#endif
   1.128 +  }
   1.129 +
   1.130 +  void RegisterThread(ThreadInfo* aInfo) {
   1.131 +    if (!aInfo->IsMainThread() && !mProfileThreads) {
   1.132 +      return;
   1.133 +    }
   1.134 +
   1.135 +    if (!threadSelected(aInfo, mThreadNameFilters, mFilterCount)) {
   1.136 +      return;
   1.137 +    }
   1.138 +
   1.139 +    ThreadProfile* profile = new ThreadProfile(aInfo->Name(),
   1.140 +                                               EntrySize(),
   1.141 +                                               aInfo->Stack(),
   1.142 +                                               aInfo->ThreadId(),
   1.143 +                                               aInfo->GetPlatformData(),
   1.144 +                                               aInfo->IsMainThread(),
   1.145 +                                               aInfo->StackTop());
   1.146 +    aInfo->SetProfile(profile);
   1.147 +  }
   1.148 +
   1.149 +  // Called within a signal. This function must be reentrant
   1.150 +  virtual void Tick(TickSample* sample);
   1.151 +
   1.152 +  // Immediately captures the calling thread's call stack and returns it.
   1.153 +  virtual SyncProfile* GetBacktrace();
   1.154 +
   1.155 +  // Called within a signal. This function must be reentrant
   1.156 +  virtual void RequestSave()
   1.157 +  {
   1.158 +    mSaveRequested = true;
   1.159 +  }
   1.160 +
   1.161 +  virtual void HandleSaveRequest();
   1.162 +
   1.163 +  ThreadProfile* GetPrimaryThreadProfile()
   1.164 +  {
   1.165 +    if (!mPrimaryThreadProfile) {
   1.166 +      mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
   1.167 +
   1.168 +      for (uint32_t i = 0; i < sRegisteredThreads->size(); i++) {
   1.169 +        ThreadInfo* info = sRegisteredThreads->at(i);
   1.170 +        if (info->IsMainThread()) {
   1.171 +          mPrimaryThreadProfile = info->Profile();
   1.172 +          break;
   1.173 +        }
   1.174 +      }
   1.175 +    }
   1.176 +
   1.177 +    return mPrimaryThreadProfile;
   1.178 +  }
   1.179 +
   1.180 +  void ToStreamAsJSON(std::ostream& stream);
   1.181 +  virtual JSObject *ToJSObject(JSContext *aCx);
   1.182 +  void StreamMetaJSCustomObject(JSStreamWriter& b);
   1.183 +  bool HasUnwinderThread() const { return mUnwinderThread; }
   1.184 +  bool ProfileJS() const { return mProfileJS; }
   1.185 +  bool ProfileJava() const { return mProfileJava; }
   1.186 +  bool ProfilePower() const { return mProfilePower; }
   1.187 +  bool ProfileThreads() const { return mProfileThreads; }
   1.188 +  bool InPrivacyMode() const { return mPrivacyMode; }
   1.189 +  bool AddMainThreadIO() const { return mAddMainThreadIO; }
   1.190 +
   1.191 +protected:
   1.192 +  // Called within a signal. This function must be reentrant
   1.193 +  virtual void UnwinderTick(TickSample* sample);
   1.194 +
   1.195 +  // Called within a signal. This function must be reentrant
   1.196 +  virtual void InplaceTick(TickSample* sample);
   1.197 +
   1.198 +  // Not implemented on platforms which do not support backtracing
   1.199 +  void doNativeBacktrace(ThreadProfile &aProfile, TickSample* aSample);
   1.200 +
   1.201 +  void StreamJSObject(JSStreamWriter& b);
   1.202 +
   1.203 +  // This represent the application's main thread (SAMPLER_INIT)
   1.204 +  ThreadProfile* mPrimaryThreadProfile;
   1.205 +  bool mSaveRequested;
   1.206 +  bool mAddLeafAddresses;
   1.207 +  bool mUseStackWalk;
   1.208 +  bool mJankOnly;
   1.209 +  bool mProfileJS;
   1.210 +  bool mProfileThreads;
   1.211 +  bool mUnwinderThread;
   1.212 +  bool mProfileJava;
   1.213 +  bool mProfilePower;
   1.214 +
   1.215 +  // Keep the thread filter to check against new thread that
   1.216 +  // are started while profiling
   1.217 +  char** mThreadNameFilters;
   1.218 +  uint32_t mFilterCount;
   1.219 +  bool mPrivacyMode;
   1.220 +  bool mAddMainThreadIO;
   1.221 +#if defined(XP_WIN)
   1.222 +  IntelPowerGadget* mIntelPowerGadget;
   1.223 +#endif
   1.224 +};
   1.225 +
   1.226 +#endif
   1.227 +

mercurial