mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
00751f64c7
Summary: See also D36889794. This is a very similar idea, except the core problem is that BaseTextProps is accessing the same props as ViewProps; and for ParagraphProps parsing, it first defers to ViewProps' parser and then BaseTextProps. RawPropsParser is optimized to access the same props in the same order, *exactly once*, so if we access a prop out-of-order, or for a second time, that access and the next access are deoptimized. Paragraph/Text, in particular, were quite bad because we did this several times, and each out-of-order access requires scanning /all/ props. This fixes the issue, at least partially, by (1) pulling all the duplicate accesses to the beginning of BaseTextProps, and (2) accessing them all in the same order as ViewProps, relatively (some props are skipped, but that matters less). Practically what this means is that now, all of Props' accesses have a cost of O(1) for lookup, or a total of O(n) for all of them; each access is at the n+1 position in the internal RawPropsParser array, so each access is cheap. BaseTextProps' duplicate accesses, even though there are only 4 of them: (1) the first one scans the entire array until we reach the prop in question; (2) the next accesses require scans, but not whole-array scans, since they're in order. (3) The BaseTextProps accesses /after/ the duplicate accesses are all O(1). tl;dr is that before we had something like O(n*6) cost for BaseTextProps parsing and now it is O(n*2). Similar to my summary in the last diff: we may want to revisit the RawPropsParser API... but I want to tread gently there, and this gets us a large improvement without major, risky changes. Empirically, based on a couple of systraces, average time for a single UIManager::createNode called from JS thread, before this stack: 17us. After: 667ns (3% as long). On average, for every 60 createNode calls, we will save 1ms on the UI thread. The savings will be greater for certain screens that use many Views or Text nodes, and lesser for screens that use fewer of these components. Changelog: [Internal] Reviewed By: mdvacca Differential Revision: D36890072 fbshipit-source-id: 5d24b986c391d7bb158ed2f43d130a71960837d1
211 lines
6.4 KiB
C++
211 lines
6.4 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "BaseTextProps.h"
|
|
|
|
#include <react/renderer/attributedstring/conversions.h>
|
|
#include <react/renderer/core/propsConversions.h>
|
|
#include <react/renderer/debug/DebugStringConvertibleItem.h>
|
|
#include <react/renderer/graphics/conversions.h>
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
static TextAttributes convertRawProp(
|
|
PropsParserContext const &context,
|
|
RawProps const &rawProps,
|
|
TextAttributes const &sourceTextAttributes,
|
|
TextAttributes const &defaultTextAttributes) {
|
|
auto textAttributes = TextAttributes{};
|
|
|
|
// Color (not accessed by ViewProps)
|
|
textAttributes.foregroundColor = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"color",
|
|
sourceTextAttributes.foregroundColor,
|
|
defaultTextAttributes.foregroundColor);
|
|
|
|
// Font
|
|
textAttributes.fontFamily = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontFamily",
|
|
sourceTextAttributes.fontFamily,
|
|
defaultTextAttributes.fontFamily);
|
|
textAttributes.fontSize = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontSize",
|
|
sourceTextAttributes.fontSize,
|
|
defaultTextAttributes.fontSize);
|
|
textAttributes.fontSizeMultiplier = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontSizeMultiplier",
|
|
sourceTextAttributes.fontSizeMultiplier,
|
|
defaultTextAttributes.fontSizeMultiplier);
|
|
textAttributes.fontWeight = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontWeight",
|
|
sourceTextAttributes.fontWeight,
|
|
defaultTextAttributes.fontWeight);
|
|
textAttributes.fontStyle = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontStyle",
|
|
sourceTextAttributes.fontStyle,
|
|
defaultTextAttributes.fontStyle);
|
|
textAttributes.fontVariant = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"fontVariant",
|
|
sourceTextAttributes.fontVariant,
|
|
defaultTextAttributes.fontVariant);
|
|
textAttributes.allowFontScaling = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"allowFontScaling",
|
|
sourceTextAttributes.allowFontScaling,
|
|
defaultTextAttributes.allowFontScaling);
|
|
textAttributes.letterSpacing = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"letterSpacing",
|
|
sourceTextAttributes.letterSpacing,
|
|
defaultTextAttributes.letterSpacing);
|
|
textAttributes.textTransform = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textTransform",
|
|
sourceTextAttributes.textTransform,
|
|
defaultTextAttributes.textTransform);
|
|
|
|
// Paragraph
|
|
textAttributes.lineHeight = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"lineHeight",
|
|
sourceTextAttributes.lineHeight,
|
|
defaultTextAttributes.lineHeight);
|
|
textAttributes.alignment = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textAlign",
|
|
sourceTextAttributes.alignment,
|
|
defaultTextAttributes.alignment);
|
|
textAttributes.baseWritingDirection = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"baseWritingDirection",
|
|
sourceTextAttributes.baseWritingDirection,
|
|
defaultTextAttributes.baseWritingDirection);
|
|
|
|
// Decoration
|
|
textAttributes.textDecorationColor = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textDecorationColor",
|
|
sourceTextAttributes.textDecorationColor,
|
|
defaultTextAttributes.textDecorationColor);
|
|
textAttributes.textDecorationLineType = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textDecorationLine",
|
|
sourceTextAttributes.textDecorationLineType,
|
|
defaultTextAttributes.textDecorationLineType);
|
|
textAttributes.textDecorationStyle = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textDecorationStyle",
|
|
sourceTextAttributes.textDecorationStyle,
|
|
defaultTextAttributes.textDecorationStyle);
|
|
|
|
// Shadow
|
|
textAttributes.textShadowOffset = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textShadowOffset",
|
|
sourceTextAttributes.textShadowOffset,
|
|
defaultTextAttributes.textShadowOffset);
|
|
textAttributes.textShadowRadius = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textShadowRadius",
|
|
sourceTextAttributes.textShadowRadius,
|
|
defaultTextAttributes.textShadowRadius);
|
|
textAttributes.textShadowColor = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"textShadowColor",
|
|
sourceTextAttributes.textShadowColor,
|
|
defaultTextAttributes.textShadowColor);
|
|
|
|
// Special
|
|
textAttributes.isHighlighted = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"isHighlighted",
|
|
sourceTextAttributes.isHighlighted,
|
|
defaultTextAttributes.isHighlighted);
|
|
|
|
// In general, we want this class to access props in the same order
|
|
// that ViewProps accesses them in, so that RawPropParser can optimize
|
|
// accesses. This is both theoretical, and ParagraphProps takes advantage
|
|
// of this.
|
|
// In particular: accessibilityRole, opacity, and backgroundColor also
|
|
// are parsed first by ViewProps (and indirectly AccessibilityProps).
|
|
// However, since RawPropsParser will always store these props /before/
|
|
// the unique BaseTextProps props, it is most efficient to parse these, in
|
|
// order, /after/ all of the other BaseTextProps, so that the RawPropsParser
|
|
// index rolls over only once instead of twice.
|
|
textAttributes.accessibilityRole = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"accessibilityRole",
|
|
sourceTextAttributes.accessibilityRole,
|
|
defaultTextAttributes.accessibilityRole);
|
|
|
|
// Color (accessed in this order by ViewProps)
|
|
textAttributes.opacity = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"opacity",
|
|
sourceTextAttributes.opacity,
|
|
defaultTextAttributes.opacity);
|
|
textAttributes.backgroundColor = convertRawProp(
|
|
context,
|
|
rawProps,
|
|
"backgroundColor",
|
|
sourceTextAttributes.backgroundColor,
|
|
defaultTextAttributes.backgroundColor);
|
|
|
|
return textAttributes;
|
|
}
|
|
|
|
BaseTextProps::BaseTextProps(
|
|
const PropsParserContext &context,
|
|
const BaseTextProps &sourceProps,
|
|
const RawProps &rawProps)
|
|
: textAttributes(convertRawProp(
|
|
context,
|
|
rawProps,
|
|
sourceProps.textAttributes,
|
|
TextAttributes{})){};
|
|
|
|
#pragma mark - DebugStringConvertible
|
|
|
|
#if RN_DEBUG_STRING_CONVERTIBLE
|
|
SharedDebugStringConvertibleList BaseTextProps::getDebugProps() const {
|
|
return textAttributes.getDebugProps();
|
|
}
|
|
#endif
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|