88
99namespace margelo ::nitro::rnnitrosqlite {
1010
11+ namespace {
12+
13+ /* *
14+ * Compute the approximate external memory size of a single SQLiteValue.
15+ *
16+ * We only need to account for heap allocations that can actually put
17+ * pressure on the JS GC – in practice, that means:
18+ * - `std::string` contents,
19+ * - `ArrayBuffer` instances (object + underlying bytes).
20+ *
21+ * Other variants (`NullType`, `bool`, `double`) are small and live inline.
22+ */
23+ size_t getValueExternalMemorySize (const SQLiteValue& value) {
24+ if (std::holds_alternative<std::string>(value)) {
25+ const auto & stringValue = std::get<std::string>(value);
26+ return stringValue.capacity ();
27+ }
28+
29+ if (std::holds_alternative<std::shared_ptr<ArrayBuffer>>(value)) {
30+ const auto & buffer = std::get<std::shared_ptr<ArrayBuffer>>(value);
31+ if (!buffer) {
32+ return 0 ;
33+ }
34+
35+ const auto bufferSize = buffer->size ();
36+ return sizeof (*buffer.get ()) + bufferSize;
37+ }
38+
39+ return 0 ;
40+ }
41+
42+ /* *
43+ * Compute the approximate external memory size of a single result row.
44+ * This includes:
45+ * - Column name string capacities,
46+ * - Heap usage for the actual SQLiteValue contents.
47+ */
48+ size_t getRowExternalMemorySize (const SQLiteQueryResultRow& row) {
49+ size_t size = 0 ;
50+
51+ for (const auto & entry : row) {
52+ const auto & columnName = entry.first ;
53+ const auto & value = entry.second ;
54+
55+ size += columnName.capacity ();
56+ size += getValueExternalMemorySize (value);
57+ }
58+
59+ return size;
60+ }
61+
62+ /* *
63+ * Compute the approximate external memory size of the full result set.
64+ * We add:
65+ * - The vector's backing storage,
66+ * - All rows (column names + values).
67+ */
68+ size_t getResultsExternalMemorySize (const SQLiteQueryResults& results) {
69+ size_t size = 0 ;
70+
71+ const auto resultCapacity = results.capacity ();
72+ size += resultCapacity * sizeof (SQLiteQueryResultRow);
73+
74+ for (const auto & row : results) {
75+ size += getRowExternalMemorySize (row);
76+ }
77+
78+ return size;
79+ }
80+
81+ /* *
82+ * Compute the approximate external memory size of the table metadata.
83+ * We include:
84+ * - Column name string capacities (map keys),
85+ * - Metadata contents, especially the `name` string on each metadata entry.
86+ */
87+ size_t getMetadataExternalMemorySize (const SQLiteQueryTableMetadata& metadata) {
88+ size_t size = 0 ;
89+
90+ for (const auto & entry : metadata) {
91+ const auto & columnName = entry.first ;
92+ const auto & columnMeta = entry.second ;
93+
94+ size += columnName.capacity ();
95+ size += columnMeta.name .capacity ();
96+ }
97+
98+ return size;
99+ }
100+
101+ } // namespace
102+
11103std::optional<double > HybridNitroSQLiteQueryResult::getInsertId () {
12104 return _insertId;
13105}
@@ -24,4 +116,16 @@ std::optional<SQLiteQueryTableMetadata> HybridNitroSQLiteQueryResult::getMetadat
24116 return _metadata;
25117}
26118
119+ size_t HybridNitroSQLiteQueryResult::getExternalMemorySize () noexcept {
120+ size_t size = sizeof (*this );
121+
122+ size += getResultsExternalMemorySize (_results);
123+
124+ if (_metadata) {
125+ size += getMetadataExternalMemorySize (*_metadata);
126+ }
127+
128+ return size;
129+ }
130+
27131} // namespace margelo::nitro::rnnitrosqlite
0 commit comments