Android:Add PerformanceProfile
This commit is contained in:
parent
800365645c
commit
51719d3fc7
@ -19,8 +19,6 @@ import android.animation.AnimatorSet;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.text.TextUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import androidx.fragment.app.Fragment;
|
||||
|
||||
@ -37,6 +35,7 @@ import java.util.concurrent.Callable;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.navbar.IDoricNavBar;
|
||||
import pub.doric.navigator.IDoricNavigator;
|
||||
import pub.doric.performance.DoricPerformanceProfile;
|
||||
import pub.doric.plugin.DoricJavaPlugin;
|
||||
import pub.doric.shader.RootNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
@ -60,6 +59,7 @@ public class DoricContext {
|
||||
private JSONObject initParams;
|
||||
private IDoricDriver doricDriver;
|
||||
private final Map<String, Map<String, ViewNode>> mHeadNodes = new HashMap<>();
|
||||
private final DoricPerformanceProfile performanceProfile;
|
||||
|
||||
public Collection<ViewNode> allHeadNodes(String type) {
|
||||
return mHeadNodes.get(type).values();
|
||||
@ -107,6 +107,11 @@ public class DoricContext {
|
||||
this.mContextId = contextId;
|
||||
this.source = source;
|
||||
this.extra = extra;
|
||||
this.performanceProfile = new DoricPerformanceProfile(contextId);
|
||||
}
|
||||
|
||||
public DoricPerformanceProfile getPerformanceProfile() {
|
||||
return this.performanceProfile;
|
||||
}
|
||||
|
||||
public String getSource() {
|
||||
|
@ -21,6 +21,8 @@ import android.util.Log;
|
||||
|
||||
import com.github.pengfeizhou.jscore.JSDecoder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -28,6 +30,7 @@ import java.util.concurrent.Executors;
|
||||
import pub.doric.async.AsyncCall;
|
||||
import pub.doric.async.AsyncResult;
|
||||
import pub.doric.engine.DoricJSEngine;
|
||||
import pub.doric.performance.DoricPerformanceProfile;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.ThreadMode;
|
||||
|
||||
@ -82,7 +85,6 @@ public class DoricNativeDriver implements IDoricDriver {
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
|
||||
}
|
||||
});
|
||||
return asyncResult;
|
||||
@ -90,10 +92,38 @@ public class DoricNativeDriver implements IDoricDriver {
|
||||
|
||||
@Override
|
||||
public AsyncResult<JSDecoder> invokeDoricMethod(final String method, final Object... args) {
|
||||
DoricPerformanceProfile profile = null;
|
||||
Object contextId = args.length > 0 ? args[0] : null;
|
||||
if (contextId instanceof String) {
|
||||
DoricContext context = DoricContextManager.getContext((String) contextId);
|
||||
if (context != null) {
|
||||
profile = context.getPerformanceProfile();
|
||||
}
|
||||
}
|
||||
StringBuilder stringBuilder = new StringBuilder(DoricPerformanceProfile.STEP_Call)
|
||||
.append(":");
|
||||
for (Object object : args) {
|
||||
if (object == contextId) {
|
||||
continue;
|
||||
}
|
||||
stringBuilder.append(object.toString()).append(",");
|
||||
}
|
||||
final String anchorName = stringBuilder.toString();
|
||||
final DoricPerformanceProfile finalProfile = profile;
|
||||
if (finalProfile != null) {
|
||||
finalProfile.prepare(anchorName);
|
||||
}
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<JSDecoder>() {
|
||||
@Override
|
||||
public JSDecoder call() {
|
||||
return doricJSEngine.invokeDoricMethod(method, args);
|
||||
if (finalProfile != null) {
|
||||
finalProfile.start(anchorName);
|
||||
}
|
||||
JSDecoder decoder = doricJSEngine.invokeDoricMethod(method, args);
|
||||
if (finalProfile != null) {
|
||||
finalProfile.end(anchorName);
|
||||
}
|
||||
return decoder;
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -113,11 +143,15 @@ public class DoricNativeDriver implements IDoricDriver {
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> createContext(final String contextId, final String script, final String source) {
|
||||
final DoricPerformanceProfile performanceProfile = DoricContextManager.getContext(contextId).getPerformanceProfile();
|
||||
performanceProfile.prepare(DoricPerformanceProfile.STEP_CREATE);
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
performanceProfile.start(DoricPerformanceProfile.STEP_CREATE);
|
||||
doricJSEngine.prepareContext(contextId, script, source);
|
||||
performanceProfile.end(DoricPerformanceProfile.STEP_CREATE);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
doricJSEngine.getRegistry().onException(DoricContextManager.getContext(contextId), e);
|
||||
@ -130,11 +164,15 @@ public class DoricNativeDriver implements IDoricDriver {
|
||||
|
||||
@Override
|
||||
public AsyncResult<Boolean> destroyContext(final String contextId) {
|
||||
final DoricPerformanceProfile profile = DoricContextManager.getContext(contextId).getPerformanceProfile();
|
||||
profile.prepare(DoricPerformanceProfile.STEP_DESTROY);
|
||||
return AsyncCall.ensureRunInHandler(mJSHandler, new Callable<Boolean>() {
|
||||
@Override
|
||||
public Boolean call() {
|
||||
try {
|
||||
profile.start(DoricPerformanceProfile.STEP_DESTROY);
|
||||
doricJSEngine.destroyContext(contextId);
|
||||
profile.end(DoricPerformanceProfile.STEP_DESTROY);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
doricJSEngine.getRegistry().onException(DoricContextManager.getContext(contextId), e);
|
||||
|
@ -44,6 +44,7 @@ import pub.doric.DoricRegistry;
|
||||
import pub.doric.IDoricMonitor;
|
||||
import pub.doric.extension.bridge.DoricBridgeExtension;
|
||||
import pub.doric.extension.timer.DoricTimerExtension;
|
||||
import pub.doric.performance.DoricPerformanceProfile;
|
||||
import pub.doric.utils.DoricConstant;
|
||||
import pub.doric.utils.DoricLog;
|
||||
import pub.doric.utils.DoricUtils;
|
||||
@ -62,9 +63,11 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
|
||||
private boolean initialized = false;
|
||||
private final DoricRegistry mDoricRegistry;
|
||||
private final Map<String, Object> mEnvironmentMap = new ConcurrentHashMap<>();
|
||||
private final DoricPerformanceProfile globalProfile = new DoricPerformanceProfile("JSEngine");
|
||||
|
||||
public DoricJSEngine() {
|
||||
mDoricRegistry = new DoricRegistry(this);
|
||||
globalProfile.prepare(DoricPerformanceProfile.PART_INIT);
|
||||
handlerThread = new HandlerThread(this.getClass().getSimpleName());
|
||||
handlerThread.start();
|
||||
Looper looper = handlerThread.getLooper();
|
||||
@ -72,10 +75,12 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
|
||||
mJSHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
globalProfile.start(DoricPerformanceProfile.PART_INIT);
|
||||
initJSEngine();
|
||||
injectGlobal();
|
||||
initDoricRuntime();
|
||||
initialized = true;
|
||||
globalProfile.end(DoricPerformanceProfile.PART_INIT);
|
||||
}
|
||||
});
|
||||
mTimerExtension = new DoricTimerExtension(looper, this);
|
||||
@ -285,7 +290,7 @@ public class DoricJSEngine implements Handler.Callback, DoricTimerExtension.Time
|
||||
values.add(DoricUtils.toJavaValue(arg));
|
||||
}
|
||||
return mDoricJSE.invokeMethod(DoricConstant.GLOBAL_DORIC, method,
|
||||
values.toArray(new JavaValue[values.size()]), false);
|
||||
values.toArray(new JavaValue[0]), false);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package pub.doric.performance;
|
||||
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* @Description: pub.doric.performance
|
||||
* @Author: pengfei.zhou
|
||||
* @CreateDate: 3/29/21
|
||||
*/
|
||||
public class DoricPerformanceProfile {
|
||||
private static final String TAG = DoricPerformanceProfile.class.getSimpleName();
|
||||
public static final String PART_INIT = "Init";
|
||||
public static final String STEP_CREATE = "Create";
|
||||
public static final String STEP_Call = "Call";
|
||||
public static final String STEP_DESTROY = "Destroy";
|
||||
public static final String STEP_RENDER = "Render";
|
||||
private static final String MARK_PREPARE = "prepare";
|
||||
private static final String MARK_START = "start";
|
||||
private static final String MARK_END = "end";
|
||||
private final String name;
|
||||
|
||||
private static final boolean DEBUG = true;
|
||||
|
||||
public DoricPerformanceProfile(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
private final Map<String, Long> anchorMap = new ConcurrentHashMap<>();
|
||||
|
||||
private void markAnchor(String eventName) {
|
||||
if (DEBUG) {
|
||||
anchorMap.put(eventName, System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
|
||||
private String getPrepareAnchor(String anchorName) {
|
||||
return anchorName + "#" + MARK_PREPARE;
|
||||
}
|
||||
|
||||
private String getStartAnchor(String anchorName) {
|
||||
return anchorName + "#" + MARK_START;
|
||||
}
|
||||
|
||||
private String getEndAnchor(String anchorName) {
|
||||
return anchorName + "#" + MARK_END;
|
||||
}
|
||||
|
||||
public void prepare(String anchorName) {
|
||||
markAnchor(getPrepareAnchor(anchorName));
|
||||
}
|
||||
|
||||
public void start(String anchorName) {
|
||||
markAnchor(getStartAnchor(anchorName));
|
||||
}
|
||||
|
||||
public void end(String anchorName) {
|
||||
markAnchor(getEndAnchor(anchorName));
|
||||
if (DEBUG) {
|
||||
print(anchorName);
|
||||
}
|
||||
}
|
||||
|
||||
private void print(String anchorName) {
|
||||
Long prepare = anchorMap.get(getPrepareAnchor(anchorName));
|
||||
Long start = anchorMap.get(getStartAnchor(anchorName));
|
||||
Long end = anchorMap.get(getEndAnchor(anchorName));
|
||||
if (end == null) {
|
||||
end = System.currentTimeMillis();
|
||||
}
|
||||
if (start == null) {
|
||||
start = end;
|
||||
}
|
||||
if (prepare == null) {
|
||||
prepare = start;
|
||||
}
|
||||
Log.d(TAG, String.format("%s: %s prepared %dms, cost %dms.",
|
||||
name, anchorName, start - prepare, end - start));
|
||||
}
|
||||
}
|
@ -34,6 +34,7 @@ import pub.doric.async.AsyncResult;
|
||||
import pub.doric.extension.bridge.DoricMethod;
|
||||
import pub.doric.extension.bridge.DoricPlugin;
|
||||
import pub.doric.extension.bridge.DoricPromise;
|
||||
import pub.doric.performance.DoricPerformanceProfile;
|
||||
import pub.doric.shader.RootNode;
|
||||
import pub.doric.shader.SuperNode;
|
||||
import pub.doric.shader.ViewNode;
|
||||
@ -54,9 +55,13 @@ public class ShaderPlugin extends DoricJavaPlugin {
|
||||
|
||||
@DoricMethod
|
||||
public void render(final JSObject jsObject, final DoricPromise promise) {
|
||||
final DoricPerformanceProfile profile = getDoricContext().getPerformanceProfile();
|
||||
profile.prepare(DoricPerformanceProfile.STEP_RENDER);
|
||||
getDoricContext().getDriver().asyncCall(new Callable<Object>() {
|
||||
@Override
|
||||
public Object call() throws Exception {
|
||||
profile.start(DoricPerformanceProfile.STEP_RENDER);
|
||||
|
||||
if (getDoricContext().getContext() instanceof Activity) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1
|
||||
&& ((Activity) getDoricContext().getContext()).isDestroyed()) {
|
||||
@ -110,6 +115,7 @@ public class ShaderPlugin extends DoricJavaPlugin {
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
profile.end(DoricPerformanceProfile.STEP_RENDER);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
Reference in New Issue
Block a user