void IOMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { streamCommonProps("io", aWriter, aUniqueStacks); aWriter.StringProperty("source", mSource); if (mFilename != nullptr) { aWriter.StringProperty("filename", mFilename); } }
void GPUMarkerPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { streamCommonProps("gpu_timer_query", aWriter, aUniqueStacks); aWriter.DoubleProperty("cpustart", profiler_time(mCpuTimeStart)); aWriter.DoubleProperty("cpuend", profiler_time(mCpuTimeEnd)); aWriter.IntProperty("gpustart", (int)mGpuTimeStart); aWriter.IntProperty("gpuend", (int)mGpuTimeEnd); }
void LayerTranslationPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { const size_t bufferSize = 32; char buffer[bufferSize]; PR_snprintf(buffer, bufferSize, "%p", mLayer); aWriter.StringProperty("layer", buffer); aWriter.IntProperty("x", mPoint.x); aWriter.IntProperty("y", mPoint.y); aWriter.StringProperty("category", "LayerTranslation"); }
void ProfilerMarkerTracing::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { streamCommonProps("tracing", aWriter, aUniqueStacks); if (GetCategory()) { aWriter.StringProperty("category", GetCategory()); } if (GetMetaData() != TRACING_DEFAULT) { if (GetMetaData() == TRACING_INTERVAL_START) { aWriter.StringProperty("interval", "start"); } else if (GetMetaData() == TRACING_INTERVAL_END) { aWriter.StringProperty("interval", "end"); } } }
void ProfilerMarkerPayload::streamCommonProps(const char* aMarkerType, SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { MOZ_ASSERT(aMarkerType); aWriter.StringProperty("type", aMarkerType); if (!mStartTime.IsNull()) { aWriter.DoubleProperty("startTime", profiler_time(mStartTime)); } if (!mEndTime.IsNull()) { aWriter.DoubleProperty("endTime", profiler_time(mEndTime)); } if (mStack) { aWriter.StartObjectProperty("stack"); { mStack->StreamJSON(aWriter, aUniqueStacks); } aWriter.EndObject(); } }
void ProfilerMarker::StreamJSON(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) const { // Schema: // [name, time, data] aWriter.StartArrayElement(); { aUniqueStacks.mUniqueStrings.WriteElement(aWriter, GetMarkerName()); aWriter.DoubleElement(mTime); // TODO: Store the callsite for this marker if available: // if have location data // b.NameValue(marker, "location", ...); if (mPayload) { aWriter.StartObjectElement(); { mPayload->StreamPayload(aWriter, aUniqueStacks); } aWriter.EndObject(); } } aWriter.EndArray(); }
void GeckoSampler::StreamJSON(SpliceableJSONWriter& aWriter, double aSinceTime) { aWriter.Start(SpliceableJSONWriter::SingleLineStyle); { // Put shared library info aWriter.StringProperty("libs", GetSharedLibraryInfoStringInternal().c_str()); // Put meta data aWriter.StartObjectProperty("meta"); StreamMetaJSCustomObject(aWriter); aWriter.EndObject(); // Data of TaskTracer doesn't belong in the circular buffer. if (TaskTracer()) { aWriter.StartObjectProperty("tasktracer"); StreamTaskTracer(aWriter); } // Lists the samples for each ThreadProfile aWriter.StartArrayProperty("threads"); { SetPaused(true); { ::MutexAutoLock lock(*sRegisteredThreadsMutex); for (size_t i = 0; i < sRegisteredThreads->size(); i++) { // Thread not being profiled, skip it if (!sRegisteredThreads->at(i)->Profile()) continue; // Note that we intentionally include ThreadProfile which // have been marked for pending delete. ::MutexAutoLock lock(sRegisteredThreads->at(i)->Profile()->GetMutex()); sRegisteredThreads->at(i)->Profile()->StreamJSON(aWriter, aSinceTime); } } #ifndef SPS_STANDALONE if (Sampler::CanNotifyObservers()) { // Send a event asking any subprocesses (plugins) to // give us their information SubprocessClosure closure(&aWriter); nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService(); if (os) { RefPtr<ProfileSaveEvent> pse = new ProfileSaveEvent(SubProcessCallback, &closure); os->NotifyObservers(pse, "profiler-subprocess", nullptr); } } #if defined(SPS_OS_android) && !defined(MOZ_WIDGET_GONK) if (ProfileJava()) { mozilla::widget::GeckoJavaSampler::PauseJavaProfiling(); aWriter.Start(); { BuildJavaThreadJSObject(aWriter); } aWriter.End(); mozilla::widget::GeckoJavaSampler::UnpauseJavaProfiling(); } #endif #endif SetPaused(false); } aWriter.EndArray(); } aWriter.End(); }
static void BuildJavaThreadJSObject(SpliceableJSONWriter& aWriter) { aWriter.StringProperty("name", "Java Main Thread"); aWriter.StartArrayProperty("samples"); // for each sample for (int sampleId = 0; true; sampleId++) { bool firstRun = true; // for each frame for (int frameId = 0; true; frameId++) { nsCString result; bool hasFrame = AndroidBridge::Bridge()->GetFrameNameJavaProfiling(0, sampleId, frameId, result); // when we run out of frames, we stop looping if (!hasFrame) { // if we found at least one frame, we have objects to close if (!firstRun) { aWriter.EndArray(); aWriter.EndObject(); } break; } // the first time around, open the sample object and frames array if (firstRun) { firstRun = false; double sampleTime = mozilla::widget::GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId); aWriter.StartObjectElement(); aWriter.DoubleProperty("time", sampleTime); aWriter.StartArrayProperty("frames"); } // add a frame to the sample aWriter.StartObjectElement(); aWriter.StringProperty("location", result.BeginReading()); aWriter.EndObject(); } // if we found no frames for this sample, we are done if (firstRun) { break; } } aWriter.EndArray(); }
void GeckoSampler::StreamMetaJSCustomObject(SpliceableJSONWriter& aWriter) { aWriter.IntProperty("version", 3); aWriter.DoubleProperty("interval", interval()); aWriter.IntProperty("stackwalk", mUseStackWalk); #ifndef SPS_STANDALONE mozilla::TimeDuration delta = mozilla::TimeStamp::Now() - sStartTime; aWriter.DoubleProperty("startTime", static_cast<double>(PR_Now()/1000.0 - delta.ToMilliseconds())); aWriter.IntProperty("processType", XRE_GetProcessType()); nsresult res; nsCOMPtr<nsIHttpProtocolHandler> http = do_GetService(NS_NETWORK_PROTOCOL_CONTRACTID_PREFIX "http", &res); if (!NS_FAILED(res)) { nsAutoCString string; res = http->GetPlatform(string); if (!NS_FAILED(res)) aWriter.StringProperty("platform", string.Data()); res = http->GetOscpu(string); if (!NS_FAILED(res)) aWriter.StringProperty("oscpu", string.Data()); res = http->GetMisc(string); if (!NS_FAILED(res)) aWriter.StringProperty("misc", string.Data()); } nsCOMPtr<nsIXULRuntime> runtime = do_GetService("@mozilla.org/xre/runtime;1"); if (runtime) { nsAutoCString string; res = runtime->GetXPCOMABI(string); if (!NS_FAILED(res)) aWriter.StringProperty("abi", string.Data()); res = runtime->GetWidgetToolkit(string); if (!NS_FAILED(res)) aWriter.StringProperty("toolkit", string.Data()); } nsCOMPtr<nsIXULAppInfo> appInfo = do_GetService("@mozilla.org/xre/app-info;1"); if (appInfo) { nsAutoCString string; res = appInfo->GetName(string); if (!NS_FAILED(res)) aWriter.StringProperty("product", string.Data()); } #endif }
void GeckoSampler::StreamTaskTracer(SpliceableJSONWriter& aWriter) { #ifdef MOZ_TASK_TRACER aWriter.StartArrayProperty("data"); nsAutoPtr<nsTArray<nsCString>> data(mozilla::tasktracer::GetLoggedData(sStartTime)); for (uint32_t i = 0; i < data->Length(); ++i) { aWriter.StringElement((data->ElementAt(i)).get()); } aWriter.EndArray(); aWriter.StartArrayProperty("threads"); ::MutexAutoLock lock(*sRegisteredThreadsMutex); for (size_t i = 0; i < sRegisteredThreads->size(); i++) { // Thread meta data ThreadInfo* info = sRegisteredThreads->at(i); aWriter.StartObjectElement(); if (XRE_GetProcessType() == GeckoProcessType_Plugin) { // TODO Add the proper plugin name aWriter.StringProperty("name", "Plugin"); } else { aWriter.StringProperty("name", info->Name()); } aWriter.IntProperty("tid", static_cast<int>(info->ThreadId())); aWriter.EndObject(); } aWriter.EndArray(); aWriter.DoubleProperty("start", static_cast<double>(mozilla::tasktracer::GetStartTime())); #endif }
void VsyncPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { aWriter.DoubleProperty("vsync", profiler_time(mVsyncTimestamp)); aWriter.StringProperty("category", "VsyncTimestamp"); }
void TouchDataPayload::StreamPayload(SpliceableJSONWriter& aWriter, UniqueStacks& aUniqueStacks) { aWriter.IntProperty("x", mPoint.x); aWriter.IntProperty("y", mPoint.y); }
void UniqueStacks::SpliceStackTableElements(SpliceableJSONWriter& aWriter) { mStackTableWriter.EndBareList(); aWriter.TakeAndSplice(mStackTableWriter.WriteFunc()); }
void ThreadProfile::StreamSamplesAndMarkers(SpliceableJSONWriter& aWriter, float aSinceTime, UniqueStacks& aUniqueStacks) { // Thread meta data if (XRE_GetProcessType() == GeckoProcessType_Plugin) { // TODO Add the proper plugin name aWriter.StringProperty("name", "Plugin"); } else if (XRE_GetProcessType() == GeckoProcessType_Content) { // This isn't going to really help once we have multiple content // processes, but it'll do for now. aWriter.StringProperty("name", "Content"); } else { aWriter.StringProperty("name", Name()); } aWriter.IntProperty("tid", static_cast<int>(mThreadId)); aWriter.StartObjectProperty("samples"); { { JSONSchemaWriter schema(aWriter); schema.WriteField("stack"); schema.WriteField("time"); schema.WriteField("responsiveness"); schema.WriteField("rss"); schema.WriteField("uss"); schema.WriteField("frameNumber"); schema.WriteField("power"); } aWriter.StartArrayProperty("data"); { if (mSavedStreamedSamples) { // We would only have saved streamed samples during shutdown // streaming, which cares about dumping the entire buffer, and thus // should have passed in 0 for aSinceTime. MOZ_ASSERT(aSinceTime == 0); aWriter.Splice(mSavedStreamedSamples.get()); mSavedStreamedSamples.reset(); } mBuffer->StreamSamplesToJSON(aWriter, mThreadId, aSinceTime, mPseudoStack->mRuntime, aUniqueStacks); } aWriter.EndArray(); } aWriter.EndObject(); aWriter.StartObjectProperty("markers"); { { JSONSchemaWriter schema(aWriter); schema.WriteField("name"); schema.WriteField("time"); schema.WriteField("data"); } aWriter.StartArrayProperty("data"); { if (mSavedStreamedMarkers) { MOZ_ASSERT(aSinceTime == 0); aWriter.Splice(mSavedStreamedMarkers.get()); mSavedStreamedMarkers.reset(); } mBuffer->StreamMarkersToJSON(aWriter, mThreadId, aSinceTime, aUniqueStacks); } aWriter.EndArray(); } aWriter.EndObject(); }
void ThreadProfile::StreamJSON(SpliceableJSONWriter& aWriter, float aSinceTime) { // mUniqueStacks may already be emplaced from FlushSamplesAndMarkers. if (!mUniqueStacks.isSome()) { mUniqueStacks.emplace(mPseudoStack->mRuntime); } aWriter.Start(SpliceableJSONWriter::SingleLineStyle); { StreamSamplesAndMarkers(aWriter, aSinceTime, *mUniqueStacks); aWriter.StartObjectProperty("stackTable"); { { JSONSchemaWriter schema(aWriter); schema.WriteField("prefix"); schema.WriteField("frame"); } aWriter.StartArrayProperty("data"); { mUniqueStacks->SpliceStackTableElements(aWriter); } aWriter.EndArray(); } aWriter.EndObject(); aWriter.StartObjectProperty("frameTable"); { { JSONSchemaWriter schema(aWriter); schema.WriteField("location"); schema.WriteField("implementation"); schema.WriteField("optimizations"); schema.WriteField("line"); schema.WriteField("category"); } aWriter.StartArrayProperty("data"); { mUniqueStacks->SpliceFrameTableElements(aWriter); } aWriter.EndArray(); } aWriter.EndObject(); aWriter.StartArrayProperty("stringTable"); { mUniqueStacks->mUniqueStrings.SpliceStringTableElements(aWriter); } aWriter.EndArray(); } aWriter.End(); mUniqueStacks.reset(); }
static void WriteSample(SpliceableJSONWriter& aWriter, ProfileSample& aSample) { // Schema: // [stack, time, responsiveness, rss, uss, frameNumber, power] aWriter.StartArrayElement(); { // The last non-null index is tracked to save space in the JSON by avoid // emitting 'null's at the end of the array, as they're only needed if // followed by non-null elements. uint32_t index = 0; uint32_t lastNonNullIndex = 0; aWriter.IntElement(aSample.mStack); index++; if (aSample.mTime.isSome()) { lastNonNullIndex = index; aWriter.DoubleElement(*aSample.mTime); } index++; if (aSample.mResponsiveness.isSome()) { aWriter.NullElements(index - lastNonNullIndex - 1); lastNonNullIndex = index; aWriter.DoubleElement(*aSample.mResponsiveness); } index++; if (aSample.mRSS.isSome()) { aWriter.NullElements(index - lastNonNullIndex - 1); lastNonNullIndex = index; aWriter.DoubleElement(*aSample.mRSS); } index++; if (aSample.mUSS.isSome()) { aWriter.NullElements(index - lastNonNullIndex - 1); lastNonNullIndex = index; aWriter.DoubleElement(*aSample.mUSS); } index++; if (aSample.mFrameNumber.isSome()) { aWriter.NullElements(index - lastNonNullIndex - 1); lastNonNullIndex = index; aWriter.IntElement(*aSample.mFrameNumber); } index++; if (aSample.mPower.isSome()) { aWriter.NullElements(index - lastNonNullIndex - 1); lastNonNullIndex = index; aWriter.DoubleElement(*aSample.mPower); } index++; } aWriter.EndArray(); }