Bug 815709 - Shutdown time is read in the main thread. r=ehsan.

Move code to Telemetry.cpp and s/NULL/nullptr/.
This commit is contained in:
Rafael Ávila de Espíndola 2012-12-13 12:06:27 -05:00
parent 522c85f0af
commit 976680c34c
7 changed files with 138 additions and 133 deletions

View File

@ -40,6 +40,7 @@ NS_VISIBILITY_DEFAULT __attribute__((weak));
namespace mozilla {
void RecordShutdownEndTimeStamp();
void RecordShutdownStartTimeStamp();
class StartupTimeline {
public:

View File

@ -163,9 +163,7 @@ nsAppStartup::nsAppStartup() :
mRestart(false),
mInterrupted(false),
mIsSafeModeNecessary(false),
mStartupCrashTrackingEnded(false),
mCachedShutdownTime(false),
mLastShutdownTime(0)
mStartupCrashTrackingEnded(false)
{ }
@ -296,83 +294,7 @@ nsAppStartup::Run(void)
return mRestart ? NS_SUCCESS_RESTART_APP : NS_OK;
}
static TimeStamp gRecordedShutdownStartTime;
static bool gAlreadyFreedShutdownTimeFileName = false;
static char *gRecordedShutdownTimeFileName = NULL;
static char *
GetShutdownTimeFileName()
{
if (gAlreadyFreedShutdownTimeFileName) {
return NULL;
}
if (!gRecordedShutdownTimeFileName) {
nsCOMPtr<nsIFile> mozFile;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
if (!mozFile)
return NULL;
mozFile->AppendNative(NS_LITERAL_CSTRING("Telemetry.ShutdownTime.txt"));
nsAutoCString nativePath;
nsresult rv = mozFile->GetNativePath(nativePath);
if (!NS_SUCCEEDED(rv))
return NULL;
gRecordedShutdownTimeFileName = PL_strdup(nativePath.get());
}
return gRecordedShutdownTimeFileName;
}
static void
RecordShutdownStartTimeStamp() {
if (!Telemetry::CanRecord())
return;
gRecordedShutdownStartTime = TimeStamp::Now();
GetShutdownTimeFileName();
}
namespace mozilla {
void
RecordShutdownEndTimeStamp() {
if (!gRecordedShutdownTimeFileName || gAlreadyFreedShutdownTimeFileName)
return;
nsCString name(gRecordedShutdownTimeFileName);
PL_strfree(gRecordedShutdownTimeFileName);
gRecordedShutdownTimeFileName = NULL;
gAlreadyFreedShutdownTimeFileName = true;
nsCString tmpName = name;
tmpName += ".tmp";
FILE *f = fopen(tmpName.get(), "w");
if (!f)
return;
// On a normal release build this should be called just before
// calling _exit, but on a debug build or when the user forces a full
// shutdown this is called as late as possible, so we have to
// white list this write as write poisoning will be enabled.
int fd = fileno(f);
MozillaRegisterDebugFD(fd);
TimeStamp now = TimeStamp::Now();
MOZ_ASSERT(now >= gRecordedShutdownStartTime);
TimeDuration diff = now - gRecordedShutdownStartTime;
uint32_t diff2 = diff.ToMilliseconds();
int written = fprintf(f, "%d\n", diff2);
MozillaUnRegisterDebugFILE(f);
int rv = fclose(f);
if (written < 0 || rv != 0) {
PR_Delete(tmpName.get());
return;
}
PR_Delete(name.get());
PR_Rename(tmpName.get(), name.get());
}
}
NS_IMETHODIMP
nsAppStartup::Quit(uint32_t aMode)
@ -389,7 +311,7 @@ nsAppStartup::Quit(uint32_t aMode)
return NS_OK;
SAMPLE_MARKER("Shutdown start");
RecordShutdownStartTimeStamp();
mozilla::RecordShutdownStartTimeStamp();
// If we're considering quitting, we will only do so if:
if (ferocity == eConsiderQuit) {
@ -588,47 +510,6 @@ nsAppStartup::ExitLastWindowClosingSurvivalArea(void)
return NS_OK;
}
NS_IMETHODIMP
nsAppStartup::GetLastShutdownDuration(uint32_t *aResult)
{
// We make this check so that GetShutdownTimeFileName() doesn't get
// called; calling that function without telemetry enabled violates
// assumptions that the write-the-shutdown-timestamp machinery makes.
if (!Telemetry::CanRecord()) {
*aResult = 0;
return NS_OK;
}
if (!mCachedShutdownTime) {
const char *filename = GetShutdownTimeFileName();
if (!filename) {
*aResult = 0;
return NS_OK;
}
FILE *f = fopen(filename, "r");
if (!f) {
*aResult = 0;
return NS_OK;
}
int shutdownTime;
int r = fscanf(f, "%d\n", &shutdownTime);
fclose(f);
if (r != 1) {
*aResult = 0;
return NS_OK;
}
mLastShutdownTime = shutdownTime;
mCachedShutdownTime = true;
}
*aResult = mLastShutdownTime;
return NS_OK;
}
//
// nsAppStartup->nsIAppStartup2
//

View File

@ -61,8 +61,6 @@ private:
bool mInterrupted; // Was startup interrupted by an interactive prompt?
bool mIsSafeModeNecessary; // Whether safe mode is necessary
bool mStartupCrashTrackingEnded; // Whether startup crash tracking has already ended
bool mCachedShutdownTime;
uint32_t mLastShutdownTime;
#if defined(XP_WIN)
//Interaction with OS-provided profiling probes

View File

@ -7,7 +7,7 @@
interface nsICmdLineService;
[scriptable, uuid(5016bc45-54d9-4f97-935c-df4cef4b999f)]
[scriptable, uuid(2b51b67f-6f05-4145-b37e-7369bbc92b19)]
interface nsIAppStartup : nsISupports
{
/**
@ -42,12 +42,6 @@ interface nsIAppStartup : nsISupports
void enterLastWindowClosingSurvivalArea();
void exitLastWindowClosingSurvivalArea();
/**
* The amount of time, in milliseconds, that the last session took
* to shutdown. Reads as 0 to indicate failure.
*/
readonly attribute uint32_t lastShutdownDuration;
/**
* Startup Crash Detection
*

View File

@ -24,12 +24,15 @@
#include "nsBaseHashtable.h"
#include "nsXULAppAPI.h"
#include "nsThreadUtils.h"
#include "plstr.h"
#include "nsAppDirectoryServiceDefs.h"
#include "mozilla/ProcessedStack.h"
#include "mozilla/Mutex.h"
#include "mozilla/FileUtils.h"
#include "mozilla/Preferences.h"
#include "mozilla/Attributes.h"
#include "mozilla/Likely.h"
#include "mozilla/mozPoisonWrite.h"
namespace {
@ -313,6 +316,9 @@ private:
HangReports mHangReports;
Mutex mHangReportsMutex;
nsIMemoryReporter *mMemoryReporter;
bool mCachedShutdownTime;
uint32_t mLastShutdownTime;
};
TelemetryImpl* TelemetryImpl::sTelemetry = NULL;
@ -680,11 +686,83 @@ WrapAndReturnHistogram(Histogram *h, JSContext *cx, jsval *ret)
return NS_OK;
}
static TimeStamp gRecordedShutdownStartTime;
static bool gAlreadyFreedShutdownTimeFileName = false;
static char *gRecordedShutdownTimeFileName = nullptr;
static char *
GetShutdownTimeFileName()
{
if (gAlreadyFreedShutdownTimeFileName) {
return nullptr;
}
if (!gRecordedShutdownTimeFileName) {
nsCOMPtr<nsIFile> mozFile;
NS_GetSpecialDirectory(NS_APP_USER_PROFILE_50_DIR, getter_AddRefs(mozFile));
if (!mozFile)
return nullptr;
mozFile->AppendNative(NS_LITERAL_CSTRING("Telemetry.ShutdownTime.txt"));
nsAutoCString nativePath;
nsresult rv = mozFile->GetNativePath(nativePath);
if (!NS_SUCCEEDED(rv))
return nullptr;
gRecordedShutdownTimeFileName = PL_strdup(nativePath.get());
}
return gRecordedShutdownTimeFileName;
}
NS_IMETHODIMP
TelemetryImpl::GetLastShutdownDuration(uint32_t *aResult)
{
// We make this check so that GetShutdownTimeFileName() doesn't get
// called; calling that function without telemetry enabled violates
// assumptions that the write-the-shutdown-timestamp machinery makes.
if (!Telemetry::CanRecord()) {
*aResult = 0;
return NS_OK;
}
if (!mCachedShutdownTime) {
const char *filename = GetShutdownTimeFileName();
if (!filename) {
*aResult = 0;
return NS_OK;
}
FILE *f = fopen(filename, "r");
if (!f) {
*aResult = 0;
return NS_OK;
}
int shutdownTime;
int r = fscanf(f, "%d\n", &shutdownTime);
fclose(f);
if (r != 1) {
*aResult = 0;
return NS_OK;
}
mLastShutdownTime = shutdownTime;
mCachedShutdownTime = true;
}
*aResult = mLastShutdownTime;
return NS_OK;
}
TelemetryImpl::TelemetryImpl():
mHistogramMap(Telemetry::HistogramCount),
mCanRecord(XRE_GetProcessType() == GeckoProcessType_Default),
mHashMutex("Telemetry::mHashMutex"),
mHangReportsMutex("Telemetry::mHangReportsMutex")
mHangReportsMutex("Telemetry::mHangReportsMutex"),
mCachedShutdownTime(false),
mLastShutdownTime(0)
{
// A whitelist to prevent Telemetry reporting on Addon & Thunderbird DBs
const char *trackedDBs[] = {
@ -1673,6 +1751,53 @@ const Module kTelemetryModule = {
} // anonymous namespace
namespace mozilla {
void
RecordShutdownStartTimeStamp() {
if (!Telemetry::CanRecord())
return;
gRecordedShutdownStartTime = TimeStamp::Now();
GetShutdownTimeFileName();
}
void
RecordShutdownEndTimeStamp() {
if (!gRecordedShutdownTimeFileName || gAlreadyFreedShutdownTimeFileName)
return;
nsCString name(gRecordedShutdownTimeFileName);
PL_strfree(gRecordedShutdownTimeFileName);
gRecordedShutdownTimeFileName = nullptr;
gAlreadyFreedShutdownTimeFileName = true;
nsCString tmpName = name;
tmpName += ".tmp";
FILE *f = fopen(tmpName.get(), "w");
if (!f)
return;
// On a normal release build this should be called just before
// calling _exit, but on a debug build or when the user forces a full
// shutdown this is called as late as possible, so we have to
// white list this write as write poisoning will be enabled.
int fd = fileno(f);
MozillaRegisterDebugFD(fd);
TimeStamp now = TimeStamp::Now();
MOZ_ASSERT(now >= gRecordedShutdownStartTime);
TimeDuration diff = now - gRecordedShutdownStartTime;
uint32_t diff2 = diff.ToMilliseconds();
int written = fprintf(f, "%d\n", diff2);
MozillaUnRegisterDebugFILE(f);
int rv = fclose(f);
if (written < 0 || rv != 0) {
PR_Delete(tmpName.get());
return;
}
PR_Delete(name.get());
PR_Rename(tmpName.get(), name.get());
}
namespace Telemetry {
void

View File

@ -147,7 +147,7 @@ function getSimpleMeasurements() {
.getService(Ci.nsIJSEngineTelemetryStats)
.telemetryValue;
let shutdownDuration = Services.startup.lastShutdownDuration;
let shutdownDuration = Telemetry.lastShutdownDuration;
if (shutdownDuration)
ret.shutdownDuration = shutdownDuration;

View File

@ -6,7 +6,7 @@
#include "nsISupports.idl"
#include "nsIFile.idl"
[scriptable, uuid(de54f594-4c20-4968-a27a-83b38ff952b9)]
[scriptable, uuid(420ebbd5-efe3-42f2-8a13-f695e0fdcca0)]
interface nsITelemetry : nsISupports
{
/**
@ -36,6 +36,12 @@ interface nsITelemetry : nsISupports
[implicit_jscontext]
readonly attribute jsval histogramSnapshots;
/**
* The amount of time, in milliseconds, that the last session took
* to shutdown. Reads as 0 to indicate failure.
*/
readonly attribute uint32_t lastShutdownDuration;
/*
* An object containing information about slow SQL statements.
*