зеркало из https://github.com/mozilla/pjs.git
Bug 699918 - Implement profiler module. r=jmuizelaar
This commit is contained in:
Родитель
f7ba84cbaa
Коммит
f975747cf9
|
@ -3401,3 +3401,9 @@ pref("dom.sms.whitelist", "");
|
|||
|
||||
// enable JS dump() function.
|
||||
pref("browser.dom.window.dump.enabled", false);
|
||||
|
||||
// SPS Profiler
|
||||
pref("profiler.enabled", false);
|
||||
pref("profiler.interval", 10);
|
||||
pref("profiler.entries", 100000);
|
||||
|
||||
|
|
|
@ -2259,6 +2259,7 @@ WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
|||
and also some files in the directories
|
||||
<span class="path">ipc/chromium/</span>,
|
||||
<span class="path">dom/plugins/</span>,
|
||||
<span class="path">tools/profiler/sps/</span>,
|
||||
<span class="path">gfx/ots/</span> and
|
||||
<span class="path">gfx/ycbcr</span>.
|
||||
</p>
|
||||
|
|
|
@ -34,8 +34,12 @@
|
|||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <string>
|
||||
#include "sampler.h"
|
||||
#include "nsProfiler.h"
|
||||
#include <stdio.h>
|
||||
#include "nsMemory.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
NS_IMPL_ISUPPORTS1(nsProfiler, nsIProfiler)
|
||||
|
||||
|
@ -46,14 +50,55 @@ nsProfiler::nsProfiler()
|
|||
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::StartProfiler()
|
||||
nsProfiler::StartProfiler(PRUint32 aInterval, PRUint32 aEntries)
|
||||
{
|
||||
SAMPLER_START(aInterval, aEntries);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::StopProfiler()
|
||||
{
|
||||
SAMPLER_STOP();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetProfile(char **aProfile)
|
||||
{
|
||||
char *profile = SAMPLER_GET_PROFILE();
|
||||
PRUint32 len = strlen(profile);
|
||||
char *profileStr = static_cast<char *>
|
||||
(nsMemory::Clone(profile, len * sizeof(char)));
|
||||
*aProfile = profileStr;
|
||||
free(profile);
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::IsActive(bool *aIsActive)
|
||||
{
|
||||
*aIsActive = SAMPLER_IS_ACTIVE();
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
NS_IMETHODIMP
|
||||
nsProfiler::GetResponsivenessTimes(PRUint32 *aCount, float **aResult)
|
||||
{
|
||||
unsigned int len = 100;
|
||||
const float* times = SAMPLER_GET_RESPONSIVENESS();
|
||||
if (!times) {
|
||||
*aCount = 0;
|
||||
*aResult = nsnull;
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
float *fs = static_cast<float *>
|
||||
(nsMemory::Clone(times, len * sizeof(float)));
|
||||
|
||||
*aCount = len;
|
||||
*aResult = fs;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,7 +38,10 @@
|
|||
[scriptable, uuid(25db9b8e-8123-4de1-b36d-8bbbedf2cdf4)]
|
||||
interface nsIProfiler : nsISupports
|
||||
{
|
||||
void StartProfiler();
|
||||
void StartProfiler(in PRUint32 aInterval, in PRUint32 aEntries);
|
||||
void StopProfiler();
|
||||
string GetProfile();
|
||||
boolean IsActive();
|
||||
void GetResponsivenessTimes(out PRUint32 aCount, [retval, array, size_is(aCount)] out float aResult);
|
||||
};
|
||||
|
||||
|
|
|
@ -89,7 +89,14 @@
|
|||
// before the sampler has been initialized (i.e. early start-up code)
|
||||
#define SAMPLER_INIT()
|
||||
#define SAMPLER_DEINIT()
|
||||
#define SAMPLER_RESPONSIVENESS(time)
|
||||
#define SAMPLER_START(entries, interval)
|
||||
#define SAMPLER_STOP()
|
||||
#define SAMPLER_IS_ACTIVE() false
|
||||
#define SAMPLER_SAVE()
|
||||
// Returned string must be free'ed
|
||||
#define SAMPLER_GET_PROFILE() NULL
|
||||
#define SAMPLER_RESPONSIVENESS(time) NULL
|
||||
#define SAMPLER_GET_RESPONSIVENESS() NULL
|
||||
#define SAMPLE_CHECKPOINT(name_space, info)
|
||||
#define SAMPLE_MARKER(info)
|
||||
|
||||
|
|
|
@ -1,62 +0,0 @@
|
|||
#! gmake
|
||||
#
|
||||
# ***** BEGIN LICENSE BLOCK *****
|
||||
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||
#
|
||||
# The contents of this file are subject to the Mozilla Public License Version
|
||||
# 1.1 (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
# http://www.mozilla.org/MPL/
|
||||
#
|
||||
# Software distributed under the License is distributed on an "AS IS" basis,
|
||||
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||
# for the specific language governing rights and limitations under the
|
||||
# License.
|
||||
#
|
||||
# The Original Code is mozilla.org Code.
|
||||
#
|
||||
# The Initial Developer of the Original Code is
|
||||
# Kipp E.B. Hickman.
|
||||
# Portions created by the Initial Developer are Copyright (C) 2001
|
||||
# the Initial Developer. All Rights Reserved.
|
||||
#
|
||||
# Contributor(s):
|
||||
#
|
||||
# Alternatively, the contents of this file may be used under the terms of
|
||||
# either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||
# the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||
# in which case the provisions of the GPL or the LGPL are applicable instead
|
||||
# of those above. If you wish to allow use of your version of this file only
|
||||
# under the terms of either the GPL or the LGPL, and not to allow others to
|
||||
# use your version of this file under the terms of the MPL, indicate your
|
||||
# decision by deleting the provisions above and replace them with the notice
|
||||
# and other provisions required by the GPL or the LGPL. If you do not delete
|
||||
# the provisions above, a recipient may use your version of this file under
|
||||
# the terms of any one of the MPL, the GPL or the LGPL.
|
||||
#
|
||||
# ***** END LICENSE BLOCK *****
|
||||
|
||||
DEPTH = ../../..
|
||||
topsrcdir = @top_srcdir@
|
||||
srcdir = @srcdir@
|
||||
VPATH = @srcdir@
|
||||
|
||||
include $(DEPTH)/config/autoconf.mk
|
||||
|
||||
MODULE = profilersps
|
||||
EXPORTS =
|
||||
LIBRARY_NAME = profilersps
|
||||
EXPORT_LIBRARY = 1
|
||||
LIBXUL_LIBRARY = 1
|
||||
|
||||
CPPSRCS = \
|
||||
sampler.cc \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS = \
|
||||
$(NULL)
|
||||
|
||||
EXPORTS := $(addprefix $(srcdir)/, $(EXPORTS))
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
@ -39,18 +39,22 @@
|
|||
#include <sys/stat.h> // open
|
||||
#include <fcntl.h> // open
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <semaphore.h>
|
||||
#include <string.h>
|
||||
#include "sps_sampler.h"
|
||||
#include "platform.h"
|
||||
#include "nsXULAppAPI.h"
|
||||
#include "nsThreadUtils.h"
|
||||
#include "prenv.h"
|
||||
|
||||
using std::string;
|
||||
|
||||
pthread_key_t pkey_stack;
|
||||
pthread_key_t pkey_ticker;
|
||||
|
||||
TimeStamp sLastTracerEvent;
|
||||
|
||||
class Profile;
|
||||
|
||||
class ProfileEntry
|
||||
|
@ -69,16 +73,27 @@ public:
|
|||
, mTagName(aTagName)
|
||||
{ }
|
||||
|
||||
// aTagData must not need release (i.e. be a string from the text segment)
|
||||
ProfileEntry(char aTagName, const char *aTagData, Address aLeafAddress)
|
||||
: mTagData(aTagData)
|
||||
, mLeafAddress(aLeafAddress)
|
||||
, mTagName(aTagName)
|
||||
{ }
|
||||
|
||||
ProfileEntry(char aTagName, float aTagFloat)
|
||||
: mTagFloat(aTagFloat)
|
||||
, mLeafAddress(0)
|
||||
, mTagName(aTagName)
|
||||
{ }
|
||||
|
||||
string TagToString(Profile *profile);
|
||||
void WriteTag(Profile *profile, FILE* stream);
|
||||
|
||||
private:
|
||||
const char* mTagData;
|
||||
union {
|
||||
const char* mTagData;
|
||||
float mTagFloat;
|
||||
};
|
||||
Address mLeafAddress;
|
||||
char mTagName;
|
||||
};
|
||||
|
@ -112,9 +127,25 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void ToString(string* profile)
|
||||
{
|
||||
// Can't be called from signal because
|
||||
// get_maps calls non reentrant functions.
|
||||
#ifdef ENABLE_SPS_LEAF_DATA
|
||||
mMaps = getmaps(getpid());
|
||||
#endif
|
||||
|
||||
*profile = "";
|
||||
int oldReadPos = mReadPos;
|
||||
while (mReadPos != mWritePos) {
|
||||
*profile += mEntries[mReadPos].TagToString(this);
|
||||
mReadPos = (mReadPos + 1) % mEntrySize;
|
||||
}
|
||||
mReadPos = oldReadPos;
|
||||
}
|
||||
|
||||
void WriteProfile(FILE* stream)
|
||||
{
|
||||
LOG("Save profile");
|
||||
// Can't be called from signal because
|
||||
// get_maps calls non reentrant functions.
|
||||
#ifdef ENABLE_SPS_LEAF_DATA
|
||||
|
@ -151,9 +182,10 @@ class SaveProfileTask;
|
|||
|
||||
class TableTicker: public Sampler {
|
||||
public:
|
||||
explicit TableTicker(int aEntrySize, int aInterval)
|
||||
explicit TableTicker(int aInterval, int aEntrySize, Stack *aStack)
|
||||
: Sampler(aInterval, true)
|
||||
, mProfile(aEntrySize)
|
||||
, mStack(aStack)
|
||||
, mSaveRequested(false)
|
||||
{
|
||||
mProfile.addTag(ProfileEntry('m', "Start"));
|
||||
|
@ -176,7 +208,7 @@ class TableTicker: public Sampler {
|
|||
|
||||
Stack* GetStack()
|
||||
{
|
||||
return &mStack;
|
||||
return mStack;
|
||||
}
|
||||
|
||||
Profile* GetProfile()
|
||||
|
@ -185,7 +217,7 @@ class TableTicker: public Sampler {
|
|||
}
|
||||
private:
|
||||
Profile mProfile;
|
||||
Stack mStack;
|
||||
Stack *mStack;
|
||||
bool mSaveRequested;
|
||||
};
|
||||
|
||||
|
@ -212,7 +244,7 @@ public:
|
|||
if (stream) {
|
||||
t->GetProfile()->WriteProfile(stream);
|
||||
::fclose(stream);
|
||||
LOG("Saved to " FOLDER "profile_TYPE_ID.txt");
|
||||
LOG("Saved to " FOLDER "profile_TYPE_PID.txt");
|
||||
} else {
|
||||
LOG("Fail to open profile log file.");
|
||||
}
|
||||
|
@ -238,29 +270,71 @@ void TableTicker::Tick(TickSample* sample)
|
|||
{
|
||||
// Marker(s) come before the sample
|
||||
int i = 0;
|
||||
const char *marker = mStack.getMarker(i++);
|
||||
const char *marker = mStack->getMarker(i++);
|
||||
for (int i = 0; marker != NULL; i++) {
|
||||
mProfile.addTag(ProfileEntry('m', marker));
|
||||
marker = mStack.getMarker(i++);
|
||||
marker = mStack->getMarker(i++);
|
||||
}
|
||||
mStack.mQueueClearMarker = true;
|
||||
mStack->mQueueClearMarker = true;
|
||||
|
||||
// Sample
|
||||
// 's' tag denotes the start of a sample block
|
||||
// followed by 0 or more 'c' tags.
|
||||
for (int i = 0; i < mStack.mStackPointer; i++) {
|
||||
for (int i = 0; i < mStack->mStackPointer; i++) {
|
||||
if (i == 0) {
|
||||
Address pc = 0;
|
||||
if (sample) {
|
||||
pc = sample->pc;
|
||||
}
|
||||
mProfile.addTag(ProfileEntry('s', mStack.mStack[i], pc));
|
||||
mProfile.addTag(ProfileEntry('s', mStack->mStack[i], pc));
|
||||
} else {
|
||||
mProfile.addTag(ProfileEntry('c', mStack.mStack[i]));
|
||||
mProfile.addTag(ProfileEntry('c', mStack->mStack[i]));
|
||||
}
|
||||
}
|
||||
|
||||
if (!sLastTracerEvent.IsNull()) {
|
||||
TimeDuration delta = TimeStamp::Now() - sLastTracerEvent;
|
||||
mProfile.addTag(ProfileEntry('r', delta.ToMilliseconds()));
|
||||
}
|
||||
}
|
||||
|
||||
string ProfileEntry::TagToString(Profile *profile)
|
||||
{
|
||||
string tag = "";
|
||||
if (mTagName == 'r') {
|
||||
char buff[50];
|
||||
snprintf(buff, 50, "%-40f", mTagFloat);
|
||||
tag += string(1, mTagName) + string("-") + string(buff) + string("\n");
|
||||
} else {
|
||||
tag += string(1, mTagName) + string("-") + string(mTagData) + string("\n");
|
||||
}
|
||||
|
||||
#ifdef ENABLE_SPS_LEAF_DATA
|
||||
if (mLeafAddress) {
|
||||
bool found = false;
|
||||
char tagBuff[1024];
|
||||
MapInfo& maps = profile->getMap();
|
||||
unsigned long pc = (unsigned long)mLeafAddress;
|
||||
// TODO Use binary sort (STL)
|
||||
for (size_t i = 0; i < maps.GetSize(); i++) {
|
||||
MapEntry &e = maps.GetEntry(i);
|
||||
if (pc > e.GetStart() && pc < e.GetEnd()) {
|
||||
if (e.GetName()) {
|
||||
found = true;
|
||||
snprintf(tagBuff, 1024, "l-%900s@%llu\n", e.GetName(), pc - e.GetStart());
|
||||
tag += string(tagBuff);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
snprintf(tagBuff, 1024, "l-???@%llu\n", pc);
|
||||
tag += string(tagBuff);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return tag;
|
||||
}
|
||||
|
||||
void ProfileEntry::WriteTag(Profile *profile, FILE *stream)
|
||||
{
|
||||
|
@ -290,6 +364,8 @@ void ProfileEntry::WriteTag(Profile *profile, FILE *stream)
|
|||
}
|
||||
|
||||
#define PROFILE_DEFAULT_ENTRY 100000
|
||||
#define PROFILE_DEFAULT_INTERVAL 10
|
||||
|
||||
void mozilla_sampler_init()
|
||||
{
|
||||
// TODO linux port: Use TLS with ifdefs
|
||||
|
@ -303,19 +379,71 @@ void mozilla_sampler_init()
|
|||
return;
|
||||
}
|
||||
|
||||
const char *val = PR_GetEnv("MOZ_PROFILER_SPS");
|
||||
Stack *stack = new Stack();
|
||||
pthread_setspecific(pkey_stack, stack);
|
||||
|
||||
// We can't open pref so we use an environment variable
|
||||
// to know if we should trigger the profiler on startup
|
||||
// NOTE: Default
|
||||
const char *val = PR_GetEnv("MOZ_PROFILER_STARTUP");
|
||||
if (!val || !*val) {
|
||||
return;
|
||||
}
|
||||
|
||||
TableTicker *t = new TableTicker(PROFILE_DEFAULT_ENTRY, 10);
|
||||
pthread_setspecific(pkey_ticker, t);
|
||||
pthread_setspecific(pkey_stack, t->GetStack());
|
||||
|
||||
t->Start();
|
||||
mozilla_sampler_start(PROFILE_DEFAULT_ENTRY, PROFILE_DEFAULT_INTERVAL);
|
||||
}
|
||||
|
||||
void mozilla_sampler_deinit()
|
||||
{
|
||||
mozilla_sampler_stop();
|
||||
// We can't delete the Stack because we can be between a
|
||||
// sampler call_enter/call_exit point.
|
||||
// TODO Need to find a safe time to delete Stack
|
||||
}
|
||||
|
||||
void mozilla_sampler_save() {
|
||||
TableTicker *t = (TableTicker*)pthread_getspecific(pkey_ticker);
|
||||
if (!t) {
|
||||
return;
|
||||
}
|
||||
|
||||
t->RequestSave();
|
||||
// We're on the main thread already so we don't
|
||||
// have to wait to handle the save request.
|
||||
t->HandleSaveRequest();
|
||||
}
|
||||
|
||||
char* mozilla_sampler_get_profile() {
|
||||
TableTicker *t = (TableTicker*)pthread_getspecific(pkey_ticker);
|
||||
if (!t) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
string profile;
|
||||
t->GetProfile()->ToString(&profile);
|
||||
|
||||
char *rtn = (char*)malloc( (strlen(profile.c_str())+1) * sizeof(char) );
|
||||
strcpy(rtn, profile.c_str());
|
||||
return rtn;
|
||||
}
|
||||
|
||||
// Values are only honored on the first start
|
||||
void mozilla_sampler_start(int aProfileEntries, int aInterval)
|
||||
{
|
||||
Stack *stack = (Stack*)pthread_getspecific(pkey_stack);
|
||||
if (!stack) {
|
||||
ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
mozilla_sampler_stop();
|
||||
|
||||
TableTicker *t = new TableTicker(aInterval, aProfileEntries, stack);
|
||||
pthread_setspecific(pkey_ticker, t);
|
||||
t->Start();
|
||||
}
|
||||
|
||||
void mozilla_sampler_stop()
|
||||
{
|
||||
TableTicker *t = (TableTicker*)pthread_getspecific(pkey_ticker);
|
||||
if (!t) {
|
||||
|
@ -323,9 +451,44 @@ void mozilla_sampler_deinit()
|
|||
}
|
||||
|
||||
t->Stop();
|
||||
pthread_setspecific(pkey_stack, NULL);
|
||||
// We can't delete the TableTicker because we can be between a
|
||||
// sampler call_enter/call_exit point.
|
||||
// TODO Need to find a safe time to delete TableTicker
|
||||
pthread_setspecific(pkey_ticker, NULL);
|
||||
}
|
||||
|
||||
bool mozilla_sampler_is_active()
|
||||
{
|
||||
TableTicker *t = (TableTicker*)pthread_getspecific(pkey_ticker);
|
||||
if (!t) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return t->IsActive();
|
||||
}
|
||||
|
||||
float sResponsivenessTimes[100];
|
||||
float sCurrResponsiveness = 0.f;
|
||||
unsigned int sResponsivenessLoc = 0;
|
||||
void mozilla_sampler_responsiveness(TimeStamp aTime)
|
||||
{
|
||||
if (!sLastTracerEvent.IsNull()) {
|
||||
if (sResponsivenessLoc == 100) {
|
||||
for(size_t i = 0; i < 100-1; i++) {
|
||||
sResponsivenessTimes[i] = sResponsivenessTimes[i+1];
|
||||
}
|
||||
sResponsivenessLoc--;
|
||||
//for(size_t i = 0; i < 100; i++) {
|
||||
// sResponsivenessTimes[i] = 0;
|
||||
//}
|
||||
//sResponsivenessLoc = 0;
|
||||
}
|
||||
TimeDuration delta = aTime - sLastTracerEvent;
|
||||
sResponsivenessTimes[sResponsivenessLoc++] = delta.ToMilliseconds();
|
||||
}
|
||||
|
||||
sLastTracerEvent = aTime;
|
||||
}
|
||||
|
||||
const float* mozilla_sampler_get_responsiveness()
|
||||
{
|
||||
return sResponsivenessTimes;
|
||||
}
|
||||
|
||||
|
|
|
@ -151,6 +151,9 @@ void Thread::Start() {
|
|||
ASSERT(data_->thread_ != kNoThread);
|
||||
}
|
||||
|
||||
void Thread::Join() {
|
||||
pthread_join(data_->thread_, NULL);
|
||||
}
|
||||
|
||||
class Sampler::PlatformData : public Malloced {
|
||||
public:
|
||||
|
@ -191,6 +194,9 @@ class SamplerThread : public Thread {
|
|||
static void RemoveActiveSampler(Sampler* sampler) {
|
||||
ScopedLock lock(mutex_);
|
||||
SamplerRegistry::RemoveActiveSampler(sampler);
|
||||
instance_->Join();
|
||||
delete instance_;
|
||||
instance_ = NULL;
|
||||
/*
|
||||
if (SamplerRegistry::GetState() == SamplerRegistry::HAS_NO_SAMPLERS) {
|
||||
RuntimeProfiler::StopRuntimeProfilerThreadBeforeShutdown(instance_);
|
||||
|
@ -296,6 +302,6 @@ void Sampler::Start() {
|
|||
|
||||
void Sampler::Stop() {
|
||||
ASSERT(IsActive());
|
||||
SamplerThread::RemoveActiveSampler(this);
|
||||
SetActive(false);
|
||||
SamplerThread::RemoveActiveSampler(this);
|
||||
}
|
||||
|
|
|
@ -171,6 +171,8 @@ class Thread {
|
|||
// Start new thread by calling the Run() method in the new thread.
|
||||
void Start();
|
||||
|
||||
void Join();
|
||||
|
||||
inline const char* name() const {
|
||||
return name_;
|
||||
}
|
||||
|
|
|
@ -39,6 +39,10 @@
|
|||
#include <pthread.h>
|
||||
#include "base/atomicops.h"
|
||||
#include "nscore.h"
|
||||
#include "mozilla/TimeStamp.h"
|
||||
|
||||
using mozilla::TimeStamp;
|
||||
using mozilla::TimeDuration;
|
||||
|
||||
// TODO Merge into Sampler.h
|
||||
|
||||
|
@ -46,6 +50,13 @@ extern pthread_key_t pkey_stack;
|
|||
|
||||
#define SAMPLER_INIT() mozilla_sampler_init();
|
||||
#define SAMPLER_DEINIT() mozilla_sampler_deinit();
|
||||
#define SAMPLER_START(entries, interval) mozilla_sampler_start(entries, interval);
|
||||
#define SAMPLER_STOP() mozilla_sampler_stop();
|
||||
#define SAMPLER_IS_ACTIVE() mozilla_sampler_is_active();
|
||||
#define SAMPLER_RESPONSIVENESS(time) mozilla_sampler_responsiveness(time)
|
||||
#define SAMPLER_GET_RESPONSIVENESS() mozilla_sampler_get_responsiveness()
|
||||
#define SAMPLER_SAVE() mozilla_sampler_save();
|
||||
#define SAMPLER_GET_PROFILE() mozilla_sampler_get_profile();
|
||||
#define SAMPLE_CHECKPOINT(name_space, info) mozilla::SamplerStackFrameRAII only_one_sampleraii_per_scope(FULLFUNCTION, name_space "::" info);
|
||||
#define SAMPLE_MARKER(info) mozilla_sampler_add_marker(info);
|
||||
|
||||
|
@ -70,6 +81,13 @@ inline void* mozilla_sampler_call_enter(const char *aInfo);
|
|||
inline void mozilla_sampler_call_exit(void* handle);
|
||||
inline void mozilla_sampler_add_marker(const char *aInfo);
|
||||
|
||||
void mozilla_sampler_start(int aEntries, int aInterval);
|
||||
void mozilla_sampler_stop();
|
||||
bool mozilla_sampler_is_active();
|
||||
void mozilla_sampler_responsiveness(TimeStamp time);
|
||||
const float* mozilla_sampler_get_responsiveness();
|
||||
void mozilla_sampler_save();
|
||||
char* mozilla_sampler_get_profile();
|
||||
void mozilla_sampler_init();
|
||||
|
||||
namespace mozilla {
|
||||
|
|
Загрузка…
Ссылка в новой задаче