1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/tools/profiler/nsProfiler.cpp Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,270 @@ 1.4 +/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ 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 +#include <string> 1.10 +#include <sstream> 1.11 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP 1.12 +#include "EventTracer.h" 1.13 +#endif 1.14 +#include "GeckoProfiler.h" 1.15 +#include "nsProfiler.h" 1.16 +#include "nsMemory.h" 1.17 +#include "nsString.h" 1.18 +#include "mozilla/Services.h" 1.19 +#include "nsIObserverService.h" 1.20 +#include "nsIInterfaceRequestor.h" 1.21 +#include "nsILoadContext.h" 1.22 +#include "nsIWebNavigation.h" 1.23 +#include "nsIInterfaceRequestorUtils.h" 1.24 +#include "shared-libraries.h" 1.25 +#include "js/Value.h" 1.26 + 1.27 +using std::string; 1.28 + 1.29 +NS_IMPL_ISUPPORTS(nsProfiler, nsIProfiler) 1.30 + 1.31 +nsProfiler::nsProfiler() 1.32 + : mLockedForPrivateBrowsing(false) 1.33 +{ 1.34 +} 1.35 + 1.36 +nsProfiler::~nsProfiler() 1.37 +{ 1.38 + nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); 1.39 + if (observerService) { 1.40 + observerService->RemoveObserver(this, "chrome-document-global-created"); 1.41 + observerService->RemoveObserver(this, "last-pb-context-exited"); 1.42 + } 1.43 +} 1.44 + 1.45 +nsresult 1.46 +nsProfiler::Init() { 1.47 + nsCOMPtr<nsIObserverService> observerService = mozilla::services::GetObserverService(); 1.48 + if (observerService) { 1.49 + observerService->AddObserver(this, "chrome-document-global-created", false); 1.50 + observerService->AddObserver(this, "last-pb-context-exited", false); 1.51 + } 1.52 + return NS_OK; 1.53 +} 1.54 + 1.55 +NS_IMETHODIMP 1.56 +nsProfiler::Observe(nsISupports *aSubject, 1.57 + const char *aTopic, 1.58 + const char16_t *aData) 1.59 +{ 1.60 + if (strcmp(aTopic, "chrome-document-global-created") == 0) { 1.61 + nsCOMPtr<nsIInterfaceRequestor> requestor = do_QueryInterface(aSubject); 1.62 + nsCOMPtr<nsIWebNavigation> parentWebNav = do_GetInterface(requestor); 1.63 + nsCOMPtr<nsILoadContext> loadContext = do_QueryInterface(parentWebNav); 1.64 + if (loadContext && loadContext->UsePrivateBrowsing() && !mLockedForPrivateBrowsing) { 1.65 + mLockedForPrivateBrowsing = true; 1.66 + profiler_lock(); 1.67 + } 1.68 + } else if (strcmp(aTopic, "last-pb-context-exited") == 0) { 1.69 + mLockedForPrivateBrowsing = false; 1.70 + profiler_unlock(); 1.71 + } 1.72 + return NS_OK; 1.73 +} 1.74 + 1.75 +NS_IMETHODIMP 1.76 +nsProfiler::StartProfiler(uint32_t aEntries, double aInterval, 1.77 + const char** aFeatures, uint32_t aFeatureCount, 1.78 + const char** aThreadNameFilters, uint32_t aFilterCount) 1.79 +{ 1.80 + if (mLockedForPrivateBrowsing) { 1.81 + return NS_ERROR_NOT_AVAILABLE; 1.82 + } 1.83 + 1.84 + profiler_start(aEntries, aInterval, 1.85 + aFeatures, aFeatureCount, 1.86 + aThreadNameFilters, aFilterCount); 1.87 +#ifdef MOZ_INSTRUMENT_EVENT_LOOP 1.88 + bool printToConsole = false; 1.89 + mozilla::InitEventTracing(printToConsole); 1.90 +#endif 1.91 + return NS_OK; 1.92 +} 1.93 + 1.94 +NS_IMETHODIMP 1.95 +nsProfiler::StopProfiler() 1.96 +{ 1.97 + profiler_stop(); 1.98 + return NS_OK; 1.99 +} 1.100 + 1.101 +NS_IMETHODIMP 1.102 +nsProfiler::IsPaused(bool *aIsPaused) 1.103 +{ 1.104 + *aIsPaused = profiler_is_paused(); 1.105 + return NS_OK; 1.106 +} 1.107 + 1.108 +NS_IMETHODIMP 1.109 +nsProfiler::PauseSampling() 1.110 +{ 1.111 + profiler_pause(); 1.112 + return NS_OK; 1.113 +} 1.114 + 1.115 +NS_IMETHODIMP 1.116 +nsProfiler::ResumeSampling() 1.117 +{ 1.118 + profiler_resume(); 1.119 + return NS_OK; 1.120 +} 1.121 + 1.122 +NS_IMETHODIMP 1.123 +nsProfiler::AddMarker(const char *aMarker) 1.124 +{ 1.125 + PROFILER_MARKER(aMarker); 1.126 + return NS_OK; 1.127 +} 1.128 + 1.129 +NS_IMETHODIMP 1.130 +nsProfiler::GetProfile(char **aProfile) 1.131 +{ 1.132 + char *profile = profiler_get_profile(); 1.133 + if (profile) { 1.134 + size_t len = strlen(profile); 1.135 + char *profileStr = static_cast<char *> 1.136 + (nsMemory::Clone(profile, (len + 1) * sizeof(char))); 1.137 + profileStr[len] = '\0'; 1.138 + *aProfile = profileStr; 1.139 + free(profile); 1.140 + } 1.141 + return NS_OK; 1.142 +} 1.143 + 1.144 +static void 1.145 +AddSharedLibraryInfoToStream(std::ostream& aStream, const SharedLibrary& aLib) 1.146 +{ 1.147 + aStream << "{"; 1.148 + aStream << "\"start\":" << aLib.GetStart(); 1.149 + aStream << ",\"end\":" << aLib.GetEnd(); 1.150 + aStream << ",\"offset\":" << aLib.GetOffset(); 1.151 + aStream << ",\"name\":\"" << aLib.GetName() << "\""; 1.152 + const std::string &breakpadId = aLib.GetBreakpadId(); 1.153 + aStream << ",\"breakpadId\":\"" << breakpadId << "\""; 1.154 +#ifdef XP_WIN 1.155 + // FIXME: remove this XP_WIN code when the profiler plugin has switched to 1.156 + // using breakpadId. 1.157 + std::string pdbSignature = breakpadId.substr(0, 32); 1.158 + std::string pdbAgeStr = breakpadId.substr(32, breakpadId.size() - 1); 1.159 + 1.160 + std::stringstream stream; 1.161 + stream << pdbAgeStr; 1.162 + 1.163 + unsigned pdbAge; 1.164 + stream << std::hex; 1.165 + stream >> pdbAge; 1.166 + 1.167 +#ifdef DEBUG 1.168 + std::ostringstream oStream; 1.169 + oStream << pdbSignature << std::hex << std::uppercase << pdbAge; 1.170 + MOZ_ASSERT(breakpadId == oStream.str()); 1.171 +#endif 1.172 + 1.173 + aStream << ",\"pdbSignature\":\"" << pdbSignature << "\""; 1.174 + aStream << ",\"pdbAge\":" << pdbAge; 1.175 + aStream << ",\"pdbName\":\"" << aLib.GetName() << "\""; 1.176 +#endif 1.177 + aStream << "}"; 1.178 +} 1.179 + 1.180 +std::string 1.181 +GetSharedLibraryInfoString() 1.182 +{ 1.183 + SharedLibraryInfo info = SharedLibraryInfo::GetInfoForSelf(); 1.184 + if (info.GetSize() == 0) 1.185 + return "[]"; 1.186 + 1.187 + std::ostringstream os; 1.188 + os << "["; 1.189 + AddSharedLibraryInfoToStream(os, info.GetEntry(0)); 1.190 + 1.191 + for (size_t i = 1; i < info.GetSize(); i++) { 1.192 + os << ","; 1.193 + AddSharedLibraryInfoToStream(os, info.GetEntry(i)); 1.194 + } 1.195 + 1.196 + os << "]"; 1.197 + return os.str(); 1.198 +} 1.199 + 1.200 +NS_IMETHODIMP 1.201 +nsProfiler::GetSharedLibraryInformation(nsAString& aOutString) 1.202 +{ 1.203 + aOutString.Assign(NS_ConvertUTF8toUTF16(GetSharedLibraryInfoString().c_str())); 1.204 + return NS_OK; 1.205 +} 1.206 + 1.207 +NS_IMETHODIMP nsProfiler::GetProfileData(JSContext* aCx, 1.208 + JS::MutableHandle<JS::Value> aResult) 1.209 +{ 1.210 + JS::RootedObject obj(aCx, profiler_get_profile_jsobject(aCx)); 1.211 + if (!obj) { 1.212 + return NS_ERROR_FAILURE; 1.213 + } 1.214 + aResult.setObject(*obj); 1.215 + return NS_OK; 1.216 +} 1.217 + 1.218 +NS_IMETHODIMP 1.219 +nsProfiler::IsActive(bool *aIsActive) 1.220 +{ 1.221 + *aIsActive = profiler_is_active(); 1.222 + return NS_OK; 1.223 +} 1.224 + 1.225 +NS_IMETHODIMP 1.226 +nsProfiler::GetResponsivenessTimes(uint32_t *aCount, double **aResult) 1.227 +{ 1.228 + unsigned int len = 100; 1.229 + const double* times = profiler_get_responsiveness(); 1.230 + if (!times) { 1.231 + *aCount = 0; 1.232 + *aResult = nullptr; 1.233 + return NS_OK; 1.234 + } 1.235 + 1.236 + double *fs = static_cast<double *> 1.237 + (nsMemory::Clone(times, len * sizeof(double))); 1.238 + 1.239 + *aCount = len; 1.240 + *aResult = fs; 1.241 + 1.242 + return NS_OK; 1.243 +} 1.244 + 1.245 +NS_IMETHODIMP 1.246 +nsProfiler::GetFeatures(uint32_t *aCount, char ***aFeatures) 1.247 +{ 1.248 + uint32_t len = 0; 1.249 + 1.250 + const char **features = profiler_get_features(); 1.251 + if (!features) { 1.252 + *aCount = 0; 1.253 + *aFeatures = nullptr; 1.254 + return NS_OK; 1.255 + } 1.256 + 1.257 + while (features[len]) { 1.258 + len++; 1.259 + } 1.260 + 1.261 + char **featureList = static_cast<char **> 1.262 + (nsMemory::Alloc(len * sizeof(char*))); 1.263 + 1.264 + for (size_t i = 0; i < len; i++) { 1.265 + size_t strLen = strlen(features[i]); 1.266 + featureList[i] = static_cast<char *> 1.267 + (nsMemory::Clone(features[i], (strLen + 1) * sizeof(char))); 1.268 + } 1.269 + 1.270 + *aFeatures = featureList; 1.271 + *aCount = len; 1.272 + return NS_OK; 1.273 +}