1 /* -*- Mode: Java; c-basic-offset: 4; tab-width: 20; indent-tabs-mode: nil; -*-
2  * vim: ts=4 sw=4 expandtab:
3  * This Source Code Form is subject to the terms of the Mozilla Public
4  * License, v. 2.0. If a copy of the MPL was not distributed with this
5  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 
7 package org.mozilla.geckoview;
8 
9 import org.mozilla.gecko.GeckoJavaSampler;
10 
11 import androidx.annotation.Nullable;
12 import androidx.annotation.NonNull;
13 import androidx.annotation.UiThread;
14 
15 /**
16  * ProfilerController is used to manage GeckoProfiler related features.
17  *
18  * If you want to add a profiler marker to mark a point in time (without a duration)
19  * you can directly use <code>profilerController.addMarker("marker name")</code>.
20  * Or if you want to provide more information, you can use
21  * <code>profilerController.addMarker("marker name", "extra information")</code>
22  *
23  * If you want to add a profiler marker with a duration (with start and end time)
24  * you can use it like this:
25  * <code>
26  *     Double startTime = profilerController.getProfilerTime();
27  *     ...some code you want to measure...
28  *     profilerController.addMarker("name", startTime);
29  * </code>
30 
31  * Or you can capture start and end time in somewhere, then add the marker in somewhere
32  * else:
33  * <code>
34  *     Double startTime = profilerController.getProfilerTime();
35  *     ...some code you want to measure (or end time can be collected in a callback)...
36  *     Double endTime = profilerController.getProfilerTime();
37  *
38  *     ...somewhere else in the codebase...
39  *     profilerController.addMarker("name", startTime, endTime);
40  * </code>
41  *
42  * Here's an <code>addMarker</code> example with all the possible parameters:
43  * <code>
44  *     Double startTime = profilerController.getProfilerTime();
45  *     ...some code you want to measure...
46  *     Double endTime = profilerController.getProfilerTime();
47  *
48  *     ...somewhere else in the codebase...
49  *     profilerController.addMarker("name", startTime, endTime, "extra information");
50  * </code>
51  *
52  * <code>isProfilerActive</code> method is handy when you want to get more information to
53  * add inside the marker, but you think it's going to be computationally heavy (and useless)
54  * when profiler is not running:
55  * <pre>
56  * <code>
57  *     Double startTime = profilerController.getProfilerTime();
58  *     ...some code you want to measure...
59  *     if (profilerController.isProfilerActive()) {
60  *         String info = aFunctionYouDoNotWantToCallWhenProfilerIsNotActive();
61  *         profilerController.addMarker("name", startTime, info);
62  *     }
63  * </code>
64  * </pre>
65  *
66  * FIXME(bug 1618560): Currently only works in the main thread.
67  */
68 @UiThread
69 public class ProfilerController {
70     private static final String LOGTAG = "ProfilerController";
71 
72     /**
73      * Returns true if profiler is active and it's allowed the add markers.
74      * It's useful when it's computationally heavy to get startTime or the
75      * additional text for the marker. That code can be wrapped with
76      * isProfilerActive if check to reduce the overhead of it.
77      *
78      * @return true if profiler is active and safe to add a new marker.
79      */
isProfilerActive()80     public boolean isProfilerActive() {
81         return GeckoJavaSampler.isProfilerActive();
82     }
83 
84     /**
85      * Get the profiler time to be able to mark the start of the marker events.
86      * can be used like this:
87      *
88      * <code>
89      *     Double startTime = profilerController.getProfilerTime();
90      *     ...some code you want to measure...
91      *     profilerController.addMarker("name", startTime);
92      * </code>
93      *
94      * @return profiler time as double or null if the profiler is not active.
95      */
getProfilerTime()96     public @Nullable Double getProfilerTime() {
97         return GeckoJavaSampler.tryToGetProfilerTime();
98     }
99 
100     /**
101      * Add a profiler marker to Gecko Profiler with the given arguments.
102      * No-op if profiler is not active.
103      *
104      * @param aMarkerName Name of the event as a string.
105      * @param aStartTime Start time as Double. It can be null if you want to mark a point of time.
106      * @param aEndTime End time as Double. If it's null, this function implicitly gets the end time.
107      * @param aText An optional string field for more information about the marker.
108      */
addMarker(@onNull final String aMarkerName, @Nullable final Double aStartTime, @Nullable final Double aEndTime, @Nullable final String aText)109     public void addMarker(@NonNull final String aMarkerName,
110                           @Nullable final Double aStartTime,
111                           @Nullable final Double aEndTime,
112                           @Nullable final String aText) {
113         GeckoJavaSampler.addMarker(aMarkerName, aStartTime, aEndTime, aText);
114     }
115 
116     /**
117      * Add a profiler marker to Gecko Profiler with the given arguments.
118      * End time will be added automatically with the current profiler time when the function is called.
119      * No-op if profiler is not active.
120      * This is an overload of {@link #addMarker(String, Double, Double, String)} for convenience.
121      *
122      * @param aMarkerName Name of the event as a string.
123      * @param aStartTime Start time as Double. It can be null if you want to mark a point of time.
124      * @param aText An optional string field for more information about the marker.
125      */
addMarker(@onNull final String aMarkerName, @Nullable final Double aStartTime, @Nullable final String aText)126     public void addMarker(@NonNull final String aMarkerName,
127                           @Nullable final Double aStartTime,
128                           @Nullable final String aText) {
129         GeckoJavaSampler.addMarker(aMarkerName, aStartTime, null, aText);
130     }
131 
132     /**
133      * Add a profiler marker to Gecko Profiler with the given arguments.
134      * End time will be added automatically with the current profiler time when the function is called.
135      * No-op if profiler is not active.
136      * This is an overload of {@link #addMarker(String, Double, Double, String)} for convenience.
137      *
138      * @param aMarkerName Name of the event as a string.
139      * @param aStartTime Start time as Double. It can be null if you want to mark a point of time.
140      */
addMarker(@onNull final String aMarkerName, @Nullable final Double aStartTime)141     public void addMarker(@NonNull final String aMarkerName,
142                           @Nullable final Double aStartTime) {
143         addMarker(aMarkerName, aStartTime, null, null);
144     }
145 
146     /**
147      * Add a profiler marker to Gecko Profiler with the given arguments.
148      * Time will be added automatically with the current profiler time when the function is called.
149      * No-op if profiler is not active.
150      * This is an overload of {@link #addMarker(String, Double, Double, String)} for convenience.
151      *
152      * @param aMarkerName Name of the event as a string.
153      * @param aText An optional string field for more information about the marker.
154      */
addMarker(@onNull final String aMarkerName, @Nullable final String aText)155     public void addMarker(@NonNull final String aMarkerName, @Nullable final String aText) {
156         addMarker(aMarkerName, null, null, aText);
157     }
158 
159     /**
160      * Add a profiler marker to Gecko Profiler with the given arguments.
161      * Time will be added automatically with the current profiler time when the function is called.
162      * No-op if profiler is not active.
163      * This is an overload of {@link #addMarker(String, Double, Double, String)} for convenience.
164      *
165      * @param aMarkerName Name of the event as a string.
166      */
addMarker(@onNull final String aMarkerName)167     public void addMarker(@NonNull final String aMarkerName) {
168         addMarker(aMarkerName, null, null, null);
169     }
170 }
171