Node -> Measure func map instead of vec (#1581)

Summary:
Pull Request resolved: https://github.com/facebook/yoga/pull/1581

This is better than just trusting the order of the measure func call. Now each measure function I/O is associated with a node in the JSON.

Reviewed By: NickGerleman

Differential Revision: D53776790

fbshipit-source-id: 793cf2d9cbf6f663d24848af0af30aa297614eea
This commit is contained in:
Joe Vilches
2024-02-21 18:02:58 -08:00
committed by Facebook GitHub Bot
parent b35456b93c
commit c278713eb5
9 changed files with 10165 additions and 9807 deletions

View File

@@ -46,6 +46,11 @@ static bool inputsMatch(
actualHeightMode == expectedHeightMode; actualHeightMode == expectedHeightMode;
} }
YGSize defaultMeasureFunctionResult() {
std::cout << "Trying to measure a node that wasn't serialized" << std::endl;
return {10.0, 10.0};
}
YGSize mockMeasureFunc( YGSize mockMeasureFunc(
YGNodeConstRef node, YGNodeConstRef node,
float availableWidth, float availableWidth,
@@ -53,42 +58,34 @@ YGSize mockMeasureFunc(
float availableHeight, float availableHeight,
YGMeasureMode heightMode) { YGMeasureMode heightMode) {
(void)node; (void)node;
MeasureFuncVecWithIndex* fns = auto fnsPtr = static_cast<SerializedMeasureFuncMap*>(YGNodeGetContext(node));
static_cast<MeasureFuncVecWithIndex*>(YGNodeGetContext(node));
if (fns->index >= fns->vec.size()) { if (fnsPtr == nullptr) {
std::cout << "Extra measure function call made" << std::endl; return defaultMeasureFunctionResult();
return {10.0, 10.0};
} }
auto values = fns->vec.at(fns->index); auto fnsIt = fnsPtr->find(node);
if (fnsIt == fnsPtr->end()) {
if (!inputsMatch( return defaultMeasureFunctionResult();
availableWidth,
values.inputWidth,
availableHeight,
values.inputHeight,
widthMode,
values.widthMode,
heightMode,
values.heightMode)) {
std::cout << "Measure function input mismatch." << std::endl
<< "Expected width: " << values.inputWidth
<< ", actual width: " << availableWidth << std::endl
<< "Expected height: " << values.inputHeight
<< ", actual height: " << availableHeight << std::endl
<< "Expected width mode: " << values.widthMode
<< ", actual width mode: " << widthMode << std::endl
<< "Expected height mode: " << values.heightMode
<< ", actual height mode: " << heightMode << std::endl;
return {10.0, 10.0};
} }
fns->index++; for (auto measureFunc : fnsIt->second) {
if (inputsMatch(
availableWidth,
measureFunc.inputWidth,
availableHeight,
measureFunc.inputHeight,
widthMode,
measureFunc.widthMode,
heightMode,
measureFunc.heightMode)) {
std::this_thread::sleep_for(
std::chrono::nanoseconds(measureFunc.durationNs));
return {measureFunc.outputWidth, measureFunc.outputHeight};
}
}
std::this_thread::sleep_for(std::chrono::nanoseconds(values.durationNs)); return defaultMeasureFunctionResult();
return {values.outputWidth, values.outputHeight};
} }
std::shared_ptr<const YGConfig> buildConfigFromJson(const json& j) { std::shared_ptr<const YGConfig> buildConfigFromJson(const json& j) {
@@ -257,7 +254,7 @@ void setStylesFromJson(const json& j, YGNodeRef node) {
std::shared_ptr<YGNode> buildNodeFromJson( std::shared_ptr<YGNode> buildNodeFromJson(
const json& j, const json& j,
std::shared_ptr<const YGConfig> config, std::shared_ptr<const YGConfig> config,
std::shared_ptr<MeasureFuncVecWithIndex> fns) { std::shared_ptr<SerializedMeasureFuncMap> fns) {
std::shared_ptr<YGNode> node(YGNodeNewWithConfig(config.get()), YGNodeFree); std::shared_ptr<YGNode> node(YGNodeNewWithConfig(config.get()), YGNodeFree);
if (!j.contains("node") || j["node"].is_null()) { if (!j.contains("node") || j["node"].is_null()) {
@@ -268,8 +265,13 @@ std::shared_ptr<YGNode> buildNodeFromJson(
for (json::iterator it = nodeState.begin(); it != nodeState.end(); it++) { for (json::iterator it = nodeState.begin(); it != nodeState.end(); it++) {
if (it.key() == "always-forms-containing-block") { if (it.key() == "always-forms-containing-block") {
YGNodeSetAlwaysFormsContainingBlock(node.get(), it.value()); YGNodeSetAlwaysFormsContainingBlock(node.get(), it.value());
} else if (it.key() == "has-custom-measure" && it.value()) { } else if (it.key() == "measure-funcs") {
YGNodeSetContext(node.get(), fns.get()); std::vector<SerializedMeasureFunc> vec{};
for (auto measureFuncJson : it.value()) {
vec.push_back(serializedMeasureFuncFromJson(measureFuncJson));
}
fns->insert(std::make_pair(node.get(), vec));
YGNodeSetContext(node.get(), it.value().is_null() ? nullptr : fns.get());
YGNodeSetMeasureFunc(node.get(), mockMeasureFunc); YGNodeSetMeasureFunc(node.get(), mockMeasureFunc);
} }
} }
@@ -279,7 +281,7 @@ std::shared_ptr<YGNode> buildNodeFromJson(
std::shared_ptr<YogaNodeAndConfig> buildTreeFromJson( std::shared_ptr<YogaNodeAndConfig> buildTreeFromJson(
const json& j, const json& j,
std::shared_ptr<MeasureFuncVecWithIndex> fns, std::shared_ptr<SerializedMeasureFuncMap> fns,
std::shared_ptr<YogaNodeAndConfig> parent, std::shared_ptr<YogaNodeAndConfig> parent,
size_t index) { size_t index) {
auto config = buildConfigFromJson(j); auto config = buildConfigFromJson(j);
@@ -307,8 +309,7 @@ std::shared_ptr<YogaNodeAndConfig> buildTreeFromJson(
} }
BenchmarkResult generateBenchmark(json& capture) { BenchmarkResult generateBenchmark(json& capture) {
auto fns = std::make_shared<MeasureFuncVecWithIndex>(); auto fns = std::make_shared<SerializedMeasureFuncMap>();
populateMeasureFuncVec(capture["measure-funcs"], fns);
auto treeCreationBegin = steady_clock::now(); auto treeCreationBegin = steady_clock::now();
std::shared_ptr<YogaNodeAndConfig> root = std::shared_ptr<YogaNodeAndConfig> root =

View File

@@ -228,18 +228,14 @@ YGMeasureMode measureModeFromString(std::string str) {
} }
} }
void populateMeasureFuncVec( SerializedMeasureFunc serializedMeasureFuncFromJson(json& j) {
json& j, return SerializedMeasureFunc{
std::shared_ptr<MeasureFuncVecWithIndex> fns) { floatFromJson(j["width"]),
for (auto measureFuncJson : j) { measureModeFromString(j["width-mode"]),
fns->vec.push_back(SerializedMeasureFunc{ floatFromJson(j["height"]),
floatFromJson(measureFuncJson["width"]), measureModeFromString(j["height-mode"]),
measureModeFromString(measureFuncJson["width-mode"]), floatFromJson(j["output-width"]),
floatFromJson(measureFuncJson["height"]), floatFromJson(j["output-height"]),
measureModeFromString(measureFuncJson["height-mode"]), j["duration-ns"]};
floatFromJson(measureFuncJson["output-width"]),
floatFromJson(measureFuncJson["output-height"]),
measureFuncJson["duration-ns"]});
}
} }
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -18,11 +18,6 @@ namespace facebook::yoga {
using namespace nlohmann; using namespace nlohmann;
struct MeasureFuncVecWithIndex {
std::vector<SerializedMeasureFunc> vec;
size_t index;
};
YGFlexDirection flexDirectionFromString(std::string str); YGFlexDirection flexDirectionFromString(std::string str);
YGJustify justifyContentFromString(std::string str); YGJustify justifyContentFromString(std::string str);
@@ -53,7 +48,5 @@ YGDirection directionFromString(std::string str);
YGMeasureMode measureModeFromString(std::string str); YGMeasureMode measureModeFromString(std::string str);
void populateMeasureFuncVec( SerializedMeasureFunc serializedMeasureFuncFromJson(json& j);
json& j,
std::shared_ptr<MeasureFuncVecWithIndex> fns);
} // namespace facebook::yoga } // namespace facebook::yoga

File diff suppressed because it is too large Load Diff

View File

@@ -4,224 +4,6 @@
"available-width": 1080.0, "available-width": 1080.0,
"owner-direction": "ltr" "owner-direction": "ltr"
}, },
"measure-funcs": [
{
"duration-ns": 23667,
"height": null,
"height-mode": "undefined",
"output-height": 330.0,
"output-width": 408.0,
"width": 647.3333129882813,
"width-mode": "at-most"
},
{
"duration-ns": 9083,
"height": null,
"height-mode": "undefined",
"output-height": 448.0,
"output-width": 562.5,
"width": 647.3333129882813,
"width-mode": "at-most"
},
{
"duration-ns": 7667,
"height": null,
"height-mode": "undefined",
"output-height": 100.0,
"output-width": 294.0,
"width": 647.3333129882813,
"width-mode": "at-most"
},
{
"duration-ns": 8333,
"height": 676.0,
"height-mode": "at-most",
"output-height": 94.0,
"output-width": 328.6666564941406,
"width": 328.6666564941406,
"width-mode": "exactly"
},
{
"duration-ns": 7791,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 8041,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 8000,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7709,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7666,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 6916,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7167,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 9333,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7125,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7125,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7209,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7083,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7333,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7375,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 8917,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 7667,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
},
{
"duration-ns": 8583,
"height": null,
"height-mode": "undefined",
"output-height": 295.0,
"output-width": 816.0,
"width": null,
"width-mode": "undefined"
},
{
"duration-ns": 7667,
"height": null,
"height-mode": "undefined",
"output-height": 7.0,
"output-width": 70.5,
"width": 1076.0,
"width-mode": "at-most"
},
{
"duration-ns": 494291,
"height": 44.0,
"height-mode": "at-most",
"output-height": 18.0,
"output-width": 5.0,
"width": 1016.0,
"width-mode": "at-most"
},
{
"duration-ns": 58250,
"height": 44.0,
"height-mode": "at-most",
"output-height": 18.0,
"output-width": 10.0,
"width": 10.0,
"width-mode": "exactly"
}
],
"tree": { "tree": {
"children": [ "children": [
{ {
@@ -237,7 +19,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8167,
"height": null,
"height-mode": "undefined",
"output-height": 295.0,
"output-width": 816.0,
"width": null,
"width-mode": "undefined"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -720,7 +512,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 24625,
"height": null,
"height-mode": "undefined",
"output-height": 330.0,
"output-width": 408.0,
"width": 647.3333129882813,
"width-mode": "at-most"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -747,7 +549,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 9625,
"height": null,
"height-mode": "undefined",
"output-height": 448.0,
"output-width": 562.5,
"width": 647.3333129882813,
"width-mode": "at-most"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -774,7 +586,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8417,
"height": null,
"height-mode": "undefined",
"output-height": 100.0,
"output-width": 294.0,
"width": 647.3333129882813,
"width-mode": "at-most"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -815,7 +637,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 9166,
"height": 676.0,
"height-mode": "at-most",
"output-height": 94.0,
"output-width": 328.6666564941406,
"width": 328.6666564941406,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"padding-all": { "padding-all": {
@@ -837,7 +669,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8250,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -880,7 +722,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8625,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -923,7 +775,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 7250,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -966,7 +828,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6833,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1009,7 +881,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 7042,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1052,7 +934,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6208,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1095,7 +987,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6834,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1138,7 +1040,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8500,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1181,7 +1093,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6750,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1224,7 +1146,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6667,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1267,7 +1199,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8958,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1310,7 +1252,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 8125,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1353,7 +1305,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6541,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1396,7 +1358,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6541,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1439,7 +1411,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 6333,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1482,7 +1464,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 7875,
"height": 566.0,
"height-mode": "at-most",
"output-height": 21.0,
"output-width": 158.33331298828125,
"width": 158.33331298828125,
"width-mode": "exactly"
}
]
}, },
"style": { "style": {
"margin-all": { "margin-all": {
@@ -1619,7 +1611,17 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 7583,
"height": null,
"height-mode": "undefined",
"output-height": 7.0,
"output-width": 70.5,
"width": 1076.0,
"width-mode": "at-most"
}
]
}, },
"style": null "style": null
} }
@@ -1664,7 +1666,26 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": [
{
"duration-ns": 478791,
"height": 44.0,
"height-mode": "at-most",
"output-height": 18.0,
"output-width": 5.0,
"width": 1016.0,
"width-mode": "at-most"
},
{
"duration-ns": 61250,
"height": 44.0,
"height-mode": "at-most",
"output-height": 18.0,
"output-width": 10.0,
"width": 10.0,
"width-mode": "exactly"
}
]
}, },
"style": null "style": null
} }
@@ -1709,7 +1730,7 @@
"errata": "all" "errata": "all"
}, },
"node": { "node": {
"has-custom-measure": true "measure-funcs": null
}, },
"style": { "style": {
"flex": 1.0 "flex": 1.0

View File

@@ -5,8 +5,8 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include <cassert>
#include <fstream> #include <fstream>
#include <vector>
#include <capture/CaptureTree.h> #include <capture/CaptureTree.h>
#include <capture/NodeToString.h> #include <capture/NodeToString.h>
@@ -23,10 +23,9 @@ static void captureTree(
file << serializedTree; file << serializedTree;
} }
static std::vector<SerializedMeasureFunc>& currentSerializedMeasureFuncVec() { static SerializedMeasureFuncMap& currentSerializedMeasureFuncMap() {
static thread_local std::vector<SerializedMeasureFunc> static thread_local SerializedMeasureFuncMap map{};
currentSerializedMeasureFuncVec; return map;
return currentSerializedMeasureFuncVec;
} }
/* /*
@@ -57,38 +56,45 @@ void YGNodeCalculateLayoutWithCapture(
YGDirection ownerDirection, YGDirection ownerDirection,
const std::filesystem::path& path) { const std::filesystem::path& path) {
dirtyTree(node); dirtyTree(node);
YGNodeCalculateLayout(node, availableWidth, availableHeight, ownerDirection);
json j; json j;
serializeLayoutInputs(j, availableWidth, availableHeight, ownerDirection); serializeLayoutInputs(j, availableWidth, availableHeight, ownerDirection);
serializeTree( serializeTree(
j, j,
currentSerializedMeasureFuncMap(),
node, node,
PrintOptions::Style | PrintOptions::Children | PrintOptions::Config | PrintOptions::Style | PrintOptions::Children | PrintOptions::Config |
PrintOptions::Node); PrintOptions::Node);
YGNodeCalculateLayout(node, availableWidth, availableHeight, ownerDirection);
serializeMeasureFuncResults(j, currentSerializedMeasureFuncVec());
// TODO: It is possible to have a measure function call layout again if, e.g., // TODO: It is possible to have a measure function call layout again if, e.g.,
// views are nested in text. Need to be able to resolve this special case. // views are nested in text. Need to be able to resolve this special case.
currentSerializedMeasureFuncVec().clear(); currentSerializedMeasureFuncMap().clear();
captureTree(j.dump(2), path); captureTree(j.dump(2), path);
} }
void captureMeasureFunc( void captureMeasureFunc(
YGNodeConstRef node,
float width, float width,
YGMeasureMode widthMode, YGMeasureMode widthMode,
float height, float height,
YGMeasureMode heightMode, YGMeasureMode heightMode,
YGSize output, YGSize output,
std::chrono::steady_clock::duration durationNs) { std::chrono::steady_clock::duration durationNs) {
currentSerializedMeasureFuncVec().push_back(SerializedMeasureFunc{ auto measureFuncIt = currentSerializedMeasureFuncMap().find(node);
width, if (measureFuncIt == currentSerializedMeasureFuncMap().end()) {
widthMode, std::vector<SerializedMeasureFunc> vec{};
height, currentSerializedMeasureFuncMap().insert(std::make_pair(node, vec));
heightMode, }
output.width, measureFuncIt = currentSerializedMeasureFuncMap().find(node);
output.height, assert(measureFuncIt != currentSerializedMeasureFuncMap().end());
durationNs.count()}); measureFuncIt->second.push_back(
{width,
widthMode,
height,
heightMode,
output.width,
output.height,
durationNs.count()});
} }
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -8,6 +8,8 @@
#pragma once #pragma once
#include <filesystem> #include <filesystem>
#include <unordered_map>
#include <vector>
#include <yoga/Yoga.h> #include <yoga/Yoga.h>
@@ -23,6 +25,9 @@ struct SerializedMeasureFunc {
std::chrono::steady_clock::duration::rep durationNs; std::chrono::steady_clock::duration::rep durationNs;
}; };
using SerializedMeasureFuncMap =
std::unordered_map<YGNodeConstRef, std::vector<SerializedMeasureFunc>>;
void YGNodeCalculateLayoutWithCapture( void YGNodeCalculateLayoutWithCapture(
YGNodeRef node, YGNodeRef node,
float availableWidth, float availableWidth,
@@ -31,6 +36,7 @@ void YGNodeCalculateLayoutWithCapture(
const std::filesystem::path& path); const std::filesystem::path& path);
void captureMeasureFunc( void captureMeasureFunc(
YGNodeConstRef node,
float width, float width,
YGMeasureMode widthMode, YGMeasureMode widthMode,
float height, float height,

View File

@@ -6,6 +6,7 @@
*/ */
#include <memory> #include <memory>
#include <vector>
#include <capture/NodeToString.h> #include <capture/NodeToString.h>
@@ -120,7 +121,26 @@ static YGValue borderFloatToYGValue(YGNodeRef node, YGEdge edge) {
return YGValue{val, unit}; return YGValue{val, unit};
} }
static void serializeTreeImpl(json& j, YGNodeRef node, PrintOptions options) { static void serializeMeasureFuncResults(
json& j,
std::vector<SerializedMeasureFunc>& measureFuncs) {
for (auto measureFunc : measureFuncs) {
j["measure-funcs"].push_back(
{{"width", measureFunc.inputWidth},
{"width-mode", YGMeasureModeToString(measureFunc.widthMode)},
{"height", measureFunc.inputHeight},
{"height-mode", YGMeasureModeToString(measureFunc.heightMode)},
{"output-width", measureFunc.outputWidth},
{"output-height", measureFunc.outputHeight},
{"duration-ns", measureFunc.durationNs}});
}
}
static void serializeTreeImpl(
json& j,
SerializedMeasureFuncMap& nodesToMeasureFuncs,
YGNodeRef node,
PrintOptions options) {
if ((options & PrintOptions::Layout) == PrintOptions::Layout) { if ((options & PrintOptions::Layout) == PrintOptions::Layout) {
j["layout"]["width"] = YGNodeStyleGetWidth(node).value; j["layout"]["width"] = YGNodeStyleGetWidth(node).value;
j["layout"]["height"] = YGNodeStyleGetHeight(node).value; j["layout"]["height"] = YGNodeStyleGetHeight(node).value;
@@ -293,7 +313,12 @@ static void serializeTreeImpl(json& j, YGNodeRef node, PrintOptions options) {
YGNodeGetAlwaysFormsContainingBlock(node), YGNodeGetAlwaysFormsContainingBlock(node),
YGNodeGetAlwaysFormsContainingBlock(defaultNode.get())); YGNodeGetAlwaysFormsContainingBlock(defaultNode.get()));
if (YGNodeHasMeasureFunc(node)) { if (YGNodeHasMeasureFunc(node)) {
j["node"]["has-custom-measure"] = true; auto measureFuncIt = nodesToMeasureFuncs.find(node);
if (measureFuncIt == nodesToMeasureFuncs.end()) {
j["node"]["measure-funcs"];
} else {
serializeMeasureFuncResults(j["node"], measureFuncIt->second);
}
} }
} }
@@ -302,13 +327,21 @@ static void serializeTreeImpl(json& j, YGNodeRef node, PrintOptions options) {
childCount > 0) { childCount > 0) {
for (size_t i = 0; i < childCount; i++) { for (size_t i = 0; i < childCount; i++) {
j["children"].push_back({}); j["children"].push_back({});
serializeTreeImpl(j["children"][i], YGNodeGetChild(node, i), options); serializeTreeImpl(
j["children"][i],
nodesToMeasureFuncs,
YGNodeGetChild(node, i),
options);
} }
} }
} }
void serializeTree(json& j, YGNodeRef node, PrintOptions options) { void serializeTree(
serializeTreeImpl(j["tree"], node, options); json& j,
SerializedMeasureFuncMap& nodesToMeasureFuncs,
YGNodeRef node,
PrintOptions options) {
serializeTreeImpl(j["tree"], nodesToMeasureFuncs, node, options);
} }
void serializeLayoutInputs( void serializeLayoutInputs(
@@ -323,19 +356,4 @@ void serializeLayoutInputs(
}; };
} }
void serializeMeasureFuncResults(
json& j,
std::vector<SerializedMeasureFunc>& measureFuncs) {
for (auto measureFunc : measureFuncs) {
j["measure-funcs"].push_back(
{{"width", measureFunc.inputWidth},
{"width-mode", YGMeasureModeToString(measureFunc.widthMode)},
{"height", measureFunc.inputHeight},
{"height-mode", YGMeasureModeToString(measureFunc.heightMode)},
{"output-width", measureFunc.outputWidth},
{"output-height", measureFunc.outputHeight},
{"duration-ns", measureFunc.durationNs}});
}
}
} // namespace facebook::yoga } // namespace facebook::yoga

View File

@@ -25,7 +25,11 @@ enum class PrintOptions : uint8_t {
}; };
YG_DEFINE_ENUM_FLAG_OPERATORS(PrintOptions); YG_DEFINE_ENUM_FLAG_OPERATORS(PrintOptions);
void serializeTree(nlohmann::json& j, YGNodeRef root, PrintOptions options); void serializeTree(
nlohmann::json& j,
SerializedMeasureFuncMap& nodesToMeasureFuncs,
YGNodeRef root,
PrintOptions options);
void serializeLayoutInputs( void serializeLayoutInputs(
nlohmann::json& j, nlohmann::json& j,
@@ -33,8 +37,4 @@ void serializeLayoutInputs(
float availableHeight, float availableHeight,
YGDirection ownerDirection); YGDirection ownerDirection);
void serializeMeasureFuncResults(
nlohmann::json& j,
std::vector<SerializedMeasureFunc>& measureFuncs);
} // namespace facebook::yoga } // namespace facebook::yoga