Bug 793735 - Make XRE_StartupTimelineRecord() generate TimeStamps and modify its callers to use the appropriate timers, r=nfroyd

This commit is contained in:
Gabriele Svelto 2013-03-26 11:31:20 +01:00
parent 47339aca3a
commit c5cb74f8ec
7 changed files with 143 additions and 33 deletions

View File

@ -66,6 +66,10 @@ ifdef MOZ_LINKER
LIBS += $(MOZ_ZLIB_LIBS)
endif
ifdef HAVE_CLOCK_MONOTONIC
LIBS += $(REALTIME_LIBS)
endif
ifndef MOZ_WINCONSOLE
ifdef MOZ_DEBUG
MOZ_WINCONSOLE = 1

View File

@ -13,12 +13,13 @@
#include <io.h>
#include <fcntl.h>
#elif defined(XP_UNIX)
#include <sys/time.h>
#include <sys/resource.h>
#include <time.h>
#include <unistd.h>
#endif
#ifdef XP_MACOSX
#include <mach/mach_time.h>
#include "MacQuirks.h"
#endif
@ -381,25 +382,80 @@ static int do_main(int argc, char* argv[], nsIFile *xreDirectory)
return 255;
}
/* Local implementation of PR_Now, since the executable can't depend on NSPR */
static PRTime _PR_Now()
{
#ifdef XP_WIN
MOZ_STATIC_ASSERT(sizeof(PRTime) == sizeof(FILETIME), "PRTime must have the same size as FILETIME");
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
PRTime now;
CopyMemory(&now, &ft, sizeof(PRTime));
#ifdef __GNUC__
return (now - 116444736000000000LL) / 10LL;
#else
return (now - 116444736000000000i64) / 10i64;
/**
* Used only when GetTickCount64 is not available on the platform.
* Last result of GetTickCount call. Kept in [ms].
*/
static DWORD sLastGTCResult = 0;
/**
* Higher part of the 64-bit value of MozGetTickCount64,
* incremented atomically.
*/
static DWORD sLastGTCRollover = 0;
/**
* Function protecting GetTickCount result from rolling over. The original
* code comes from the Windows implementation of the TimeStamp class minus the
* locking harness which isn't needed here.
*
* @returns The current time in milliseconds
*/
static ULONGLONG WINAPI
MozGetTickCount64()
{
DWORD GTC = ::GetTickCount();
/* Pull the rollover counter forward only if new value of GTC goes way
* down under the last saved result */
if ((sLastGTCResult > GTC) && ((sLastGTCResult - GTC) > (1UL << 30)))
++sLastGTCRollover;
sLastGTCResult = GTC;
return (ULONGLONG)sLastGTCRollover << 32 | sLastGTCResult;
}
typedef ULONGLONG (WINAPI* GetTickCount64_t)();
static GetTickCount64_t sGetTickCount64 = nullptr;
#endif
#else
struct timeval tm;
gettimeofday(&tm, 0);
return (((PRTime)tm.tv_sec * 1000000LL) + (PRTime)tm.tv_usec);
/**
* Local TimeStamp::Now()-compatible implementation used to record timestamps
* which will be passed to XRE_StartupTimelineRecord().
*/
static uint64_t
TimeStamp_Now()
{
#ifdef XP_WIN
LARGE_INTEGER freq;
::QueryPerformanceFrequency(&freq);
HMODULE kernelDLL = GetModuleHandleW(L"kernel32.dll");
sGetTickCount64 = reinterpret_cast<GetTickCount64_t>
(GetProcAddress(kernelDLL, "GetTickCount64"));
if (!sGetTickCount64) {
/* If the platform does not support the GetTickCount64 (Windows XP doesn't),
* then use our fallback implementation based on GetTickCount. */
sGetTickCount64 = MozGetTickCount64;
}
return sGetTickCount64() * freq.QuadPart;
#elif defined(XP_MACOSX)
return mach_absolute_time();
#elif defined(HAVE_CLOCK_MONOTONIC)
struct timespec ts;
int rv = clock_gettime(CLOCK_MONOTONIC, &ts);
if (rv != 0) {
return 0;
}
uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
return baseNs + (uint64_t)ts.tv_nsec;
#endif
}
@ -521,7 +577,7 @@ int main(int argc, char* argv[])
#ifdef DEBUG_delay_start_metro
Sleep(5000);
#endif
PRTime start = _PR_Now();
uint64_t start = TimeStamp_Now();
#ifdef XP_MACOSX
TriggerQuirks();

View File

@ -11,7 +11,6 @@
#include <jni.h>
#include <android/log.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/mman.h>
@ -20,6 +19,7 @@
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <unistd.h>
#include <zlib.h>
@ -56,7 +56,6 @@ extern "C" {
}
typedef int mozglueresult;
typedef int64_t MOZTime;
enum StartupEvent {
#define mozilla_StartupTimeline_Event(ev, z) ev,
@ -67,11 +66,22 @@ enum StartupEvent {
using namespace mozilla;
static MOZTime MOZ_Now()
/**
* Local TimeStamp::Now()-compatible implementation used to record timestamps
* which will be passed to XRE_StartupTimelineRecord().
*/
static uint64_t TimeStamp_Now()
{
struct timeval tm;
gettimeofday(&tm, 0);
return (((MOZTime)tm.tv_sec * 1000000LL) + (MOZTime)tm.tv_usec);
struct timespec ts;
int rv = clock_gettime(CLOCK_MONOTONIC, &ts);
if (rv != 0) {
return 0;
}
uint64_t baseNs = (uint64_t)ts.tv_sec * 1000000000;
return baseNs + (uint64_t)ts.tv_nsec;
}
static struct mapping_info * lib_mapping = NULL;
@ -143,7 +153,7 @@ loadGeckoLibs(const char *apkName)
{
chdir(getenv("GRE_HOME"));
MOZTime t0 = MOZ_Now();
uint64_t t0 = TimeStamp_Now();
struct rusage usage1;
getrusage(RUSAGE_THREAD, &usage1);
@ -163,10 +173,10 @@ loadGeckoLibs(const char *apkName)
#include "jni-stubs.inc"
#undef JNI_BINDINGS
void (*XRE_StartupTimelineRecord)(int, MOZTime);
void (*XRE_StartupTimelineRecord)(int, uint64_t);
xul_dlsym("XRE_StartupTimelineRecord", &XRE_StartupTimelineRecord);
MOZTime t1 = MOZ_Now();
uint64_t t1 = TimeStamp_Now();
struct rusage usage2;
getrusage(RUSAGE_THREAD, &usage2);

View File

@ -3,6 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "StartupTimeline.h"
#include "mozilla/Telemetry.h"
#include "mozilla/TimeStamp.h"
#include "nsXULAppAPI.h"
namespace mozilla {
@ -14,17 +16,52 @@ const char *StartupTimeline::sStartupTimelineDesc[StartupTimeline::MAX_EVENT_ID]
#undef mozilla_StartupTimeline_Event
};
/**
* Implementation of XRE_StartupTimelineRecord()
*
* @param aEvent Same as XRE_StartupTimelineRecord() equivalent argument
* @param aWhen Same as XRE_StartupTimelineRecord() equivalent argument
*/
void
StartupTimelineRecordExternal(int aEvent, uint64_t aWhen)
{
#if XP_WIN
TimeStamp ts = TimeStampValue(aWhen, 0, 0);
#else
TimeStamp ts = TimeStampValue(aWhen);
#endif
bool error = false;
// Since the timestamp comes from an external source validate it before
// recording it and log a telemetry error if it appears inconsistent.
if (ts < TimeStamp::ProcessCreation(error)) {
Telemetry::Accumulate(Telemetry::STARTUP_MEASUREMENT_ERRORS,
(StartupTimeline::Event)aEvent);
} else {
StartupTimeline::Record((StartupTimeline::Event)aEvent, ts);
}
}
} /* namespace mozilla */
/**
* The XRE_StartupTimeline_Record function is to be used by embedding applications
* that can't use mozilla::StartupTimeline::Record() directly.
* The XRE_StartupTimeline_Record function is to be used by embedding
* applications that can't use mozilla::StartupTimeline::Record() directly.
*
* It can create timestamps from arbitrary time values and sanitizies them to
* ensure that they are not inconsistent with those captured using monotonic
* timers. The value of aWhen must have been captured using the same timer
* used by the platform's mozilla::TimeStamp implementation. Erroneous values
* will be flagged as telemetry errors.
*
* @param aEvent The event to be recorded, must correspond to an element of the
* mozilla::StartupTimeline::Event enumartion
* @param aWhen The time at which the event happened, must have been recorded
* using the same timer as the platform's mozilla::TimeStamp
* implementation
*/
void
XRE_StartupTimelineRecord(int aEvent, PRTime aWhen)
{
/* FIXME: This effectively becomes a no-op until we fix all the users to
* provide proper timestamps */
mozilla::StartupTimeline::Record((mozilla::StartupTimeline::Event) aEvent,
mozilla::TimeStamp());
mozilla::StartupTimelineRecordExternal(aEvent, aWhen);
}

View File

@ -41,6 +41,7 @@ namespace mozilla {
void RecordShutdownEndTimeStamp();
void RecordShutdownStartTimeStamp();
void StartupTimelineRecordExternal(int, uint64_t);
class StartupTimeline {
public:

View File

@ -333,6 +333,7 @@ public:
private:
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
friend void StartupTimelineRecordExternal(int, uint64_t);
TimeStamp(TimeStampValue aValue) : mValue(aValue) {}

View File

@ -15,6 +15,7 @@ class TimeStampValue
{
friend struct IPC::ParamTraits<mozilla::TimeStampValue>;
friend class TimeStamp;
friend void StartupTimelineRecordExternal(int, uint64_t);
// Both QPC and GTC are kept in [mt] units.
uint64_t mGTC;