From 5dadf62203e1603cb574aabc07ee8b68f11e7cca Mon Sep 17 00:00:00 2001 From: maxli Date: Sun, 29 Sep 2024 15:18:38 +0800 Subject: [PATCH] fix(android): support work reuse with group id --- .../src/main/cpp/include/connector/dom_jni.h | 2 +- .../connector/dom/src/main/cpp/src/dom_jni.cc | 53 ++++++++++++++----- .../com/openhippy/connector/DomManager.java | 51 ++++++++++++++++-- .../js/src/main/cpp/src/js_driver_jni.cc | 1 + .../mtt/hippy/HippyEngineManagerImpl.java | 3 +- .../openhippy/example/HippyEngineWrapper.kt | 1 + modules/footstone/include/footstone/worker.h | 7 +++ modules/footstone/src/worker.cc | 1 + 8 files changed, 98 insertions(+), 21 deletions(-) diff --git a/framework/android/connector/dom/src/main/cpp/include/connector/dom_jni.h b/framework/android/connector/dom/src/main/cpp/include/connector/dom_jni.h index 1879ab136c3..1a3d8f835a6 100644 --- a/framework/android/connector/dom/src/main/cpp/include/connector/dom_jni.h +++ b/framework/android/connector/dom/src/main/cpp/include/connector/dom_jni.h @@ -29,7 +29,7 @@ inline namespace framework { inline namespace connector { inline namespace dom { -jint CreateDomManager(JNIEnv* j_env, __unused jobject j_obj); +jint CreateDomManager(JNIEnv* j_env, __unused jobject j_obj, jint j_group_id, jint j_share_dom_id); void DestroyDomManager(JNIEnv* j_env, __unused jobject j_obj, diff --git a/framework/android/connector/dom/src/main/cpp/src/dom_jni.cc b/framework/android/connector/dom/src/main/cpp/src/dom_jni.cc index 534ce835ec1..0c5021a3b47 100644 --- a/framework/android/connector/dom/src/main/cpp/src/dom_jni.cc +++ b/framework/android/connector/dom/src/main/cpp/src/dom_jni.cc @@ -41,7 +41,7 @@ inline namespace dom { REGISTER_JNI("com/openhippy/connector/DomManager", // NOLINT(cert-err58-cpp) "createDomManager", - "()I", + "(II)I", CreateDomManager) REGISTER_JNI("com/openhippy/connector/DomManager", // NOLINT(cert-err58-cpp) @@ -79,6 +79,7 @@ using TaskRunner = footstone::TaskRunner; constexpr char kDomWorkerName[] = "dom_worker"; constexpr char kDomRunnerName[] = "dom_task_runner"; +constexpr int32_t kDefaultGroupId = -1; void CreateRoot(JNIEnv* j_env, __unused jobject j_obj, @@ -151,21 +152,41 @@ static void SetThreadPriority(jobject j_object) { j_env->DeleteLocalRef(j_class); } -jint CreateDomManager(JNIEnv* j_env, jobject j_obj) { +jint CreateDomManager(JNIEnv* j_env, jobject j_obj, jint j_group_id, jint j_share_dom_id) { auto dom_manager = std::make_shared(); auto dom_id = hippy::global_data_holder_key.fetch_add(1); hippy::global_data_holder.Insert(dom_id, dom_manager); - auto worker = std::make_shared(kDomWorkerName, false); - auto callback = std::make_shared(j_env, j_obj); - worker->BeforeStart([callback]() { - if (callback->GetObj()) SetThreadPriority(callback->GetObj()); - }); - worker->Start(); - auto runner = std::make_shared(kDomRunnerName); - runner->SetWorker(worker); - worker->Bind({runner}); - dom_manager->SetTaskRunner(runner); - dom_manager->SetWorker(worker); + auto group_id = footstone::checked_numeric_cast(j_group_id); + auto share_dom_id = footstone::checked_numeric_cast(j_share_dom_id); + std::any share_dom_manager; + bool flag = false; + if (share_dom_id > 0) { + flag = hippy::global_data_holder.Find(static_cast(share_dom_id), share_dom_manager); + } + FOOTSTONE_DLOG(ERROR) << "CreateDomManager flag " << flag << ", dom_id " << dom_id << ", share_dom_id " << share_dom_id; + if (flag && group_id != kDefaultGroupId) { + FOOTSTONE_DLOG(ERROR) << "CreateDomManager share "; + auto dom_manager_object = std::any_cast>(share_dom_manager); + auto worker = dom_manager_object->GetWorker(); + auto runner = dom_manager_object->GetTaskRunner(); + dom_manager->SetTaskRunner(runner); + dom_manager->SetWorker(worker); + auto count = worker->FetchAndAddReuseCount(); + FOOTSTONE_DLOG(ERROR) << "CreateDomManager worker reuse count " << count << ", dom manager id " << dom_id; + } else { + FOOTSTONE_DLOG(ERROR) << "CreateDomManager create new "; + auto worker = std::make_shared(kDomWorkerName, false); + auto callback = std::make_shared(j_env, j_obj); + worker->BeforeStart([callback]() { + if (callback->GetObj()) SetThreadPriority(callback->GetObj()); + }); + worker->Start(); + auto runner = std::make_shared(kDomRunnerName); + runner->SetWorker(worker); + worker->Bind({runner}); + dom_manager->SetTaskRunner(runner); + dom_manager->SetWorker(worker); + } return footstone::checked_numeric_cast(dom_id); } @@ -175,7 +196,11 @@ void DestroyDomManager(__unused JNIEnv* j_env, __unused jobject j_obj, jint j_do auto flag = hippy::global_data_holder.Find(dom_manager_id, dom_manager); FOOTSTONE_CHECK(flag); auto dom_manager_object = std::any_cast>(dom_manager); - dom_manager_object->GetWorker()->Terminate(); + auto count = dom_manager_object->GetWorker()->FetchAndSubReuseCount(); + FOOTSTONE_DLOG(ERROR) << "DestroyDomManager worker reuse count " << count << ", dom manager id " << dom_manager_id; + if (count == 0) { + dom_manager_object->GetWorker()->Terminate(); + } flag = hippy::global_data_holder.Erase(dom_manager_id); FOOTSTONE_DCHECK(flag); } diff --git a/framework/android/connector/dom/src/main/java/com/openhippy/connector/DomManager.java b/framework/android/connector/dom/src/main/java/com/openhippy/connector/DomManager.java index 76b3f52cdfd..eb0590251ef 100644 --- a/framework/android/connector/dom/src/main/java/com/openhippy/connector/DomManager.java +++ b/framework/android/connector/dom/src/main/java/com/openhippy/connector/DomManager.java @@ -19,19 +19,29 @@ import android.view.View; import androidx.annotation.NonNull; import android.os.Process; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; @SuppressWarnings("JavaJniMissingFunction") public class DomManager implements Connector { private final int mInstanceId; - - public DomManager() { - mInstanceId = createDomManager(); + private final int mGroupId; + private static final Map> sDomManagerGroup = new HashMap<>(); + + public DomManager(int groupId) { + int shareDomId = DomManager.getDomIdFromGroup(groupId); + mInstanceId = createDomManager(groupId, shareDomId); + mGroupId = groupId; + addDomManagerToGroup(); } @Override public void destroy() { destroyDomManager(mInstanceId); + removeDomManagerFromGroup(); } @Override @@ -39,6 +49,39 @@ public int getInstanceId() { return mInstanceId; } + public static int getDomIdFromGroup(int groupId) { + List group = sDomManagerGroup.get(groupId); + if (group == null || group.isEmpty()) { + return -1; + } + return group.get(0); + } + + private void removeDomManagerFromGroup() { + List group = sDomManagerGroup.get(mGroupId); + if (group != null) { + try { + group.remove(Integer.valueOf(mInstanceId)); + } catch (Exception e) { + e.printStackTrace(); + } + } + } + + private void addDomManagerToGroup() { + if (mGroupId < 0) { + return; + } + List group = sDomManagerGroup.get(mGroupId); + if (group == null) { + group = new ArrayList<>(); + group.add(mInstanceId); + sDomManagerGroup.put(mGroupId, group); + } else { + group.add(mInstanceId); + } + } + public void attachToRenderer(@NonNull Connector rendererConnector) { onAttachToRenderer(mInstanceId, rendererConnector.getInstanceId()); } @@ -74,7 +117,7 @@ public void setThreadPrority() { * * @return the unique id of native (C++) dom manager */ - private native int createDomManager(); + private native int createDomManager(int groupId, int shareDomId); /** * Release native (C++) dom manager instance. diff --git a/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc b/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc index 3995a6d6781..5f7011a49d3 100644 --- a/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc +++ b/framework/android/connector/driver/js/src/main/cpp/src/js_driver_jni.cc @@ -315,6 +315,7 @@ jint CreateJsDriver(JNIEnv* j_env, auto param = std::make_shared(); param->enable_v8_serialization = static_cast(j_enable_v8_serialization); param->is_debug = static_cast(j_is_dev_module); + param->group_id = static_cast(j_group_id); if (j_vm_init_param) { jclass cls = j_env->GetObjectClass(j_vm_init_param); jfieldID init_field = j_env->GetFieldID(cls, "initialHeapSize", "J"); diff --git a/framework/android/src/main/java/com/tencent/mtt/hippy/HippyEngineManagerImpl.java b/framework/android/src/main/java/com/tencent/mtt/hippy/HippyEngineManagerImpl.java index a8249d6f0c0..5eea31752ab 100644 --- a/framework/android/src/main/java/com/tencent/mtt/hippy/HippyEngineManagerImpl.java +++ b/framework/android/src/main/java/com/tencent/mtt/hippy/HippyEngineManagerImpl.java @@ -73,7 +73,6 @@ import com.tencent.mtt.hippy.views.modal.HippyModalHostManager; import com.tencent.mtt.hippy.views.modal.HippyModalHostView; import com.tencent.renderer.FrameworkProxy; -import com.tencent.renderer.NativeRenderContext; import com.tencent.renderer.component.image.ImageDecoderAdapter; import com.tencent.renderer.component.text.FontAdapter; import com.tencent.renderer.node.RenderNode; @@ -881,7 +880,7 @@ public HippyEngineContextImpl(@Nullable DomManager domManager) throws RuntimeExc mBridgeManager = new HippyBridgeManagerImpl(this, mCoreBundleLoader, getBridgeType(), enableV8Serialization, mDebugMode, mServerHost, mGroupId, mThirdPartyAdapter, v8InitParams, mJsDriver); - mDomManager = (domManager != null) ? domManager : new DomManager(); + mDomManager = (domManager != null) ? domManager : new DomManager(mGroupId); mRenderer = createRenderer(RenderConnector.NATIVE_RENDERER); mDomManager.attachToRenderer(mRenderer); mRenderer.attachToDom(mDomManager); diff --git a/framework/examples/android-demo/src/main/java/com/openhippy/example/HippyEngineWrapper.kt b/framework/examples/android-demo/src/main/java/com/openhippy/example/HippyEngineWrapper.kt index ea38d5ce1d1..193b0e9056c 100644 --- a/framework/examples/android-demo/src/main/java/com/openhippy/example/HippyEngineWrapper.kt +++ b/framework/examples/android-demo/src/main/java/com/openhippy/example/HippyEngineWrapper.kt @@ -66,6 +66,7 @@ class HippyEngineWrapper//TODO: Coming soon initParams.debugMode = isDebug initParams.enableLog = true initParams.logAdapter = DefaultLogAdapter() + initParams.groupId = 1 when(driverMode) { PageConfiguration.DriverMode.JS_REACT -> { initParams.coreJSAssetsPath = "react/vendor.android.js" diff --git a/modules/footstone/include/footstone/worker.h b/modules/footstone/include/footstone/worker.h index ff560310498..31134f8b3b9 100644 --- a/modules/footstone/include/footstone/worker.h +++ b/modules/footstone/include/footstone/worker.h @@ -75,6 +75,12 @@ class Worker { inline void SetGroupId(uint32_t id) { group_id_ = id; } + inline uint32_t FetchAndSubReuseCount() { + return --reuse_count_; + } + inline uint32_t FetchAndAddReuseCount() { + return ++reuse_count_; + } static bool IsTaskRunning(); bool RunTask(); void BeforeStart(std::function before_start) { before_start_ = before_start; } @@ -131,6 +137,7 @@ class Worker { * 不同TaskRunner切换的开销越大,则每个task从加入到执行的延迟可能就越大。 */ bool is_schedulable_; + uint32_t reuse_count_; uint32_t group_id_; std::unique_ptr driver_; }; diff --git a/modules/footstone/src/worker.cc b/modules/footstone/src/worker.cc index 5628dd72157..b6b8e5fd9e3 100644 --- a/modules/footstone/src/worker.cc +++ b/modules/footstone/src/worker.cc @@ -55,6 +55,7 @@ Worker::Worker(std::string name, bool is_schedulable, std::unique_ptr dr is_stacking_mode_(false), has_migration_data_(false), is_schedulable_(is_schedulable), + reuse_count_(1), group_id_(0), driver_(std::move(driver)) { }