3838NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
3939NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @" ASRenderingEngineDidDisplayScheduledNodes" ;
4040NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @" ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp" ;
41+ NSString * const ASDisplayNodeLayoutSpecTotalTimeKey = @" ASDisplayNodeLayoutSpecTotalTime" ;
42+ NSString * const ASDisplayNodeLayoutSpecNumberOfPassesKey = @" ASDisplayNodeLayoutSpecNumberOfPasses" ;
43+ NSString * const ASDisplayNodeLayoutGenerationTotalTimeKey = @" ASDisplayNodeLayoutGenerationTotalTime" ;
44+ NSString * const ASDisplayNodeLayoutGenerationNumberOfPassesKey = @" ASDisplayNodeLayoutGenerationNumberOfPasses" ;
45+
4146
4247// Forward declare CALayerDelegate protocol as the iOS 10 SDK moves CALayerDelegate from a formal delegate to a protocol.
4348// We have to forward declare the protocol as this place otherwise it will not compile compiling with an Base SDK < iOS 10
@@ -1156,6 +1161,33 @@ - (void)calculatedLayoutDidChange
11561161 // subclass override
11571162}
11581163
1164+ - (void )setMeasurementOptions : (ASDisplayNodePerformanceMeasurementOptions)measurementOptions
1165+ {
1166+ ASDN::MutexLocker l (__instanceLock__);
1167+ _measurementOptions = measurementOptions;
1168+ }
1169+
1170+ - (ASDisplayNodePerformanceMeasurementOptions)measurementOptions
1171+ {
1172+ ASDN::MutexLocker l (__instanceLock__);
1173+ return _measurementOptions;
1174+ }
1175+
1176+ - (NSDictionary *)performanceMeasurements
1177+ {
1178+ ASDN::MutexLocker l (__instanceLock__);
1179+ NSMutableDictionary *measurements = [NSMutableDictionary dictionaryWithCapacity: 4 ];
1180+ if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec) {
1181+ measurements[ASDisplayNodeLayoutSpecTotalTimeKey] = @(_layoutSpecTotalTime);
1182+ measurements[ASDisplayNodeLayoutSpecNumberOfPassesKey] = @(_layoutSpecNumberOfPasses);
1183+ }
1184+ if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutGeneration) {
1185+ measurements[ASDisplayNodeLayoutGenerationTotalTimeKey] = @(_layoutGenerationTotalTime);
1186+ measurements[ASDisplayNodeLayoutGenerationNumberOfPassesKey] = @(_layoutGenerationNumberOfPasses);
1187+ }
1188+ return measurements;
1189+ }
1190+
11591191#pragma mark - Asynchronous display
11601192
11611193- (BOOL )displaysAsynchronously
@@ -2343,8 +2375,16 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
23432375
23442376 ASDN::MutexLocker l (__instanceLock__);
23452377 if ((_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) || _layoutSpecBlock != NULL ) {
2346- ASLayoutSpec *layoutSpec = [self layoutSpecThatFits: constrainedSize];
2347-
2378+ ASLayoutSpec *layoutSpec = nil ;
2379+ // optional performance measurement for cell nodes
2380+ if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec) {
2381+ ASDN::SumScopeTimer t (_layoutSpecTotalTime);
2382+ _layoutSpecNumberOfPasses++;
2383+ layoutSpec = [self layoutSpecThatFits: constrainedSize];
2384+ } else {
2385+ layoutSpec = [self layoutSpecThatFits: constrainedSize];
2386+ }
2387+
23482388 ASDisplayNodeAssert (layoutSpec.isMutable , @" Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated." , self, layoutSpec);
23492389
23502390 layoutSpec.parent = self; // This causes upward propogation of any non-default layoutable values.
@@ -2353,7 +2393,16 @@ - (ASLayout *)calculateLayoutThatFits:(ASSizeRange)constrainedSize
23532393 ASEnvironmentStatePropagateDown (layoutSpec, self.environmentTraitCollection );
23542394
23552395 layoutSpec.isMutable = NO ;
2356- ASLayout *layout = [layoutSpec layoutThatFits: constrainedSize];
2396+ ASLayout *layout = nil ;
2397+ // optional performance measurement for cell nodes
2398+ if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutGeneration) {
2399+ ASDN::SumScopeTimer t (_layoutGenerationTotalTime);
2400+ _layoutGenerationNumberOfPasses++;
2401+ layout = [layoutSpec layoutThatFits: constrainedSize];
2402+ } else {
2403+ layout = [layoutSpec layoutThatFits: constrainedSize];
2404+ }
2405+
23572406 ASDisplayNodeAssertNotNil (layout, @" [ASLayoutSpec measureWithSizeRange:] should never return nil! %@ , %@ " , self, layoutSpec);
23582407
23592408 // Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct.
0 commit comments