From cc66362a281a4f937bd56a5a2d90845392a3a344 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Fri, 9 Feb 2024 16:44:32 -0800 Subject: [PATCH] Expose replacement wrapper of CalculateLayout + (de)serialize layout inputs (#1575) Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1575 If we want to replay layouts for benchmark, we should also capture the inputs. This diff does that as well as changing the API in CaptureTree.h. We now expose YGCalculateLayoutWithCapture designed to be a drop-in replacement for YGCalculateLayout. This allows us to have a bit more control on the order of everything and lets us capture measure functions in the next diff much easier. Reviewed By: NickGerleman Differential Revision: D53444261 fbshipit-source-id: 616e39153c21e7b472911502b6a717e92c88a4d1 --- benchmark/Benchmark.cpp | 7 ++++++- benchmark/TreeDeserialization.h | 12 ++++++++++++ capture/CaptureTree.cpp | 28 ++++++++++++++++++++++------ capture/CaptureTree.h | 7 ++++++- capture/NodeToString.cpp | 19 ++++++++++++------- capture/NodeToString.h | 9 ++++++++- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/benchmark/Benchmark.cpp b/benchmark/Benchmark.cpp index c0ae3690..787d3486 100644 --- a/benchmark/Benchmark.cpp +++ b/benchmark/Benchmark.cpp @@ -229,9 +229,14 @@ BenchmarkResult generateBenchmark(const std::filesystem::path& capturePath) { YogaNodeAndConfig root = buildTreeFromJson(capture, nullptr, 0 /*index*/); auto treeCreationEnd = steady_clock::now(); + json layoutInputs = capture["layout-inputs"]; + float availableWidth = layoutInputs["available-width"]; + float availableHeight = layoutInputs["available-height"]; + YGDirection direction = directionFromString(layoutInputs["owner-direction"]); + auto layoutBegin = steady_clock::now(); YGNodeCalculateLayout( - root.node_.get(), YGUndefined, YGUndefined, YGDirectionLTR); + root.node_.get(), availableWidth, availableHeight, direction); auto layoutEnd = steady_clock::now(); return BenchmarkResult{ diff --git a/benchmark/TreeDeserialization.h b/benchmark/TreeDeserialization.h index 1c6f3951..842d4bb5 100644 --- a/benchmark/TreeDeserialization.h +++ b/benchmark/TreeDeserialization.h @@ -191,4 +191,16 @@ inline std::string edgeStringFromPropertyName( std::string propertyName) { return it.key().substr(propertyName.length() + 1); } + +inline YGDirection directionFromString(std::string str) { + if (str == "ltr") { + return YGDirectionLTR; + } else if (str == "rtl") { + return YGDirectionRTL; + } else if (str == "inherit") { + return YGDirectionInherit; + } else { + throw std::invalid_argument(invalidArgumentMessage(str, "YGDirection")); + } +} } // namespace facebook::yoga diff --git a/capture/CaptureTree.cpp b/capture/CaptureTree.cpp index 67e3993f..a1a1a29f 100644 --- a/capture/CaptureTree.cpp +++ b/capture/CaptureTree.cpp @@ -9,18 +9,34 @@ #include #include +#include namespace facebook::yoga { -void captureTree(YGNodeRef node, const std::filesystem::path& path) { - std::string str; - nodeToString( - str, +using namespace nlohmann; + +static void captureTree( + std::string_view serializedTree, + const std::filesystem::path& path) { + std::ofstream file(path); + file << serializedTree; +} + +void YGNodeCalculateLayoutWithCapture( + YGNodeRef node, + float availableWidth, + float availableHeight, + YGDirection ownerDirection, + const std::filesystem::path& path) { + json j; + serializeLayoutInputs(j, availableWidth, availableHeight, ownerDirection); + serializeTree( + j, node, PrintOptions::Style | PrintOptions::Children | PrintOptions::Config | PrintOptions::Node); - std::ofstream file(path); - file << str; + captureTree(j.dump(2), path); + YGNodeCalculateLayout(node, availableWidth, availableHeight, ownerDirection); } } // namespace facebook::yoga diff --git a/capture/CaptureTree.h b/capture/CaptureTree.h index 5d809859..c12d3c78 100644 --- a/capture/CaptureTree.h +++ b/capture/CaptureTree.h @@ -13,6 +13,11 @@ namespace facebook::yoga { -void captureTree(YGNodeRef node, const std::filesystem::path& path); +void YGNodeCalculateLayoutWithCapture( + YGNodeRef node, + float availableWidth, + float availableHeight, + YGDirection ownerDirection, + const std::filesystem::path& path); } // namespace facebook::yoga diff --git a/capture/NodeToString.cpp b/capture/NodeToString.cpp index a44c8383..675b7e37 100644 --- a/capture/NodeToString.cpp +++ b/capture/NodeToString.cpp @@ -8,7 +8,6 @@ #include #include -#include namespace facebook::yoga { @@ -121,7 +120,7 @@ YGValue borderFloatToYGValue(YGNodeRef node, YGEdge edge) { return YGValue{val, unit}; } -static void nodeToStringImpl(json& j, YGNodeRef node, PrintOptions options) { +void serializeTree(json& j, YGNodeRef node, PrintOptions options) { if ((options & PrintOptions::Layout) == PrintOptions::Layout) { j["layout"]["width"] = YGNodeStyleGetWidth(node).value; j["layout"]["height"] = YGNodeStyleGetHeight(node).value; @@ -303,15 +302,21 @@ static void nodeToStringImpl(json& j, YGNodeRef node, PrintOptions options) { childCount > 0) { for (size_t i = 0; i < childCount; i++) { j["children"].push_back({}); - nodeToStringImpl(j["children"][i], YGNodeGetChild(node, i), options); + serializeTree(j["children"][i], YGNodeGetChild(node, i), options); } } } -void nodeToString(std::string& str, YGNodeRef node, PrintOptions options) { - json j; - nodeToStringImpl(j, node, options); - str = j.dump(2); +void serializeLayoutInputs( + json& j, + float availableWidth, + float availableHeight, + YGDirection ownerDirection) { + j["layout-inputs"] = { + {"available-width", availableWidth}, + {"available-height", availableHeight}, + {"owner-direction", YGDirectionToString(ownerDirection)}, + }; } } // namespace facebook::yoga diff --git a/capture/NodeToString.h b/capture/NodeToString.h index 95afd18b..b1ceb62b 100644 --- a/capture/NodeToString.h +++ b/capture/NodeToString.h @@ -9,6 +9,7 @@ #include +#include #include namespace facebook::yoga { @@ -22,6 +23,12 @@ enum class PrintOptions : uint8_t { }; YG_DEFINE_ENUM_FLAG_OPERATORS(PrintOptions); -void nodeToString(std::string& str, YGNodeRef node, PrintOptions options); +void serializeTree(nlohmann::json& j, YGNodeRef root, PrintOptions options); + +void serializeLayoutInputs( + nlohmann::json& j, + float availableWidth, + float availableHeight, + YGDirection ownerDirection); } // namespace facebook::yoga