mobile/android/base/GeckoJavaSampler.java

Wed, 31 Dec 2014 07:22:50 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:22:50 +0100
branch
TOR_BUG_3246
changeset 4
fc2d59ddac77
permissions
-rw-r--r--

Correct previous dual key logic pending first delivery installment.

     1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 4; indent-tabs-mode: nil; -*-
     2  * This Source Code Form is subject to the terms of the Mozilla Public
     3  * License, v. 2.0. If a copy of the MPL was not distributed with this
     4  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     6 package org.mozilla.gecko;
     8 import android.os.SystemClock;
     9 import android.util.Log;
    10 import android.util.SparseArray;
    12 import org.mozilla.gecko.mozglue.generatorannotations.WrapElementForJNI;
    14 import java.lang.Thread;
    15 import java.util.Set;
    17 public class GeckoJavaSampler {
    18     private static final String LOGTAG = "JavaSampler";
    19     private static Thread sSamplingThread = null;
    20     private static SamplingThread sSamplingRunnable = null;
    21     private static Thread sMainThread = null;
    22     private static volatile boolean sLibsLoaded = false;
    24     // Use the same timer primitive as the profiler
    25     // to get a perfect sample syncing.
    26     private static native double getProfilerTime();
    28     private static class Sample {
    29         public Frame[] mFrames;
    30         public double mTime;
    31         public long mJavaTime; // non-zero if Android system time is used
    32         public Sample(StackTraceElement[] aStack) {
    33             mFrames = new Frame[aStack.length];
    34             if (sLibsLoaded) {
    35                 mTime = getProfilerTime();
    36             }
    37             if (mTime == 0.0d) {
    38                 // getProfilerTime is not available yet; either libs are not loaded,
    39                 // or profiling hasn't started on the Gecko side yet
    40                 mJavaTime = SystemClock.elapsedRealtime();
    41             }
    42             for (int i = 0; i < aStack.length; i++) {
    43                 mFrames[aStack.length - 1 - i] = new Frame();
    44                 mFrames[aStack.length - 1 - i].fileName = aStack[i].getFileName();
    45                 mFrames[aStack.length - 1 - i].lineNo = aStack[i].getLineNumber();
    46                 mFrames[aStack.length - 1 - i].methodName = aStack[i].getMethodName();
    47                 mFrames[aStack.length - 1 - i].className = aStack[i].getClassName();
    48             }
    49         }
    50     }
    51     private static class Frame {
    52         public String fileName;
    53         public int lineNo;
    54         public String methodName;
    55         public String className;
    56     }
    58     private static class SamplingThread implements Runnable {
    59         private final int mInterval;
    60         private final int mSampleCount;
    62         private boolean mPauseSampler = false;
    63         private boolean mStopSampler = false;
    65         private SparseArray<Sample[]> mSamples = new SparseArray<Sample[]>();
    66         private int mSamplePos;
    68         public SamplingThread(final int aInterval, final int aSampleCount) {
    69             // If we sample faster then 10ms we get to many missed samples
    70             mInterval = Math.max(10, aInterval);
    71             mSampleCount = aSampleCount;
    72         }
    74         public void run() {
    75             synchronized (GeckoJavaSampler.class) {
    76                 mSamples.put(0, new Sample[mSampleCount]);
    77                 mSamplePos = 0;
    79                 // Find the main thread
    80                 Set<Thread> threadSet = Thread.getAllStackTraces().keySet();
    81                 for (Thread t : threadSet) {
    82                     if (t.getName().compareToIgnoreCase("main") == 0) {
    83                         sMainThread = t;
    84                         break;
    85                     }
    86                 }
    88                 if (sMainThread == null) {
    89                     Log.e(LOGTAG, "Main thread not found");
    90                     return;
    91                 }
    92             }
    94             while (true) {
    95                 try {
    96                     Thread.sleep(mInterval);
    97                 } catch (InterruptedException e) {
    98                     e.printStackTrace();
    99                 }
   100                 synchronized (GeckoJavaSampler.class) {
   101                     if (!mPauseSampler) {
   102                         StackTraceElement[] bt = sMainThread.getStackTrace();
   103                         mSamples.get(0)[mSamplePos] = new Sample(bt);
   104                         mSamplePos = (mSamplePos+1) % mSamples.get(0).length;
   105                     }
   106                     if (mStopSampler) {
   107                         break;
   108                     }
   109                 }
   110             }
   111         }
   113         private Sample getSample(int aThreadId, int aSampleId) {
   114             if (aThreadId < mSamples.size() && aSampleId < mSamples.get(aThreadId).length &&
   115                 mSamples.get(aThreadId)[aSampleId] != null) {
   116                 int startPos = 0;
   117                 if (mSamples.get(aThreadId)[mSamplePos] != null) {
   118                     startPos = mSamplePos;
   119                 }
   120                 int readPos = (startPos + aSampleId) % mSamples.get(aThreadId).length;
   121                 return mSamples.get(aThreadId)[readPos];
   122             }
   123             return null;
   124         }
   125     }
   128     @WrapElementForJNI(allowMultithread = true, stubName = "GetThreadNameJavaProfilingWrapper")
   129     public synchronized static String getThreadName(int aThreadId) {
   130         if (aThreadId == 0 && sMainThread != null) {
   131             return sMainThread.getName();
   132         }
   133         return null;
   134     }
   136     private synchronized static Sample getSample(int aThreadId, int aSampleId) {
   137         return sSamplingRunnable.getSample(aThreadId, aSampleId);
   138     }
   140     @WrapElementForJNI(allowMultithread = true, stubName = "GetSampleTimeJavaProfiling")
   141     public synchronized static double getSampleTime(int aThreadId, int aSampleId) {
   142         Sample sample = getSample(aThreadId, aSampleId);
   143         if (sample != null) {
   144             if (sample.mJavaTime != 0) {
   145                 return (double)(sample.mJavaTime -
   146                     SystemClock.elapsedRealtime()) + getProfilerTime();
   147             }
   148             System.out.println("Sample: " + sample.mTime);
   149             return sample.mTime;
   150         }
   151         return 0;
   152     }
   154     @WrapElementForJNI(allowMultithread = true, stubName = "GetFrameNameJavaProfilingWrapper")
   155     public synchronized static String getFrameName(int aThreadId, int aSampleId, int aFrameId) {
   156         Sample sample = getSample(aThreadId, aSampleId);
   157         if (sample != null && aFrameId < sample.mFrames.length) {
   158             Frame frame = sample.mFrames[aFrameId];
   159             if (frame == null) {
   160                 return null;
   161             }
   162             return frame.className + "." + frame.methodName + "()";
   163         }
   164         return null;
   165     }
   167     @WrapElementForJNI(allowMultithread = true, stubName = "StartJavaProfiling")
   168     public static void start(int aInterval, int aSamples) {
   169         synchronized (GeckoJavaSampler.class) {
   170             if (sSamplingRunnable != null) {
   171                 return;
   172             }
   173             sSamplingRunnable = new SamplingThread(aInterval, aSamples);
   174             sSamplingThread = new Thread(sSamplingRunnable, "Java Sampler");
   175             sSamplingThread.start();
   176         }
   177     }
   179     @WrapElementForJNI(allowMultithread = true, stubName = "PauseJavaProfiling")
   180     public static void pause() {
   181         synchronized (GeckoJavaSampler.class) {
   182             sSamplingRunnable.mPauseSampler = true;
   183         }
   184     }
   186     @WrapElementForJNI(allowMultithread = true, stubName = "UnpauseJavaProfiling")
   187     public static void unpause() {
   188         synchronized (GeckoJavaSampler.class) {
   189             sSamplingRunnable.mPauseSampler = false;
   190         }
   191     }
   193     @WrapElementForJNI(allowMultithread = true, stubName = "StopJavaProfiling")
   194     public static void stop() {
   195         synchronized (GeckoJavaSampler.class) {
   196             if (sSamplingThread == null) {
   197                 return;
   198             }
   200             sSamplingRunnable.mStopSampler = true;
   201             try {
   202                 sSamplingThread.join();
   203             } catch (InterruptedException e) {
   204                 e.printStackTrace();
   205             }
   206             sSamplingThread = null;
   207             sSamplingRunnable = null;
   208         }
   209     }
   211     public static void setLibsLoaded() {
   212         sLibsLoaded = true;
   213     }
   214 }

mercurial