Пример #1
0
void
TouchDataPayload::streamPayloadImpl(JSStreamWriter& b)
{
  b.BeginObject();
  b.NameValue("x", mPoint.x);
  b.NameValue("y", mPoint.y);
  b.EndObject();
}
Пример #2
0
void
VsyncPayload::streamPayloadImpl(JSStreamWriter& b)
{
  b.BeginObject();
  b.NameValue("vsync", profiler_time(mVsyncTimestamp));
  b.NameValue("category", "VsyncTimestamp");
  b.EndObject();
}
Пример #3
0
void
ProfilerMarkerImagePayload::streamPayloadImp(JSStreamWriter& b)
{
  b.BeginObject();
    streamCommonProps("innerHTML", b);
    // TODO: Finish me
    //b.NameValue("innerHTML", "<img src=''/>");
  b.EndObject();
}
Пример #4
0
void
IOMarkerPayload::streamPayloadImp(JSStreamWriter& b)
{
  b.BeginObject();
    streamCommonProps("io", b);
    b.NameValue("source", mSource);
    if (mFilename != nullptr) {
      b.NameValue("filename", mFilename);
    }
  b.EndObject();
}
Пример #5
0
void ProfilerMarker::StreamJSObject(JSStreamWriter& b) const {
  b.BeginObject();
    b.NameValue("name", GetMarkerName());
    // TODO: Store the callsite for this marker if available:
    // if have location data
    //   b.NameValue(marker, "location", ...);
    if (mPayload) {
      b.Name("data");
      mPayload->StreamPayload(b);
    }
    b.NameValue("time", mTime);
  b.EndObject();
}
Пример #6
0
void
LayerTranslationPayload::streamPayloadImpl(JSStreamWriter& b)
{
  const size_t bufferSize = 32;
  char buffer[bufferSize];
  PR_snprintf(buffer, bufferSize, "%p", mLayer);

  b.BeginObject();
  b.NameValue("layer", buffer);
  b.NameValue("x", mPoint.x);
  b.NameValue("y", mPoint.y);
  b.NameValue("category", "LayerTranslation");
  b.EndObject();
}
Пример #7
0
void ProfileBuffer::StreamMarkersToJSObject(JSStreamWriter& b, int aThreadId)
{
  b.BeginArray();
    int readPos = mReadPos;
    int currentThreadID = -1;
    while (readPos != mWritePos) {
      ProfileEntry entry = mEntries[readPos];
      if (entry.mTagName == 'T') {
        currentThreadID = entry.mTagInt;
      } else if (currentThreadID == aThreadId && entry.mTagName == 'm') {
        entry.getMarker()->StreamJSObject(b);
      }
      readPos = (readPos + 1) % mEntrySize;
    }
  b.EndArray();
}
Пример #8
0
void
ProfilerMarkerPayload::streamCommonProps(const char* aMarkerType,
                                          JSStreamWriter& b)
{
  MOZ_ASSERT(aMarkerType);
  b.NameValue("type", aMarkerType);
  if (!mStartTime.IsNull()) {
    b.NameValue("startTime", profiler_time(mStartTime));
  }
  if (!mEndTime.IsNull()) {
    b.NameValue("endTime", profiler_time(mEndTime));
  }
  if (mStack) {
    b.Name("stack");
    mStack->StreamJSObject(b);
  }
}
Пример #9
0
void
ProfilerMarkerTracing::streamPayloadImp(JSStreamWriter& b)
{
  b.BeginObject();
    streamCommonProps("tracing", b);

    if (GetCategory()) {
      b.NameValue("category", GetCategory());
    }
    if (GetMetaData() != TRACING_DEFAULT) {
      if (GetMetaData() == TRACING_INTERVAL_START) {
        b.NameValue("interval", "start");
      } else if (GetMetaData() == TRACING_INTERVAL_END) {
        b.NameValue("interval", "end");
      }
    }
  b.EndObject();
}
Пример #10
0
void TableTicker::StreamJSObject(JSStreamWriter& b)
{
    b.BeginObject();
    // Put shared library info
    b.NameValue("libs", GetSharedLibraryInfoString().c_str());

    // Put meta data
    b.Name("meta");
    StreamMetaJSCustomObject(b);

    // Lists the samples for each ThreadProfile
    b.Name("threads");
    b.BeginArray();

    SetPaused(true);

    {
        mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);

        for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
            // Thread not being profiled, skip it
            if (!sRegisteredThreads->at(i)->Profile())
                continue;

            MutexAutoLock lock(*sRegisteredThreads->at(i)->Profile()->GetMutex());

            sRegisteredThreads->at(i)->Profile()->StreamJSObject(b);
        }
    }

    if (Sampler::CanNotifyObservers()) {
        // Send a event asking any subprocesses (plugins) to
        // give us their information
        SubprocessClosure closure(&b);
        nsCOMPtr<nsIObserverService> os = mozilla::services::GetObserverService();
        if (os) {
            nsRefPtr<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::android::GeckoJavaSampler::PauseJavaProfiling();

        BuildJavaThreadJSObject(b);

        mozilla::widget::android::GeckoJavaSampler::UnpauseJavaProfiling();
    }
#endif

    SetPaused(false);
    b.EndArray();

    b.EndObject();
}
Пример #11
0
void
GPUMarkerPayload::streamPayloadImp(JSStreamWriter& b)
{
  b.BeginObject();
    streamCommonProps("gpu_timer_query", b);

    b.NameValue("cpustart", profiler_time(mCpuTimeStart));
    b.NameValue("cpuend", profiler_time(mCpuTimeEnd));
    b.NameValue("gpustart", (int)mGpuTimeStart);
    b.NameValue("gpuend", (int)mGpuTimeEnd);
  b.EndObject();
}
Пример #12
0
void ThreadProfile::StreamJSObject(JSStreamWriter& b)
{
  b.BeginObject();
    // Thread meta data
    if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
      // TODO Add the proper plugin name
      b.NameValue("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.
      b.NameValue("name", "Content");
    } else {
      b.NameValue("name", Name());
    }
    b.NameValue("tid", static_cast<int>(mThreadId));

    b.Name("samples");
    mBuffer->StreamSamplesToJSObject(b, mThreadId, mPseudoStack->mRuntime);

    b.Name("markers");
    mBuffer->StreamMarkersToJSObject(b, mThreadId);
  b.EndObject();
}
Пример #13
0
void TableTicker::StreamTaskTracer(JSStreamWriter& b)
{
  b.BeginObject();
#ifdef MOZ_TASK_TRACER
    b.Name("data");
    b.BeginArray();
      nsAutoPtr<nsTArray<nsCString>> data(
        mozilla::tasktracer::GetLoggedData(sStartTime));
      for (uint32_t i = 0; i < data->Length(); ++i) {
        b.Value((data->ElementAt(i)).get());
      }
    b.EndArray();

    b.Name("threads");
    b.BeginArray();
      mozilla::MutexAutoLock lock(*sRegisteredThreadsMutex);
      for (size_t i = 0; i < sRegisteredThreads->size(); i++) {
        // Thread meta data
        ThreadInfo* info = sRegisteredThreads->at(i);
        b.BeginObject();
        if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
          // TODO Add the proper plugin name
          b.NameValue("name", "Plugin");
        } else {
          b.NameValue("name", info->Name());
        }
        b.NameValue("tid", static_cast<int>(info->ThreadId()));
        b.EndObject();
      }
    b.EndArray();

    b.NameValue("start",
                static_cast<double>(mozilla::tasktracer::GetStartTime()));
#endif
  b.EndObject();
}
Пример #14
0
void ThreadProfile::StreamJSObject(JSStreamWriter& b)
{
  b.BeginObject();
    // Thread meta data
    if (XRE_GetProcessType() == GeckoProcessType_Plugin) {
      // TODO Add the proper plugin name
      b.NameValue("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.
      b.NameValue("name", "Content");
    } else {
      b.NameValue("name", Name());
    }
    b.NameValue("tid", static_cast<int>(mThreadId));

    b.Name("samples");
    b.BeginArray();

      bool sample = false;
      int readPos = mReadPos;
      while (readPos != mLastFlushPos) {
        // Number of tag consumed
        ProfileEntry entry = mEntries[readPos];

        switch (entry.mTagName) {
          case 'r':
            {
              if (sample) {
                b.NameValue("responsiveness", entry.mTagFloat);
              }
            }
            break;
          case 'p':
            {
              if (sample) {
                b.NameValue("power", entry.mTagFloat);
              }
            }
            break;
          case 'R':
            {
              if (sample) {
                b.NameValue("rss", entry.mTagFloat);
              }
            }
            break;
          case 'U':
            {
              if (sample) {
                b.NameValue("uss", entry.mTagFloat);
              }
            }
            break;
          case 'f':
            {
              if (sample) {
                b.NameValue("frameNumber", entry.mTagInt);
              }
            }
            break;
          case 't':
            {
              if (sample) {
                b.NameValue("time", entry.mTagFloat);
              }
            }
            break;
          case 's':
            {
              // end the previous sample if there was one
              if (sample) {
                b.EndObject();
              }
              // begin the next sample
              b.BeginObject();

              sample = true;

              // Seek forward through the entire sample, looking for frames
              // this is an easier approach to reason about than adding more
              // control variables and cases to the loop that goes through the buffer once
              b.Name("frames");
              b.BeginArray();

                b.BeginObject();
                  b.NameValue("location", "(root)");
                b.EndObject();

                int framePos = (readPos + 1) % mEntrySize;
                ProfileEntry frame = mEntries[framePos];
                while (framePos != mLastFlushPos && frame.mTagName != 's') {
                  int incBy = 1;
                  frame = mEntries[framePos];

                  // Read ahead to the next tag, if it's a 'd' tag process it now
                  const char* tagStringData = frame.mTagData;
                  int readAheadPos = (framePos + 1) % mEntrySize;
                  char tagBuff[DYNAMIC_MAX_STRING];
                  // Make sure the string is always null terminated if it fills up
                  // DYNAMIC_MAX_STRING-2
                  tagBuff[DYNAMIC_MAX_STRING-1] = '\0';

                  if (readAheadPos != mLastFlushPos && mEntries[readAheadPos].mTagName == 'd') {
                    tagStringData = processDynamicTag(framePos, &incBy, tagBuff);
                  }

                  // Write one frame. It can have either
                  // 1. only location - 'l' containing a memory address
                  // 2. location and line number - 'c' followed by 'd's,
                  // an optional 'n' and an optional 'y'
                  if (frame.mTagName == 'l') {
                    b.BeginObject();
                      // Bug 753041
                      // We need a double cast here to tell GCC that we don't want to sign
                      // extend 32-bit addresses starting with 0xFXXXXXX.
                      unsigned long long pc = (unsigned long long)(uintptr_t)frame.mTagPtr;
                      snprintf(tagBuff, DYNAMIC_MAX_STRING, "%#llx", pc);
                      b.NameValue("location", tagBuff);
                    b.EndObject();
                  } else if (frame.mTagName == 'c') {
                    b.BeginObject();
                      b.NameValue("location", tagStringData);
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mLastFlushPos &&
                          mEntries[readAheadPos].mTagName == 'n') {
                        b.NameValue("line", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mLastFlushPos &&
                          mEntries[readAheadPos].mTagName == 'y') {
                        b.NameValue("category", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                    b.EndObject();
                  }
                  framePos = (framePos + incBy) % mEntrySize;
                }
              b.EndArray();
            }
            break;
        }
        readPos = (readPos + 1) % mEntrySize;
      }
      if (sample) {
        b.EndObject();
      }
    b.EndArray();

    b.Name("markers");
    b.BeginArray();
      readPos = mReadPos;
      while (readPos != mLastFlushPos) {
        ProfileEntry entry = mEntries[readPos];
        if (entry.mTagName == 'm') {
           entry.getMarker()->StreamJSObject(b);
        }
        readPos = (readPos + 1) % mEntrySize;
      }
    b.EndArray();
  b.EndObject();
}
Пример #15
0
void TableTicker::StreamMetaJSCustomObject(JSStreamWriter& b)
{
  b.BeginObject();

    b.NameValue("version", 2);
    b.NameValue("interval", interval());
    b.NameValue("stackwalk", mUseStackWalk);
    b.NameValue("jank", mJankOnly);
    b.NameValue("processType", XRE_GetProcessType());

    TimeDuration delta = TimeStamp::Now() - sStartTime;
    b.NameValue("startTime", static_cast<float>(PR_Now()/1000.0 - delta.ToMilliseconds()));

    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))
        b.NameValue("platform", string.Data());

      res = http->GetOscpu(string);
      if (!NS_FAILED(res))
        b.NameValue("oscpu", string.Data());

      res = http->GetMisc(string);
      if (!NS_FAILED(res))
        b.NameValue("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))
        b.NameValue("abi", string.Data());

      res = runtime->GetWidgetToolkit(string);
      if (!NS_FAILED(res))
        b.NameValue("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))
        b.NameValue("product", string.Data());
    }

  b.EndObject();
}
Пример #16
0
static
void BuildJavaThreadJSObject(JSStreamWriter& b)
{
  b.BeginObject();

    b.NameValue("name", "Java Main Thread");

    b.Name("samples");
    b.BeginArray();

      // 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) {
                b.EndArray();
              b.EndObject();
            }
            break;
          }
          // the first time around, open the sample object and frames array
          if (firstRun) {
            firstRun = false;

            double sampleTime =
              mozilla::widget::android::GeckoJavaSampler::GetSampleTimeJavaProfiling(0, sampleId);

            b.BeginObject();
              b.NameValue("time", sampleTime);

              b.Name("frames");
              b.BeginArray();
          }
          // add a frame to the sample
          b.BeginObject();
            b.NameValue("location", result.BeginReading());
          b.EndObject();
        }
        // if we found no frames for this sample, we are done
        if (firstRun) {
          break;
        }
      }

    b.EndArray();

  b.EndObject();
}
Пример #17
0
void ProfileBuffer::StreamSamplesToJSObject(JSStreamWriter& b, int aThreadId, JSRuntime* rt)
{
  b.BeginArray();

    bool sample = false;
    int readPos = mReadPos;
    int currentThreadID = -1;
    while (readPos != mWritePos) {
      ProfileEntry entry = mEntries[readPos];
      if (entry.mTagName == 'T') {
        currentThreadID = entry.mTagInt;
      }
      if (currentThreadID == aThreadId) {
        switch (entry.mTagName) {
          case 'r':
            {
              if (sample) {
                b.NameValue("responsiveness", entry.mTagFloat);
              }
            }
            break;
          case 'p':
            {
              if (sample) {
                b.NameValue("power", entry.mTagFloat);
              }
            }
            break;
          case 'R':
            {
              if (sample) {
                b.NameValue("rss", entry.mTagFloat);
              }
            }
            break;
          case 'U':
            {
              if (sample) {
                b.NameValue("uss", entry.mTagFloat);
              }
            }
            break;
          case 'f':
            {
              if (sample) {
                b.NameValue("frameNumber", entry.mTagInt);
              }
            }
            break;
          case 't':
            {
              if (sample) {
                b.NameValue("time", entry.mTagFloat);
              }
            }
            break;
          case 's':
            {
              // end the previous sample if there was one
              if (sample) {
                b.EndObject();
              }
              // begin the next sample
              b.BeginObject();

              sample = true;

              // Seek forward through the entire sample, looking for frames
              // this is an easier approach to reason about than adding more
              // control variables and cases to the loop that goes through the buffer once
              b.Name("frames");
              b.BeginArray();

                b.BeginObject();
                  b.NameValue("location", "(root)");
                b.EndObject();

                int framePos = (readPos + 1) % mEntrySize;
                ProfileEntry frame = mEntries[framePos];
                while (framePos != mWritePos && frame.mTagName != 's' && frame.mTagName != 'T') {
                  int incBy = 1;
                  frame = mEntries[framePos];

                  // Read ahead to the next tag, if it's a 'd' tag process it now
                  const char* tagStringData = frame.mTagData;
                  int readAheadPos = (framePos + 1) % mEntrySize;
                  char tagBuff[DYNAMIC_MAX_STRING];
                  // Make sure the string is always null terminated if it fills up
                  // DYNAMIC_MAX_STRING-2
                  tagBuff[DYNAMIC_MAX_STRING-1] = '\0';

                  if (readAheadPos != mWritePos && mEntries[readAheadPos].mTagName == 'd') {
                    tagStringData = processDynamicTag(framePos, &incBy, tagBuff);
                  }

                  // Write one frame. It can have either
                  // 1. only location - 'l' containing a memory address
                  // 2. location and line number - 'c' followed by 'd's,
                  // an optional 'n' and an optional 'y'
                  if (frame.mTagName == 'l') {
                    b.BeginObject();
                      // Bug 753041
                      // We need a double cast here to tell GCC that we don't want to sign
                      // extend 32-bit addresses starting with 0xFXXXXXX.
                      unsigned long long pc = (unsigned long long)(uintptr_t)frame.mTagPtr;
                      snprintf(tagBuff, DYNAMIC_MAX_STRING, "%#llx", pc);
                      b.NameValue("location", tagBuff);
                    b.EndObject();
                  } else if (frame.mTagName == 'c') {
                    b.BeginObject();
                      b.NameValue("location", tagStringData);
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'n') {
                        b.NameValue("line", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'y') {
                        b.NameValue("category", mEntries[readAheadPos].mTagInt);
                        incBy++;
                      }
                      readAheadPos = (framePos + incBy) % mEntrySize;
                      if (readAheadPos != mWritePos &&
                          mEntries[readAheadPos].mTagName == 'J') {
                        void* pc = mEntries[readAheadPos].mTagPtr;

                        // TODOshu: cannot stream tracked optimization info if
                        // the JS engine has already shut down when streaming.
                        if (rt) {
                          JSScript *optsScript;
                          jsbytecode *optsPC;
                          b.Name("opts");
                          b.BeginArray();
                            StreamOptimizationTypeInfoOp typeInfoOp(b);
                            JS::ForEachTrackedOptimizationTypeInfo(rt, pc, typeInfoOp);
                            StreamOptimizationAttemptsOp attemptOp(b);
                            JS::ForEachTrackedOptimizationAttempt(rt, pc, attemptOp,
                                                                  &optsScript, &optsPC);
                          b.EndArray();
                          b.NameValue("optsLine", JS_PCToLineNumber(optsScript, optsPC));
                        }
                      }
                    b.EndObject();
                  }
                  framePos = (framePos + incBy) % mEntrySize;
                }
              b.EndArray();
            }
            break;
        }
      }
      readPos = (readPos + 1) % mEntrySize;
    }
    if (sample) {
      b.EndObject();
    }
  b.EndArray();
}