зеркало из https://github.com/mozilla/gecko-dev.git
Bug 793735 - Make XRE_StartupTimelineRecord() generate TimeStamps and modify its callers to use the appropriate timers, r=nfroyd
This commit is contained in:
Родитель
852d5ec03d
Коммит
a8c937e2a1
|
@ -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
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace mozilla {
|
|||
|
||||
void RecordShutdownEndTimeStamp();
|
||||
void RecordShutdownStartTimeStamp();
|
||||
void StartupTimelineRecordExternal(int, uint64_t);
|
||||
|
||||
class StartupTimeline {
|
||||
public:
|
||||
|
|
|
@ -333,6 +333,7 @@ public:
|
|||
|
||||
private:
|
||||
friend struct IPC::ParamTraits<mozilla::TimeStamp>;
|
||||
friend void StartupTimelineRecordExternal(int, uint64_t);
|
||||
|
||||
TimeStamp(TimeStampValue aValue) : mValue(aValue) {}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче