Skip to content

Commit

Permalink
Node -> Measure func map instead of vec (#1581)
Browse files Browse the repository at this point in the history
Summary:
Pull Request resolved: #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
  • Loading branch information
joevilches authored and facebook-github-bot committed Feb 22, 2024
1 parent b35456b commit c278713
Show file tree
Hide file tree
Showing 9 changed files with 7,101 additions and 6,743 deletions.
73 changes: 37 additions & 36 deletions benchmark/Benchmark.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,49 +46,46 @@ static bool inputsMatch(
actualHeightMode == expectedHeightMode;
}

YGSize defaultMeasureFunctionResult() {
std::cout << "Trying to measure a node that wasn't serialized" << std::endl;
return {10.0, 10.0};
}

YGSize mockMeasureFunc(
YGNodeConstRef node,
float availableWidth,
YGMeasureMode widthMode,
float availableHeight,
YGMeasureMode heightMode) {
(void)node;
MeasureFuncVecWithIndex* fns =
static_cast<MeasureFuncVecWithIndex*>(YGNodeGetContext(node));
auto fnsPtr = static_cast<SerializedMeasureFuncMap*>(YGNodeGetContext(node));

if (fns->index >= fns->vec.size()) {
std::cout << "Extra measure function call made" << std::endl;
return {10.0, 10.0};
if (fnsPtr == nullptr) {
return defaultMeasureFunctionResult();
}

auto values = fns->vec.at(fns->index);

if (!inputsMatch(
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};
auto fnsIt = fnsPtr->find(node);
if (fnsIt == fnsPtr->end()) {
return defaultMeasureFunctionResult();
}

fns->index++;

std::this_thread::sleep_for(std::chrono::nanoseconds(values.durationNs));
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};
}
}

return {values.outputWidth, values.outputHeight};
return defaultMeasureFunctionResult();
}

std::shared_ptr<const YGConfig> buildConfigFromJson(const json& j) {
Expand Down Expand Up @@ -257,7 +254,7 @@ void setStylesFromJson(const json& j, YGNodeRef node) {
std::shared_ptr<YGNode> buildNodeFromJson(
const json& j,
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);

if (!j.contains("node") || j["node"].is_null()) {
Expand All @@ -268,8 +265,13 @@ std::shared_ptr<YGNode> buildNodeFromJson(
for (json::iterator it = nodeState.begin(); it != nodeState.end(); it++) {
if (it.key() == "always-forms-containing-block") {
YGNodeSetAlwaysFormsContainingBlock(node.get(), it.value());
} else if (it.key() == "has-custom-measure" && it.value()) {
YGNodeSetContext(node.get(), fns.get());
} else if (it.key() == "measure-funcs") {
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);
}
}
Expand All @@ -279,7 +281,7 @@ std::shared_ptr<YGNode> buildNodeFromJson(

std::shared_ptr<YogaNodeAndConfig> buildTreeFromJson(
const json& j,
std::shared_ptr<MeasureFuncVecWithIndex> fns,
std::shared_ptr<SerializedMeasureFuncMap> fns,
std::shared_ptr<YogaNodeAndConfig> parent,
size_t index) {
auto config = buildConfigFromJson(j);
Expand Down Expand Up @@ -307,8 +309,7 @@ std::shared_ptr<YogaNodeAndConfig> buildTreeFromJson(
}

BenchmarkResult generateBenchmark(json& capture) {
auto fns = std::make_shared<MeasureFuncVecWithIndex>();
populateMeasureFuncVec(capture["measure-funcs"], fns);
auto fns = std::make_shared<SerializedMeasureFuncMap>();

auto treeCreationBegin = steady_clock::now();
std::shared_ptr<YogaNodeAndConfig> root =
Expand Down
22 changes: 9 additions & 13 deletions benchmark/TreeDeserialization.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -228,18 +228,14 @@ YGMeasureMode measureModeFromString(std::string str) {
}
}

void populateMeasureFuncVec(
json& j,
std::shared_ptr<MeasureFuncVecWithIndex> fns) {
for (auto measureFuncJson : j) {
fns->vec.push_back(SerializedMeasureFunc{
floatFromJson(measureFuncJson["width"]),
measureModeFromString(measureFuncJson["width-mode"]),
floatFromJson(measureFuncJson["height"]),
measureModeFromString(measureFuncJson["height-mode"]),
floatFromJson(measureFuncJson["output-width"]),
floatFromJson(measureFuncJson["output-height"]),
measureFuncJson["duration-ns"]});
}
SerializedMeasureFunc serializedMeasureFuncFromJson(json& j) {
return SerializedMeasureFunc{
floatFromJson(j["width"]),
measureModeFromString(j["width-mode"]),
floatFromJson(j["height"]),
measureModeFromString(j["height-mode"]),
floatFromJson(j["output-width"]),
floatFromJson(j["output-height"]),
j["duration-ns"]};
}
} // namespace facebook::yoga
9 changes: 1 addition & 8 deletions benchmark/TreeDeserialization.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,6 @@ namespace facebook::yoga {

using namespace nlohmann;

struct MeasureFuncVecWithIndex {
std::vector<SerializedMeasureFunc> vec;
size_t index;
};

YGFlexDirection flexDirectionFromString(std::string str);

YGJustify justifyContentFromString(std::string str);
Expand Down Expand Up @@ -53,7 +48,5 @@ YGDirection directionFromString(std::string str);

YGMeasureMode measureModeFromString(std::string str);

void populateMeasureFuncVec(
json& j,
std::shared_ptr<MeasureFuncVecWithIndex> fns);
SerializedMeasureFunc serializedMeasureFuncFromJson(json& j);
} // namespace facebook::yoga
Loading

0 comments on commit c278713

Please sign in to comment.