mirror of https://github.com/axmolengine/axmol.git
194 lines
4.7 KiB
C++
194 lines
4.7 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* vim: set ts=8 sw=4 et tw=78:
|
|
*
|
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
#ifndef jsgc_statistics_h___
|
|
#define jsgc_statistics_h___
|
|
|
|
#include <string.h>
|
|
|
|
#include "jsfriendapi.h"
|
|
#include "jspubtd.h"
|
|
#include "jsutil.h"
|
|
|
|
struct JSCompartment;
|
|
|
|
namespace js {
|
|
namespace gcstats {
|
|
|
|
enum Phase {
|
|
PHASE_GC_BEGIN,
|
|
PHASE_WAIT_BACKGROUND_THREAD,
|
|
PHASE_PURGE,
|
|
PHASE_MARK,
|
|
PHASE_MARK_DISCARD_CODE,
|
|
PHASE_MARK_ROOTS,
|
|
PHASE_MARK_TYPES,
|
|
PHASE_MARK_DELAYED,
|
|
PHASE_MARK_WEAK,
|
|
PHASE_MARK_GRAY,
|
|
PHASE_MARK_GRAY_WEAK,
|
|
PHASE_FINALIZE_START,
|
|
PHASE_SWEEP,
|
|
PHASE_SWEEP_ATOMS,
|
|
PHASE_SWEEP_COMPARTMENTS,
|
|
PHASE_SWEEP_TABLES,
|
|
PHASE_SWEEP_OBJECT,
|
|
PHASE_SWEEP_STRING,
|
|
PHASE_SWEEP_SCRIPT,
|
|
PHASE_SWEEP_SHAPE,
|
|
PHASE_SWEEP_IONCODE,
|
|
PHASE_SWEEP_DISCARD_CODE,
|
|
PHASE_DISCARD_ANALYSIS,
|
|
PHASE_DISCARD_TI,
|
|
PHASE_FREE_TI_ARENA,
|
|
PHASE_SWEEP_TYPES,
|
|
PHASE_CLEAR_SCRIPT_ANALYSIS,
|
|
PHASE_FINALIZE_END,
|
|
PHASE_DESTROY,
|
|
PHASE_GC_END,
|
|
|
|
PHASE_LIMIT
|
|
};
|
|
|
|
enum Stat {
|
|
STAT_NEW_CHUNK,
|
|
STAT_DESTROY_CHUNK,
|
|
|
|
STAT_LIMIT
|
|
};
|
|
|
|
class StatisticsSerializer;
|
|
|
|
struct Statistics {
|
|
Statistics(JSRuntime *rt);
|
|
~Statistics();
|
|
|
|
void beginPhase(Phase phase);
|
|
void endPhase(Phase phase);
|
|
|
|
void beginSlice(int collectedCount, int compartmentCount, gcreason::Reason reason);
|
|
void endSlice();
|
|
|
|
void reset(const char *reason) { slices.back().resetReason = reason; }
|
|
void nonincremental(const char *reason) { nonincrementalReason = reason; }
|
|
|
|
void count(Stat s) {
|
|
JS_ASSERT(s < STAT_LIMIT);
|
|
counts[s]++;
|
|
}
|
|
|
|
int64_t beginSCC();
|
|
void endSCC(unsigned scc, int64_t start);
|
|
|
|
jschar *formatMessage();
|
|
jschar *formatJSON(uint64_t timestamp);
|
|
|
|
private:
|
|
JSRuntime *runtime;
|
|
|
|
int64_t startupTime;
|
|
|
|
FILE *fp;
|
|
bool fullFormat;
|
|
|
|
/*
|
|
* GCs can't really nest, but a second GC can be triggered from within the
|
|
* JSGC_END callback.
|
|
*/
|
|
int gcDepth;
|
|
|
|
int collectedCount;
|
|
int compartmentCount;
|
|
const char *nonincrementalReason;
|
|
|
|
struct SliceData {
|
|
SliceData(gcreason::Reason reason, int64_t start, size_t startFaults)
|
|
: reason(reason), resetReason(NULL), start(start), startFaults(startFaults)
|
|
{
|
|
PodArrayZero(phaseTimes);
|
|
}
|
|
|
|
gcreason::Reason reason;
|
|
const char *resetReason;
|
|
int64_t start, end;
|
|
size_t startFaults, endFaults;
|
|
int64_t phaseTimes[PHASE_LIMIT];
|
|
|
|
int64_t duration() const { return end - start; }
|
|
};
|
|
|
|
Vector<SliceData, 8, SystemAllocPolicy> slices;
|
|
|
|
/* Most recent time when the given phase started. */
|
|
int64_t phaseStartTimes[PHASE_LIMIT];
|
|
|
|
/* Total time in a given phase for this GC. */
|
|
int64_t phaseTimes[PHASE_LIMIT];
|
|
|
|
/* Total time in a given phase over all GCs. */
|
|
int64_t phaseTotals[PHASE_LIMIT];
|
|
|
|
/* Number of events of this type for this GC. */
|
|
unsigned int counts[STAT_LIMIT];
|
|
|
|
/* Allocated space before the GC started. */
|
|
size_t preBytes;
|
|
|
|
/* Sweep times for SCCs of compartments. */
|
|
Vector<int64_t, 0, SystemAllocPolicy> sccTimes;
|
|
|
|
void beginGC();
|
|
void endGC();
|
|
|
|
void gcDuration(int64_t *total, int64_t *maxPause);
|
|
void sccDurations(int64_t *total, int64_t *maxPause);
|
|
void printStats();
|
|
bool formatData(StatisticsSerializer &ss, uint64_t timestamp);
|
|
|
|
double computeMMU(int64_t resolution);
|
|
};
|
|
|
|
struct AutoGCSlice {
|
|
AutoGCSlice(Statistics &stats, int collectedCount, int compartmentCount, gcreason::Reason reason
|
|
JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
: stats(stats)
|
|
{
|
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
|
stats.beginSlice(collectedCount, compartmentCount, reason);
|
|
}
|
|
~AutoGCSlice() { stats.endSlice(); }
|
|
|
|
Statistics &stats;
|
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
};
|
|
|
|
struct AutoPhase {
|
|
AutoPhase(Statistics &stats, Phase phase JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
: stats(stats), phase(phase) { JS_GUARD_OBJECT_NOTIFIER_INIT; stats.beginPhase(phase); }
|
|
~AutoPhase() { stats.endPhase(phase); }
|
|
|
|
Statistics &stats;
|
|
Phase phase;
|
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
};
|
|
|
|
struct AutoSCC {
|
|
AutoSCC(Statistics &stats, unsigned scc JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
|
: stats(stats), scc(scc) { JS_GUARD_OBJECT_NOTIFIER_INIT; start = stats.beginSCC(); }
|
|
~AutoSCC() { stats.endSCC(scc, start); }
|
|
|
|
Statistics &stats;
|
|
unsigned scc;
|
|
int64_t start;
|
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
|
};
|
|
|
|
} /* namespace gcstats */
|
|
} /* namespace js */
|
|
|
|
#endif /* jsgc_statistics_h___ */
|