Skip to content

Commit 31a9e7e

Browse files
Fix per-node memory regression caused by Grid styles
Summary: # Why Currently, grid style properties are stored in yoga style (`gridTemplateRows_`, `gridAutoColumns_` etc). These properties increase the size of style object from `152` bytes to `280` bytes (84% increase). The cost is added even when a node is not a grid container or a grid item. # How Move grid style properties behind a pointer that is lazily allocated, on the first grid property set. A node that doesn't use grid only adds the cost of this pointer (8 bytes). So style now costs 160 bytes (5% increase). The public API remains unchanged. # Tests A test is added to catch the style size regression and `tests/GridStyleTest.cpp` includes additional cases to assert unset style, copy and move behaviour. X-link: react/yoga#2018 Differential Revision: D118628661 Pulled By: javache
1 parent bbdeb7d commit 31a9e7e

2 files changed

Lines changed: 108 additions & 41 deletions

File tree

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
/*
2+
* Copyright (c) Meta Platforms, Inc. and affiliates.
3+
*
4+
* This source code is licensed under the MIT license found in the
5+
* LICENSE file in the root directory of this source tree.
6+
*/
7+
8+
#pragma once
9+
10+
#include <memory>
11+
12+
#include <yoga/style/GridLine.h>
13+
#include <yoga/style/GridTrack.h>
14+
15+
namespace facebook::yoga {
16+
17+
/**
18+
* The CSS Grid properties of a single node.
19+
*/
20+
struct GridStyle {
21+
// Grid container properties
22+
GridTrackList templateColumns{};
23+
GridTrackList templateRows{};
24+
GridTrackList autoColumns{};
25+
GridTrackList autoRows{};
26+
27+
// Grid item properties
28+
GridLine columnStart{};
29+
GridLine columnEnd{};
30+
GridLine rowStart{};
31+
GridLine rowEnd{};
32+
33+
bool operator==(const GridStyle& other) const = default;
34+
};
35+
36+
/**
37+
* Storage for a GridStyle which stays empty until the first grid property is
38+
* set.
39+
*/
40+
class GridStyleStorage {
41+
public:
42+
GridStyleStorage() = default;
43+
GridStyleStorage(GridStyleStorage&&) noexcept = default;
44+
GridStyleStorage& operator=(GridStyleStorage&&) noexcept = default;
45+
46+
GridStyleStorage(const GridStyleStorage& other) {
47+
*this = other;
48+
}
49+
50+
GridStyleStorage& operator=(const GridStyleStorage& other) {
51+
grid_ = other.grid_ == nullptr ? nullptr
52+
: std::make_unique<GridStyle>(*other.grid_);
53+
return *this;
54+
}
55+
56+
const GridStyle& get() const {
57+
return grid_ == nullptr ? defaults() : *grid_;
58+
}
59+
60+
GridStyle& ensure() {
61+
if (grid_ == nullptr) {
62+
grid_ = std::make_unique<GridStyle>();
63+
}
64+
return *grid_;
65+
}
66+
67+
bool operator==(const GridStyleStorage& other) const {
68+
return grid_ == other.grid_ || get() == other.get();
69+
}
70+
71+
private:
72+
static const GridStyle& defaults() {
73+
static const GridStyle kDefaults{};
74+
return kDefaults;
75+
}
76+
77+
std::unique_ptr<GridStyle> grid_{};
78+
};
79+
80+
} // namespace facebook::yoga

packages/react-native/ReactCommon/yoga/yoga/style/Style.h

Lines changed: 28 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <yoga/enums/Wrap.h>
3131
#include <yoga/numeric/FloatOptional.h>
3232
#include <yoga/style/GridLine.h>
33+
#include <yoga/style/GridStyle.h>
3334
#include <yoga/style/GridTrack.h>
3435
#include <yoga/style/StyleLength.h>
3536
#include <yoga/style/StyleSizeLength.h>
@@ -209,84 +210,84 @@ class YG_EXPORT Style {
209210

210211
// Grid Container Properties
211212
const GridTrackList& gridTemplateColumns() const {
212-
return gridTemplateColumns_;
213+
return grid_.get().templateColumns;
213214
}
214215
void setGridTemplateColumns(GridTrackList value) {
215-
gridTemplateColumns_ = std::move(value);
216+
grid_.ensure().templateColumns = std::move(value);
216217
}
217218
void resizeGridTemplateColumns(size_t count) {
218-
gridTemplateColumns_.resize(count);
219+
grid_.ensure().templateColumns.resize(count);
219220
}
220221
void setGridTemplateColumnAt(size_t index, GridTrackSize value) {
221-
gridTemplateColumns_[index] = value;
222+
grid_.ensure().templateColumns[index] = value;
222223
}
223224

224225
const GridTrackList& gridTemplateRows() const {
225-
return gridTemplateRows_;
226+
return grid_.get().templateRows;
226227
}
227228
void setGridTemplateRows(GridTrackList value) {
228-
gridTemplateRows_ = std::move(value);
229+
grid_.ensure().templateRows = std::move(value);
229230
}
230231
void resizeGridTemplateRows(size_t count) {
231-
gridTemplateRows_.resize(count);
232+
grid_.ensure().templateRows.resize(count);
232233
}
233234
void setGridTemplateRowAt(size_t index, GridTrackSize value) {
234-
gridTemplateRows_[index] = value;
235+
grid_.ensure().templateRows[index] = value;
235236
}
236237

237238
const GridTrackList& gridAutoColumns() const {
238-
return gridAutoColumns_;
239+
return grid_.get().autoColumns;
239240
}
240241
void setGridAutoColumns(GridTrackList value) {
241-
gridAutoColumns_ = std::move(value);
242+
grid_.ensure().autoColumns = std::move(value);
242243
}
243244
void resizeGridAutoColumns(size_t count) {
244-
gridAutoColumns_.resize(count);
245+
grid_.ensure().autoColumns.resize(count);
245246
}
246247
void setGridAutoColumnAt(size_t index, GridTrackSize value) {
247-
gridAutoColumns_[index] = value;
248+
grid_.ensure().autoColumns[index] = value;
248249
}
249250

250251
const GridTrackList& gridAutoRows() const {
251-
return gridAutoRows_;
252+
return grid_.get().autoRows;
252253
}
253254
void setGridAutoRows(GridTrackList value) {
254-
gridAutoRows_ = std::move(value);
255+
grid_.ensure().autoRows = std::move(value);
255256
}
256257
void resizeGridAutoRows(size_t count) {
257-
gridAutoRows_.resize(count);
258+
grid_.ensure().autoRows.resize(count);
258259
}
259260
void setGridAutoRowAt(size_t index, GridTrackSize value) {
260-
gridAutoRows_[index] = value;
261+
grid_.ensure().autoRows[index] = value;
261262
}
262263

263264
// Grid Item Properties
264265
const GridLine& gridColumnStart() const {
265-
return gridColumnStart_;
266+
return grid_.get().columnStart;
266267
}
267268
void setGridColumnStart(GridLine value) {
268-
gridColumnStart_ = value;
269+
grid_.ensure().columnStart = value;
269270
}
270271

271272
const GridLine& gridColumnEnd() const {
272-
return gridColumnEnd_;
273+
return grid_.get().columnEnd;
273274
}
274275
void setGridColumnEnd(GridLine value) {
275-
gridColumnEnd_ = value;
276+
grid_.ensure().columnEnd = value;
276277
}
277278

278279
const GridLine& gridRowStart() const {
279-
return gridRowStart_;
280+
return grid_.get().rowStart;
280281
}
281282
void setGridRowStart(GridLine value) {
282-
gridRowStart_ = value;
283+
grid_.ensure().rowStart = value;
283284
}
284285

285286
const GridLine& gridRowEnd() const {
286-
return gridRowEnd_;
287+
return grid_.get().rowEnd;
287288
}
288289
void setGridRowEnd(GridLine value) {
289-
gridRowEnd_ = value;
290+
grid_.ensure().rowEnd = value;
290291
}
291292

292293
FloatOptional resolvedMinDimension(
@@ -667,14 +668,7 @@ class YG_EXPORT Style {
667668
sizeLengthsEqual(
668669
maxDimensions_, pool_, other.maxDimensions_, other.pool_) &&
669670
numbersEqual(aspectRatio_, pool_, other.aspectRatio_, other.pool_) &&
670-
gridTemplateColumns_ == other.gridTemplateColumns_ &&
671-
gridTemplateRows_ == other.gridTemplateRows_ &&
672-
gridAutoColumns_ == other.gridAutoColumns_ &&
673-
gridAutoRows_ == other.gridAutoRows_ &&
674-
gridColumnStart_ == other.gridColumnStart_ &&
675-
gridColumnEnd_ == other.gridColumnEnd_ &&
676-
gridRowStart_ == other.gridRowStart_ &&
677-
gridRowEnd_ == other.gridRowEnd_;
671+
grid_ == other.grid_;
678672
}
679673

680674
private:
@@ -929,15 +923,8 @@ class YG_EXPORT Style {
929923
Dimensions maxDimensions_{};
930924
StyleValueHandle aspectRatio_{};
931925

932-
// Grid properties
933-
GridTrackList gridTemplateColumns_{};
934-
GridTrackList gridTemplateRows_{};
935-
GridTrackList gridAutoColumns_{};
936-
GridTrackList gridAutoRows_{};
937-
GridLine gridColumnStart_{};
938-
GridLine gridColumnEnd_{};
939-
GridLine gridRowStart_{};
940-
GridLine gridRowEnd_{};
926+
// Grid properties, allocated only when one of them is set
927+
GridStyleStorage grid_{};
941928

942929
StyleValuePool pool_;
943930
};

0 commit comments

Comments
 (0)