Revise performance measurement naming and structure (#2265)

* Revise performance measurement naming and structure

- Revises naming from LayoutSpecGeneration to LayoutSpecComputation
- Adds a struct instead of an NSDictionary to retrieve performance metrics
- Includes ASEnvironmentStatePropagateDown in LayoutSpecComputation measurements

* Revise SumScopeTimer to include enable flag

* Make struct a typedef
This commit is contained in:
Harry Shamansky
2016-09-20 12:39:09 -07:00
committed by Adlai Holler
parent 5990376f68
commit 71fc2dd18d
4 changed files with 46 additions and 45 deletions

View File

@@ -38,16 +38,15 @@ ASDISPLAYNODE_EXTERN_C_END
*/
typedef NS_OPTIONS(NSUInteger, ASDisplayNodePerformanceMeasurementOptions) {
ASDisplayNodePerformanceMeasurementOptionLayoutSpec = 1 << 0,
ASDisplayNodePerformanceMeasurementOptionLayoutGeneration = 1 << 1
ASDisplayNodePerformanceMeasurementOptionLayoutComputation = 1 << 1
};
/**
* Keys to retrieve performance entries from the performance dictionary.
*/
extern NSString *const ASDisplayNodeLayoutSpecTotalTimeKey;
extern NSString *const ASDisplayNodeLayoutSpecNumberOfPassesKey;
extern NSString *const ASDisplayNodeLayoutGenerationTotalTimeKey;
extern NSString *const ASDisplayNodeLayoutGenerationNumberOfPassesKey;
typedef struct {
CFTimeInterval layoutSpecTotalTime;
NSInteger layoutSpecNumberOfPasses;
CFTimeInterval layoutComputationTotalTime;
NSInteger layoutComputationNumberOfPasses;
} ASDisplayNodePerformanceMeasurements;
@interface ASDisplayNode (Beta)
@@ -94,10 +93,9 @@ extern NSString *const ASDisplayNodeLayoutGenerationNumberOfPassesKey;
@property (nonatomic, assign) ASDisplayNodePerformanceMeasurementOptions measurementOptions;
/**
* @abstract A dictionary representing performance measurements collected.
* @note see the constants above to retrieve relevant performance measurements
* @abstract A simple struct representing performance measurements collected.
*/
@property (nonatomic, strong, readonly) NSDictionary *performanceMeasurements;
@property (nonatomic, assign, readonly) ASDisplayNodePerformanceMeasurements performanceMeasurements;
/** @name Layout Transitioning */

View File

@@ -38,11 +38,6 @@
NSInteger const ASDefaultDrawingPriority = ASDefaultTransactionPriority;
NSString * const ASRenderingEngineDidDisplayScheduledNodesNotification = @"ASRenderingEngineDidDisplayScheduledNodes";
NSString * const ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp = @"ASRenderingEngineDidDisplayNodesScheduledBeforeTimestamp";
NSString * const ASDisplayNodeLayoutSpecTotalTimeKey = @"ASDisplayNodeLayoutSpecTotalTime";
NSString * const ASDisplayNodeLayoutSpecNumberOfPassesKey = @"ASDisplayNodeLayoutSpecNumberOfPasses";
NSString * const ASDisplayNodeLayoutGenerationTotalTimeKey = @"ASDisplayNodeLayoutGenerationTotalTime";
NSString * const ASDisplayNodeLayoutGenerationNumberOfPassesKey = @"ASDisplayNodeLayoutGenerationNumberOfPasses";
// Forward declare CALayerDelegate protocol as the iOS 10 SDK moves CALayerDelegate from a formal delegate to a protocol.
// We have to forward declare the protocol as this place otherwise it will not compile compiling with an Base SDK < iOS 10
@@ -1227,17 +1222,17 @@ ASLayoutableSizeHelperForwarding
return _measurementOptions;
}
- (NSDictionary *)performanceMeasurements
- (ASDisplayNodePerformanceMeasurements)performanceMeasurements
{
ASDN::MutexLocker l(__instanceLock__);
NSMutableDictionary *measurements = [NSMutableDictionary dictionaryWithCapacity:4];
ASDisplayNodePerformanceMeasurements measurements = { .layoutSpecNumberOfPasses = -1, .layoutSpecTotalTime = NAN, .layoutComputationNumberOfPasses = -1, .layoutComputationTotalTime = NAN };
if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec) {
measurements[ASDisplayNodeLayoutSpecTotalTimeKey] = @(_layoutSpecTotalTime);
measurements[ASDisplayNodeLayoutSpecNumberOfPassesKey] = @(_layoutSpecNumberOfPasses);
measurements.layoutSpecNumberOfPasses = _layoutSpecNumberOfPasses;
measurements.layoutSpecTotalTime = _layoutSpecTotalTime;
}
if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutGeneration) {
measurements[ASDisplayNodeLayoutGenerationTotalTimeKey] = @(_layoutGenerationTotalTime);
measurements[ASDisplayNodeLayoutGenerationNumberOfPassesKey] = @(_layoutGenerationNumberOfPasses);
if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutComputation) {
measurements.layoutComputationNumberOfPasses = _layoutComputationNumberOfPasses;
measurements.layoutComputationTotalTime = _layoutComputationTotalTime;
}
return measurements;
}
@@ -2433,34 +2428,37 @@ void recursivelyTriggerDisplayForLayer(CALayer *layer, BOOL shouldBlock)
ASDN::MutexLocker l(__instanceLock__);
if ((_methodOverrides & ASDisplayNodeMethodOverrideLayoutSpecThatFits) || _layoutSpecBlock != NULL) {
ASLayoutSpec *layoutSpec = nil;
// optional performance measurement for cell nodes
if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec) {
ASDN::SumScopeTimer t(_layoutSpecTotalTime);
BOOL measureLayoutSpec = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutSpec;
if (measureLayoutSpec) {
_layoutSpecNumberOfPasses++;
layoutSpec = [self layoutSpecThatFits:constrainedSize];
} else {
layoutSpec = [self layoutSpecThatFits:constrainedSize];
}
ASLayoutSpec *layoutSpec = ({
ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec);
[self layoutSpecThatFits:constrainedSize];
});
ASDisplayNodeAssert(layoutSpec.isMutable, @"Node %@ returned layout spec %@ that has already been used. Layout specs should always be regenerated.", self, layoutSpec);
layoutSpec.parent = self; // This causes upward propogation of any non-default layoutable values.
// manually propagate the trait collection here so that any layoutSpec children of layoutSpec will get a traitCollection
ASEnvironmentStatePropagateDown(layoutSpec, self.environmentTraitCollection);
{
ASDN::SumScopeTimer t(_layoutSpecTotalTime, measureLayoutSpec);
ASEnvironmentStatePropagateDown(layoutSpec, self.environmentTraitCollection);
}
layoutSpec.isMutable = NO;
ASLayout *layout = nil;
// optional performance measurement for cell nodes
if (_measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutGeneration) {
ASDN::SumScopeTimer t(_layoutGenerationTotalTime);
_layoutGenerationNumberOfPasses++;
layout = [layoutSpec layoutThatFits:constrainedSize];
} else {
layout = [layoutSpec layoutThatFits:constrainedSize];
BOOL measureLayoutComputation = _measurementOptions & ASDisplayNodePerformanceMeasurementOptionLayoutComputation;
if (measureLayoutComputation) {
_layoutComputationNumberOfPasses++;
}
ASLayout *layout = ({
ASDN::SumScopeTimer t(_layoutComputationTotalTime, measureLayoutComputation);
[layoutSpec layoutThatFits:constrainedSize];
});
ASDisplayNodeAssertNotNil(layout, @"[ASLayoutSpec measureWithSizeRange:] should never return nil! %@, %@", self, layoutSpec);
// Make sure layoutableObject of the root layout is `self`, so that the flattened layout will be structurally correct.

View File

@@ -171,9 +171,9 @@ FOUNDATION_EXPORT NSString * const ASRenderingEngineDidDisplayNodesScheduledBefo
// performance measurement
ASDisplayNodePerformanceMeasurementOptions _measurementOptions;
NSTimeInterval _layoutSpecTotalTime;
NSUInteger _layoutSpecNumberOfPasses;
NSTimeInterval _layoutGenerationTotalTime;
NSUInteger _layoutGenerationNumberOfPasses;
NSInteger _layoutSpecNumberOfPasses;
NSTimeInterval _layoutComputationTotalTime;
NSInteger _layoutComputationNumberOfPasses;
#if TIME_DISPLAYNODE_OPS
@public

View File

@@ -42,11 +42,16 @@ namespace ASDN {
struct SumScopeTimer {
NSTimeInterval begin;
NSTimeInterval &outT;
SumScopeTimer(NSTimeInterval &outRef) : outT(outRef) {
begin = CACurrentMediaTime();
BOOL enable;
SumScopeTimer(NSTimeInterval &outRef, BOOL enable = YES) : outT(outRef), enable(enable) {
if (enable) {
begin = CACurrentMediaTime();
}
}
~SumScopeTimer() {
outT += CACurrentMediaTime() - begin;
if (enable) {
outT += CACurrentMediaTime() - begin;
}
}
};
}