From a63ddf3f3aef710cbc3c82b6a4ad645917ed4bec Mon Sep 17 00:00:00 2001 From: wwwcg Date: Tue, 18 Jun 2024 22:54:20 +0800 Subject: [PATCH] fix(ios): performance api of FP not working --- .../base/bridge/HippyBridge+PerformanceAPI.h | 39 +++++++++++ .../base/bridge/HippyBridge+PerformanceAPI.mm | 64 +++++++++++++++++++ framework/ios/base/bridge/HippyBridge.mm | 52 +-------------- renderer/native/ios/renderer/HippyRootView.mm | 23 +++++-- .../component/view/HippyViewManager.mm | 7 ++ .../component/view/UIView+MountEvent.m | 2 + 6 files changed, 131 insertions(+), 56 deletions(-) create mode 100644 framework/ios/base/bridge/HippyBridge+PerformanceAPI.h create mode 100644 framework/ios/base/bridge/HippyBridge+PerformanceAPI.mm diff --git a/framework/ios/base/bridge/HippyBridge+PerformanceAPI.h b/framework/ios/base/bridge/HippyBridge+PerformanceAPI.h new file mode 100644 index 00000000000..ffd18976f27 --- /dev/null +++ b/framework/ios/base/bridge/HippyBridge+PerformanceAPI.h @@ -0,0 +1,39 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * 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. + */ + +#import "HippyBridge.h" +#import "HippyBridge+PerformanceAPI.h" + +NS_ASSUME_NONNULL_BEGIN + +/// Performance API Category of HippyBridge +@interface HippyBridge (PerformanceAPI) + +/// Update perf records of FP, DOM_START/DOM_END etc. +- (void)updatePerfRecordsOnRootContentDidAppear; + +/// Update FCP perf record. +- (void)updatePerfRecordOnFirstContentfulPaintEnd; + +@end + +NS_ASSUME_NONNULL_END diff --git a/framework/ios/base/bridge/HippyBridge+PerformanceAPI.mm b/framework/ios/base/bridge/HippyBridge+PerformanceAPI.mm new file mode 100644 index 00000000000..43ab28ee850 --- /dev/null +++ b/framework/ios/base/bridge/HippyBridge+PerformanceAPI.mm @@ -0,0 +1,64 @@ +/*! + * iOS SDK + * + * Tencent is pleased to support the open source community by making + * Hippy available. + * + * Copyright (C) 2019 THL A29 Limited, a Tencent company. + * All rights reserved. + * + * 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. + */ + +#import "HippyBridge+PerformanceAPI.h" +#import "HippyJSExecutor.h" +#import "driver/scope.h" + +@implementation HippyBridge (PerformanceAPI) + +- (void)updatePerfRecordsOnRootContentDidAppear { + std::shared_ptr scope = self.javaScriptExecutor.pScope; + if (!scope) { + return; + } + auto domManager = scope->GetDomManager().lock(); + auto performance = scope->GetPerformance(); + if (domManager && performance) { + auto entry = performance->PerformanceNavigation(hippy::kPerfNavigationHippyInit); + if (!entry) { + return; + } + entry->SetHippyDomStart(domManager->GetDomStartTimePoint()); + entry->SetHippyDomEnd(domManager->GetDomEndTimePoint()); + entry->SetHippyFirstFrameStart(domManager->GetDomEndTimePoint()); + entry->SetHippyFirstFrameEnd(footstone::TimePoint::SystemNow()); + } +} + +- (void)updatePerfRecordOnFirstContentfulPaintEnd { + std::shared_ptr scope = self.javaScriptExecutor.pScope; + if (!scope) { + return; + } + auto domManager = scope->GetDomManager().lock(); + auto performance = scope->GetPerformance(); + if (domManager && performance) { + auto entry = performance->PerformanceNavigation(hippy::kPerfNavigationHippyInit); + if (!entry) { + return; + } + entry->SetHippyFirstContentfulPaintEnd(footstone::TimePoint::SystemNow()); + } +} + +@end diff --git a/framework/ios/base/bridge/HippyBridge.mm b/framework/ios/base/bridge/HippyBridge.mm index cc8453289cb..3975c2cd3fe 100644 --- a/framework/ios/base/bridge/HippyBridge.mm +++ b/framework/ios/base/bridge/HippyBridge.mm @@ -241,10 +241,7 @@ - (instancetype)initWithDelegate:(id)delegate _startTime = footstone::TimePoint::SystemNow(); HippyLogInfo(@"HippyBridge init begin, self:%p", self); registerLogDelegateToHippyCore(); - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(rootViewContentDidAppear:) - name:HippyContentDidAppearNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onFirstContentfulPaintEnd:) - name:HippyFirstContentfulPaintEndNotification object:nil]; + HippyExecuteOnMainThread(^{ self->_isOSNightMode = [HippyDeviceBaseInfo isUIScreenInOSDarkMode]; self.cachedDimensionsInfo = hippyExportedDimensions(self); @@ -267,53 +264,6 @@ - (instancetype)initWithDelegate:(id)delegate return self; } -- (void)rootViewContentDidAppear:(NSNotification *)noti { - UIView *rootView = [noti object]; - if (rootView) { - auto viewRenderManager = [rootView renderManager]; - if (_renderManager && _renderManager == viewRenderManager.lock()) { - std::shared_ptr scope = _javaScriptExecutor.pScope; - if (!scope) { - return; - } - auto domManager = scope->GetDomManager().lock(); - auto performance = scope->GetPerformance(); - if (domManager && performance) { - auto entry = performance->PerformanceNavigation(hippy::kPerfNavigationHippyInit); - if (!entry) { - return; - } - entry->SetHippyDomStart(domManager->GetDomStartTimePoint()); - entry->SetHippyDomEnd(domManager->GetDomEndTimePoint()); - entry->SetHippyFirstFrameStart(domManager->GetDomEndTimePoint()); - entry->SetHippyFirstFrameEnd(footstone::TimePoint::SystemNow()); - } - } - } -} - -- (void)onFirstContentfulPaintEnd:(NSNotification *)noti { - UIView *fcpView = [noti object]; - if (fcpView) { - auto viewRenderManager = [fcpView renderManager]; - if (_renderManager && _renderManager == viewRenderManager.lock()) { - std::shared_ptr scope = _javaScriptExecutor.pScope; - if (!scope) { - return; - } - auto domManager = scope->GetDomManager().lock(); - auto performance = scope->GetPerformance(); - if (domManager && performance) { - auto entry = performance->PerformanceNavigation(hippy::kPerfNavigationHippyInit); - if (!entry) { - return; - } - entry->SetHippyFirstContentfulPaintEnd(footstone::TimePoint::SystemNow()); - } - } - } -} - - (void)dealloc { /** * This runs only on the main thread, but crashes the subclass diff --git a/renderer/native/ios/renderer/HippyRootView.mm b/renderer/native/ios/renderer/HippyRootView.mm index b99d9553c45..9b40d29c24b 100644 --- a/renderer/native/ios/renderer/HippyRootView.mm +++ b/renderer/native/ios/renderer/HippyRootView.mm @@ -26,6 +26,7 @@ #import "UIView+Hippy.h" #import "HippyInvalidating.h" #import "HippyBridge.h" +#import "Hippybridge+PerformanceAPI.h" #import "HippyUIManager.h" #import "HippyDeviceBaseInfo.h" #import "HippyTouchHandler.h" @@ -52,22 +53,34 @@ @interface HippyRootContentView : HippyView +/// Whether content has appeared @property (nonatomic, readonly) BOOL contentHasAppeared; +/// The Touch handler of RootView @property (nonatomic, strong) HippyTouchHandler *touchHandler; +/// timestamp of start @property (nonatomic, assign) int64_t startTimpStamp; +/// Init Method +/// - Parameters: +/// - frame: frame +/// - bridge: hippy bridge +/// - hippyTag: root tag +/// - sizeFlexibility: size flexibility for auto resize - (instancetype)initWithFrame:(CGRect)frame bridge:(HippyBridge *)bridge hippyTag:(NSNumber *)hippyTag sizeFlexiblity:(HippyRootViewSizeFlexibility)sizeFlexibility NS_DESIGNATED_INITIALIZER; -@end +/// Unvaliable, use designated initializer. +- (instancetype)init NS_UNAVAILABLE; +/// Unvaliable, use designated initializer. ++ (instancetype)new NS_UNAVAILABLE; +@end #pragma mark - HippyRootView @interface HippyRootView () { - BOOL _contentHasAppeared; BOOL _hasBusinessBundleToLoad; } @@ -409,17 +422,17 @@ - (void)hippySetFrame:(CGRect)frame { - (void)insertHippySubview:(UIView *)subview atIndex:(NSInteger)atIndex { [super insertHippySubview:subview atIndex:atIndex]; - // [_bridge.performanceLogger markStopForTag:HippyPLTTI]; __weak __typeof(self)weakSelf = self; dispatch_async(dispatch_get_main_queue(), ^{ __strong __typeof(weakSelf)strongSelf = weakSelf; if (strongSelf && !strongSelf->_contentHasAppeared) { strongSelf->_contentHasAppeared = YES; - // int64_t cost = [strongSelf.bridge.performanceLogger durationForTag:HippyPLTTI]; + static NSString *const kHippyContentAppearCostKey = @"cost"; + [[(HippyRootView *)strongSelf.superview bridge] updatePerfRecordsOnRootContentDidAppear]; [[NSNotificationCenter defaultCenter] postNotificationName:HippyContentDidAppearNotification object:self.superview userInfo:@{ - // @"cost": @(cost) + kHippyContentAppearCostKey : @(CACurrentMediaTime() * 1000 - strongSelf.startTimpStamp) }]; } }); diff --git a/renderer/native/ios/renderer/component/view/HippyViewManager.mm b/renderer/native/ios/renderer/component/view/HippyViewManager.mm index 7ff057335fd..c0e80e02415 100644 --- a/renderer/native/ios/renderer/component/view/HippyViewManager.mm +++ b/renderer/native/ios/renderer/component/view/HippyViewManager.mm @@ -205,6 +205,13 @@ - (void)measureInAppWindow:(NSNumber *)componentTag // Leave the implementation empty for now. } +HIPPY_EXPORT_METHOD(removeFrameCallback:(nonnull NSNumber *)hippyTag + params:(NSDictionary *__nonnull)params + callback:(HippyPromiseResolveBlock)callback) { + // For devtools + // Leave the implementation empty for now. +} + #pragma mark - View properties HIPPY_EXPORT_VIEW_PROPERTY(accessibilityLabel, NSString) diff --git a/renderer/native/ios/renderer/component/view/UIView+MountEvent.m b/renderer/native/ios/renderer/component/view/UIView+MountEvent.m index b9563fab4a2..92a3fb59121 100644 --- a/renderer/native/ios/renderer/component/view/UIView+MountEvent.m +++ b/renderer/native/ios/renderer/component/view/UIView+MountEvent.m @@ -24,6 +24,7 @@ #import "objc/runtime.h" #import "UIView+Hippy.h" #import "HippyRootView.h" +#import "HippyBridge+PerformanceAPI.h" /// The FCP Notification Imp const NSNotificationName HippyFirstContentfulPaintEndNotification = @"HippyFirstContentfulPaintEndNotification"; @@ -127,6 +128,7 @@ @implementation HippyRootView (PaintEventSupport) - (void)sendFCPNotiIfNeeded:(UIView *)fcpView { if (nil == objc_getAssociatedObject(self, @selector(sendFCPNotiIfNeeded:))) { objc_setAssociatedObject(self, @selector(sendFCPNotiIfNeeded:), @(YES), OBJC_ASSOCIATION_RETAIN); + [self.bridge updatePerfRecordOnFirstContentfulPaintEnd]; [NSNotificationCenter.defaultCenter postNotificationName:HippyFirstContentfulPaintEndNotification object:fcpView]; } }