Optimize edge value resolution

Summary:
Noticed in simpleperf this was a very hot method, showing 8ms spent in these methods in our sample application. By splitting the method out in a horizontal and vertical variant we can simplify cases enormously and check for begin/end in one go.

Changelog: [Internal]

Reviewed By: SidharthGuglani

Differential Revision: D27010008

fbshipit-source-id: 22fed58c7476e1d716b0191b55997c7a06e63223
This commit is contained in:
Pieter De Baets
2021-03-15 16:53:05 -07:00
committed by Facebook GitHub Bot
parent 342aebe1d7
commit 41384fab7b
5 changed files with 129 additions and 149 deletions

View File

@@ -50,89 +50,111 @@ void YGNode::print(void* printContext) {
} }
} }
CompactValue YGNode::computeEdgeValueForRow(
const YGStyle::Edges& edges,
YGEdge rowEdge,
YGEdge edge,
CompactValue defaultValue) {
if (!edges[rowEdge].isUndefined()) {
return edges[rowEdge];
} else if (!edges[edge].isUndefined()) {
return edges[edge];
} else if (!edges[YGEdgeHorizontal].isUndefined()) {
return edges[YGEdgeHorizontal];
} else if (!edges[YGEdgeAll].isUndefined()) {
return edges[YGEdgeAll];
} else {
return defaultValue;
}
}
CompactValue YGNode::computeEdgeValueForColumn(
const YGStyle::Edges& edges,
YGEdge edge,
CompactValue defaultValue) {
if (!edges[edge].isUndefined()) {
return edges[edge];
} else if (!edges[YGEdgeVertical].isUndefined()) {
return edges[YGEdgeVertical];
} else if (!edges[YGEdgeAll].isUndefined()) {
return edges[YGEdgeAll];
} else {
return defaultValue;
}
}
YGFloatOptional YGNode::getLeadingPosition( YGFloatOptional YGNode::getLeadingPosition(
const YGFlexDirection axis, const YGFlexDirection axis,
const float axisSize) const { const float axisSize) const {
if (YGFlexDirectionIsRow(axis)) { auto leadingPosition = YGFlexDirectionIsRow(axis)
auto leadingPosition = YGComputedEdgeValue( ? computeEdgeValueForRow(
style_.position(), YGEdgeStart, CompactValue::ofUndefined()); style_.position(),
if (!leadingPosition.isUndefined()) { YGEdgeStart,
return YGResolveValue(leadingPosition, axisSize); leading[axis],
} CompactValue::ofZero())
} : computeEdgeValueForColumn(
style_.position(), leading[axis], CompactValue::ofZero());
auto leadingPosition = YGComputedEdgeValue( return YGResolveValue(leadingPosition, axisSize);
style_.position(), leading[axis], CompactValue::ofUndefined());
return leadingPosition.isUndefined()
? YGFloatOptional{0}
: YGResolveValue(leadingPosition, axisSize);
} }
YGFloatOptional YGNode::getTrailingPosition( YGFloatOptional YGNode::getTrailingPosition(
const YGFlexDirection axis, const YGFlexDirection axis,
const float axisSize) const { const float axisSize) const {
if (YGFlexDirectionIsRow(axis)) { auto trailingPosition = YGFlexDirectionIsRow(axis)
auto trailingPosition = YGComputedEdgeValue( ? computeEdgeValueForRow(
style_.position(), YGEdgeEnd, CompactValue::ofUndefined()); style_.position(),
if (!trailingPosition.isUndefined()) { YGEdgeEnd,
return YGResolveValue(trailingPosition, axisSize); trailing[axis],
} CompactValue::ofZero())
} : computeEdgeValueForColumn(
style_.position(), trailing[axis], CompactValue::ofZero());
auto trailingPosition = YGComputedEdgeValue( return YGResolveValue(trailingPosition, axisSize);
style_.position(), trailing[axis], CompactValue::ofUndefined());
return trailingPosition.isUndefined()
? YGFloatOptional{0}
: YGResolveValue(trailingPosition, axisSize);
} }
bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const { bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const {
return (YGFlexDirectionIsRow(axis) && auto leadingPosition = YGFlexDirectionIsRow(axis)
!YGComputedEdgeValue( ? computeEdgeValueForRow(
style_.position(), YGEdgeStart, CompactValue::ofUndefined()) style_.position(),
.isUndefined()) || YGEdgeStart,
!YGComputedEdgeValue( leading[axis],
style_.position(), leading[axis], CompactValue::ofUndefined()) CompactValue::ofUndefined())
.isUndefined(); : computeEdgeValueForColumn(
style_.position(), leading[axis], CompactValue::ofUndefined());
return !leadingPosition.isUndefined();
} }
bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const { bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const {
return (YGFlexDirectionIsRow(axis) && auto trailingPosition = YGFlexDirectionIsRow(axis)
!YGComputedEdgeValue( ? computeEdgeValueForRow(
style_.position(), YGEdgeEnd, CompactValue::ofUndefined()) style_.position(),
.isUndefined()) || YGEdgeEnd,
!YGComputedEdgeValue( trailing[axis],
style_.position(), trailing[axis], CompactValue::ofUndefined()) CompactValue::ofUndefined())
.isUndefined(); : computeEdgeValueForColumn(
style_.position(), trailing[axis], CompactValue::ofUndefined());
return !trailingPosition.isUndefined();
} }
YGFloatOptional YGNode::getLeadingMargin( YGFloatOptional YGNode::getLeadingMargin(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
if (YGFlexDirectionIsRow(axis) && auto leadingMargin = YGFlexDirectionIsRow(axis)
!style_.margin()[YGEdgeStart].isUndefined()) { ? computeEdgeValueForRow(
return YGResolveValueMargin(style_.margin()[YGEdgeStart], widthSize); style_.margin(), YGEdgeStart, leading[axis], CompactValue::ofZero())
} : computeEdgeValueForColumn(
style_.margin(), leading[axis], CompactValue::ofZero());
return YGResolveValueMargin( return YGResolveValueMargin(leadingMargin, widthSize);
YGComputedEdgeValue(
style_.margin(), leading[axis], CompactValue::ofZero()),
widthSize);
} }
YGFloatOptional YGNode::getTrailingMargin( YGFloatOptional YGNode::getTrailingMargin(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
if (YGFlexDirectionIsRow(axis) && !style_.margin()[YGEdgeEnd].isUndefined()) { auto trailingMargin = YGFlexDirectionIsRow(axis)
return YGResolveValueMargin(style_.margin()[YGEdgeEnd], widthSize); ? computeEdgeValueForRow(
} style_.margin(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
: computeEdgeValueForColumn(
return YGResolveValueMargin( style_.margin(), trailing[axis], CompactValue::ofZero());
YGComputedEdgeValue( return YGResolveValueMargin(trailingMargin, widthSize);
style_.margin(), trailing[axis], CompactValue::ofZero()),
widthSize);
} }
YGFloatOptional YGNode::getMarginForAxis( YGFloatOptional YGNode::getMarginForAxis(
@@ -147,7 +169,6 @@ YGSize YGNode::measure(
float height, float height,
YGMeasureMode heightMode, YGMeasureMode heightMode,
void* layoutContext) { void* layoutContext) {
return facebook::yoga::detail::getBooleanData(flags, measureUsesContext_) return facebook::yoga::detail::getBooleanData(flags, measureUsesContext_)
? measure_.withContext( ? measure_.withContext(
this, width, widthMode, height, heightMode, layoutContext) this, width, widthMode, height, heightMode, layoutContext)
@@ -448,68 +469,48 @@ bool YGNode::isNodeFlexible() {
} }
float YGNode::getLeadingBorder(const YGFlexDirection axis) const { float YGNode::getLeadingBorder(const YGFlexDirection axis) const {
YGValue leadingBorder; YGValue leadingBorder = YGFlexDirectionIsRow(axis)
if (YGFlexDirectionIsRow(axis) && ? computeEdgeValueForRow(
!style_.border()[YGEdgeStart].isUndefined()) { style_.border(), YGEdgeStart, leading[axis], CompactValue::ofZero())
leadingBorder = style_.border()[YGEdgeStart]; : computeEdgeValueForColumn(
if (leadingBorder.value >= 0) { style_.border(), leading[axis], CompactValue::ofZero());
return leadingBorder.value; return fmaxf(leadingBorder.value, 0.0f);
}
}
leadingBorder = YGComputedEdgeValue(
style_.border(), leading[axis], CompactValue::ofZero());
return YGFloatMax(leadingBorder.value, 0.0f);
} }
float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const { float YGNode::getTrailingBorder(const YGFlexDirection axis) const {
YGValue trailingBorder; YGValue trailingBorder = YGFlexDirectionIsRow(axis)
if (YGFlexDirectionIsRow(flexDirection) && ? computeEdgeValueForRow(
!style_.border()[YGEdgeEnd].isUndefined()) { style_.border(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
trailingBorder = style_.border()[YGEdgeEnd]; : computeEdgeValueForColumn(
if (trailingBorder.value >= 0.0f) { style_.border(), trailing[axis], CompactValue::ofZero());
return trailingBorder.value; return fmaxf(trailingBorder.value, 0.0f);
}
}
trailingBorder = YGComputedEdgeValue(
style_.border(), trailing[flexDirection], CompactValue::ofZero());
return YGFloatMax(trailingBorder.value, 0.0f);
} }
YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getLeadingPadding(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
const YGFloatOptional paddingEdgeStart = auto leadingPadding = YGFlexDirectionIsRow(axis)
YGResolveValue(style_.padding()[YGEdgeStart], widthSize); ? computeEdgeValueForRow(
if (YGFlexDirectionIsRow(axis) && style_.padding(),
!style_.padding()[YGEdgeStart].isUndefined() && YGEdgeStart,
!paddingEdgeStart.isUndefined() && paddingEdgeStart.unwrap() >= 0.0f) { leading[axis],
return paddingEdgeStart; CompactValue::ofZero())
} : computeEdgeValueForColumn(
style_.padding(), leading[axis], CompactValue::ofZero());
YGFloatOptional resolvedValue = YGResolveValue( return YGFloatOptionalMax(
YGComputedEdgeValue( YGResolveValue(leadingPadding, widthSize), YGFloatOptional(0.0f));
style_.padding(), leading[axis], CompactValue::ofZero()),
widthSize);
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
} }
YGFloatOptional YGNode::getTrailingPadding( YGFloatOptional YGNode::getTrailingPadding(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
const YGFloatOptional paddingEdgeEnd = auto trailingPadding = YGFlexDirectionIsRow(axis)
YGResolveValue(style_.padding()[YGEdgeEnd], widthSize); ? computeEdgeValueForRow(
if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { style_.padding(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
return paddingEdgeEnd; : computeEdgeValueForColumn(
} style_.padding(), trailing[axis], CompactValue::ofZero());
return YGFloatOptionalMax(
YGFloatOptional resolvedValue = YGResolveValue( YGResolveValue(trailingPadding, widthSize), YGFloatOptional(0.0f));
YGComputedEdgeValue(
style_.padding(), trailing[axis], CompactValue::ofZero()),
widthSize);
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
} }
YGFloatOptional YGNode::getLeadingPaddingAndBorder( YGFloatOptional YGNode::getLeadingPaddingAndBorder(

View File

@@ -193,6 +193,17 @@ public:
return resolvedDimensions_[index]; return resolvedDimensions_[index];
} }
static CompactValue computeEdgeValueForColumn(
const YGStyle::Edges& edges,
YGEdge edge,
CompactValue defaultValue);
static CompactValue computeEdgeValueForRow(
const YGStyle::Edges& edges,
YGEdge rowEdge,
YGEdge edge,
CompactValue defaultValue);
// Methods related to positions, margin, padding and border // Methods related to positions, margin, padding and border
YGFloatOptional getLeadingPosition( YGFloatOptional getLeadingPosition(
const YGFlexDirection axis, const YGFlexDirection axis,

View File

@@ -104,10 +104,13 @@ static void appendEdgeIfNotUndefined(
const string& str, const string& str,
const YGStyle::Edges& edges, const YGStyle::Edges& edges,
const YGEdge edge) { const YGEdge edge) {
appendNumberIfNotUndefined( // TODO: this doesn't take RTL / YGEdgeStart / YGEdgeEnd into account
base, auto value = (edge == YGEdgeLeft || edge == YGEdgeRight)
str, ? YGNode::computeEdgeValueForRow(
YGComputedEdgeValue(edges, edge, detail::CompactValue::ofUndefined())); edges, edge, edge, detail::CompactValue::ofUndefined())
: YGNode::computeEdgeValueForColumn(
edges, edge, detail::CompactValue::ofUndefined());
appendNumberIfNotUndefined(base, str, value);
} }
void YGNodeToString( void YGNodeToString(

View File

@@ -144,8 +144,3 @@ static const float kDefaultFlexShrink = 0.0f;
static const float kWebDefaultFlexShrink = 1.0f; static const float kWebDefaultFlexShrink = 1.0f;
extern bool YGFloatsEqual(const float a, const float b); extern bool YGFloatsEqual(const float a, const float b);
extern facebook::yoga::detail::CompactValue YGComputedEdgeValue(
const facebook::yoga::detail::Values<
facebook::yoga::enums::count<YGEdge>()>& edges,
YGEdge edge,
facebook::yoga::detail::CompactValue defaultValue);

View File

@@ -110,36 +110,6 @@ YOGA_EXPORT bool YGFloatIsUndefined(const float value) {
return facebook::yoga::isUndefined(value); return facebook::yoga::isUndefined(value);
} }
detail::CompactValue YGComputedEdgeValue(
const YGStyle::Edges& edges,
YGEdge edge,
detail::CompactValue defaultValue) {
if (!edges[edge].isUndefined()) {
return edges[edge];
}
if ((edge == YGEdgeTop || edge == YGEdgeBottom) &&
!edges[YGEdgeVertical].isUndefined()) {
return edges[YGEdgeVertical];
}
if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart ||
edge == YGEdgeEnd) &&
!edges[YGEdgeHorizontal].isUndefined()) {
return edges[YGEdgeHorizontal];
}
if (!edges[YGEdgeAll].isUndefined()) {
return edges[YGEdgeAll];
}
if (edge == YGEdgeStart || edge == YGEdgeEnd) {
return detail::CompactValue::ofUndefined();
}
return defaultValue;
}
YOGA_EXPORT void* YGNodeGetContext(YGNodeRef node) { YOGA_EXPORT void* YGNodeGetContext(YGNodeRef node) {
return node->getContext(); return node->getContext();
} }