Skip to content

Commit dee8bec

Browse files
chrispadermrousavy
andauthored
feat: Implement Nitro's getExternalMemorySize (#261)
* feat: implement Nitro's `getExternalMemorySize` * Update package/cpp/specs/HybridNitroSQLiteQueryResult.cpp Co-authored-by: Marc Rousavy <me@mrousavy.com> * Update package/cpp/specs/HybridNitroSQLiteQueryResult.cpp Co-authored-by: Marc Rousavy <me@mrousavy.com> * fix: remove unnecessary memory size calculation for `HybridNitroSQLite` class * fix: improve memory size calculation based on @mrousavy's review * fix: add back empty line --------- Co-authored-by: Marc Rousavy <me@mrousavy.com>
1 parent a96e730 commit dee8bec

2 files changed

Lines changed: 81 additions & 0 deletions

File tree

package/cpp/specs/HybridNitroSQLiteQueryResult.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,60 @@
88

99
namespace margelo::nitro::rnnitrosqlite {
1010

11+
namespace {
12+
13+
/**
14+
* Compute the approximate external memory size of a single result row.
15+
* This includes:
16+
* - Column name string capacities,
17+
* - Heap usage for the actual SQLiteValue contents.
18+
*/
19+
size_t getRowExternalMemorySize(const SQLiteQueryResultRow& row) {
20+
size_t bucketMemory = row.bucket_count() * sizeof(void*);
21+
constexpr size_t nodePadding = 24;
22+
size_t nodesMemory = row.size() * (sizeof(std::pair<std::string, SQLiteValue>) * nodePadding);
23+
return bucketMemory + nodesMemory;
24+
}
25+
26+
/**
27+
* Compute the approximate external memory size of the full result set.
28+
* We add:
29+
* - The vector's backing storage,
30+
* - All rows (column names + values).
31+
*/
32+
size_t getResultsExternalMemorySize(const SQLiteQueryResults& results) {
33+
size_t size = sizeof(SQLiteQueryResults);
34+
35+
const auto resultCapacity = results.capacity();
36+
size += resultCapacity * sizeof(SQLiteQueryResultRow);
37+
38+
for (const auto& row : results) {
39+
size += getRowExternalMemorySize(row);
40+
}
41+
42+
return size;
43+
}
44+
45+
/**
46+
* Compute the approximate external memory size of the table metadata.
47+
* We include:
48+
* - Column name string capacities (map keys),
49+
* - Metadata contents, especially the `name` string on each metadata entry.
50+
*/
51+
size_t getMetadataExternalMemorySize(const SQLiteQueryTableMetadata& metadata) {
52+
size_t size = 0;
53+
54+
for (const auto& [columnName, columnMeta] : metadata) {
55+
56+
size += columnName.capacity();
57+
size += columnMeta.name.capacity();
58+
}
59+
60+
return size;
61+
}
62+
63+
} // namespace
64+
1165
std::optional<double> HybridNitroSQLiteQueryResult::getInsertId() {
1266
return _insertId;
1367
}
@@ -24,4 +78,16 @@ std::optional<SQLiteQueryTableMetadata> HybridNitroSQLiteQueryResult::getMetadat
2478
return _metadata;
2579
}
2680

81+
size_t HybridNitroSQLiteQueryResult::getExternalMemorySize() noexcept {
82+
size_t size = sizeof(*this);
83+
84+
size += getResultsExternalMemorySize(_results);
85+
86+
if (_metadata) {
87+
size += getMetadataExternalMemorySize(*_metadata);
88+
}
89+
90+
return size;
91+
}
92+
2793
} // namespace margelo::nitro::rnnitrosqlite

package/cpp/specs/HybridNitroSQLiteQueryResult.hpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,21 @@ class HybridNitroSQLiteQueryResult : public HybridNitroSQLiteQueryResultSpec {
2727
double getRowsAffected() override;
2828
SQLiteQueryResults getResults() override;
2929
std::optional<SQLiteQueryTableMetadata> getMetadata() override;
30+
31+
/**
32+
* Approximate the native memory used by this query result.
33+
*
34+
* We account for:
35+
* - The size of this C++ object (`sizeof(*this)`),
36+
* - All rows and columns (including column name strings),
37+
* - String values stored in the result set,
38+
* - ArrayBuffers used for BLOB columns (object overhead + raw byte size),
39+
* - Column metadata strings.
40+
*
41+
* This is a best-effort estimate and intentionally focuses on external
42+
* heap allocations that can put pressure on the JS GC.
43+
*/
44+
size_t getExternalMemorySize() noexcept override;
3045
};
3146

3247
} // namespace margelo::nitro::rnnitrosqlite

0 commit comments

Comments
 (0)