rippled
Loading...
Searching...
No Matches
tests/libxrpl/basics/MallocTrim.cpp
1#include <xrpl/basics/MallocTrim.h>
2
3#include <boost/predef.h>
4
5#include <gtest/gtest.h>
6
7using namespace xrpl;
8
9// cSpell:ignore statm
10
11#if defined(__GLIBC__) && BOOST_OS_LINUX
12namespace xrpl::detail {
13long
14parseStatmRSSkB(std::string const& statm);
15} // namespace xrpl::detail
16#endif
17
18TEST(MallocTrimReport, structure)
19{
20 // Test default construction
21 MallocTrimReport report;
22 EXPECT_EQ(report.supported, false);
23 EXPECT_EQ(report.trimResult, -1);
24 EXPECT_EQ(report.rssBeforeKB, -1);
25 EXPECT_EQ(report.rssAfterKB, -1);
26 EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
27 EXPECT_EQ(report.minfltDelta, -1);
28 EXPECT_EQ(report.majfltDelta, -1);
29 EXPECT_EQ(report.deltaKB(), 0);
30
31 // Test deltaKB calculation - memory freed
32 report.rssBeforeKB = 1000;
33 report.rssAfterKB = 800;
34 EXPECT_EQ(report.deltaKB(), -200);
35
36 // Test deltaKB calculation - memory increased
37 report.rssBeforeKB = 500;
38 report.rssAfterKB = 600;
39 EXPECT_EQ(report.deltaKB(), 100);
40
41 // Test deltaKB calculation - no change
42 report.rssBeforeKB = 1234;
43 report.rssAfterKB = 1234;
44 EXPECT_EQ(report.deltaKB(), 0);
45}
46
47#if defined(__GLIBC__) && BOOST_OS_LINUX
48TEST(parseStatmRSSkB, standard_format)
49{
50 using xrpl::detail::parseStatmRSSkB;
51
52 // Test standard format: size resident shared text lib data dt
53 // Assuming 4KB page size: resident=1000 pages = 4000 KB
54 {
55 std::string const statm = "25365 1000 2377 0 0 5623 0";
56 long const result = parseStatmRSSkB(statm);
57 // Note: actual result depends on system page size
58 // On most systems it's 4KB, so 1000 pages = 4000 KB
59 EXPECT_GT(result, 0);
60 }
61
62 // Test with newline
63 {
64 std::string const statm = "12345 2000 1234 0 0 3456 0\n";
65 long const result = parseStatmRSSkB(statm);
66 EXPECT_GT(result, 0);
67 }
68
69 // Test with tabs
70 {
71 std::string const statm = "12345\t2000\t1234\t0\t0\t3456\t0";
72 long const result = parseStatmRSSkB(statm);
73 EXPECT_GT(result, 0);
74 }
75
76 // Test zero resident pages
77 {
78 std::string const statm = "25365 0 2377 0 0 5623 0";
79 long const result = parseStatmRSSkB(statm);
80 EXPECT_EQ(result, 0);
81 }
82
83 // Test with extra whitespace
84 {
85 std::string const statm = " 25365 1000 2377 ";
86 long const result = parseStatmRSSkB(statm);
87 EXPECT_GT(result, 0);
88 }
89
90 // Test empty string
91 {
92 std::string const statm;
93 long const result = parseStatmRSSkB(statm);
94 EXPECT_EQ(result, -1);
95 }
96
97 // Test malformed data (only one field)
98 {
99 std::string const statm = "25365";
100 long const result = parseStatmRSSkB(statm);
101 EXPECT_EQ(result, -1);
102 }
103
104 // Test malformed data (non-numeric)
105 {
106 std::string const statm = "abc def ghi";
107 long const result = parseStatmRSSkB(statm);
108 EXPECT_EQ(result, -1);
109 }
110
111 // Test malformed data (second field non-numeric)
112 {
113 std::string const statm = "25365 abc 2377";
114 long const result = parseStatmRSSkB(statm);
115 EXPECT_EQ(result, -1);
116 }
117}
118#endif
119
120TEST(mallocTrim, without_debug_logging)
121{
123
124 MallocTrimReport const report = mallocTrim("without_debug", journal);
125
126#if defined(__GLIBC__) && BOOST_OS_LINUX
127 EXPECT_EQ(report.supported, true);
128 EXPECT_GE(report.trimResult, 0);
129 EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
130 EXPECT_EQ(report.minfltDelta, -1);
131 EXPECT_EQ(report.majfltDelta, -1);
132#else
133 EXPECT_EQ(report.supported, false);
134 EXPECT_EQ(report.trimResult, -1);
135 EXPECT_EQ(report.rssBeforeKB, -1);
136 EXPECT_EQ(report.rssAfterKB, -1);
137 EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
138 EXPECT_EQ(report.minfltDelta, -1);
139 EXPECT_EQ(report.majfltDelta, -1);
140#endif
141}
142
143TEST(mallocTrim, empty_tag)
144{
146 MallocTrimReport const report = mallocTrim("", journal);
147
148#if defined(__GLIBC__) && BOOST_OS_LINUX
149 EXPECT_EQ(report.supported, true);
150 EXPECT_GE(report.trimResult, 0);
151#else
152 EXPECT_EQ(report.supported, false);
153#endif
154}
155
156TEST(mallocTrim, with_debug_logging)
157{
158 struct DebugSink : public beast::Journal::Sink
159 {
160 DebugSink() : Sink(beast::severities::kDebug, false)
161 {
162 }
163 void
165 {
166 }
167 void
168 writeAlways(beast::severities::Severity, std::string const&) override
169 {
170 }
171 };
172
173 DebugSink sink;
174 beast::Journal const journal{sink};
175
176 MallocTrimReport const report = mallocTrim("debug_test", journal);
177
178#if defined(__GLIBC__) && BOOST_OS_LINUX
179 EXPECT_EQ(report.supported, true);
180 EXPECT_GE(report.trimResult, 0);
181 EXPECT_GE(report.durationUs.count(), 0);
182 EXPECT_GE(report.minfltDelta, 0);
183 EXPECT_GE(report.majfltDelta, 0);
184#else
185 EXPECT_EQ(report.supported, false);
186 EXPECT_EQ(report.trimResult, -1);
187 EXPECT_EQ(report.durationUs, std::chrono::microseconds{-1});
188 EXPECT_EQ(report.minfltDelta, -1);
189 EXPECT_EQ(report.majfltDelta, -1);
190#endif
191}
192
193TEST(mallocTrim, repeated_calls)
194{
196
197 // Call malloc_trim multiple times to ensure it's safe
198 for (int i = 0; i < 5; ++i)
199 {
200 MallocTrimReport const report = mallocTrim("iteration_" + std::to_string(i), journal);
201
202#if defined(__GLIBC__) && BOOST_OS_LINUX
203 EXPECT_EQ(report.supported, true);
204 EXPECT_GE(report.trimResult, 0);
205#else
206 EXPECT_EQ(report.supported, false);
207#endif
208 }
209}
Abstraction for the underlying message destination.
Definition Journal.h:56
A generic endpoint for log messages.
Definition Journal.h:40
static Sink & getNullSink()
Returns a Sink which does nothing.
Severity
Severity level / threshold of a Journal message.
Definition Journal.h:12
void write(nudb::detail::ostream &os, std::size_t t)
Definition varint.h:115
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5
MallocTrimReport mallocTrim(std::string_view tag, beast::Journal journal)
Attempt to return freed memory to the operating system.
std::int64_t majfltDelta
Definition MallocTrim.h:35
std::int64_t minfltDelta
Definition MallocTrim.h:34
std::chrono::microseconds durationUs
Definition MallocTrim.h:33
std::int64_t deltaKB() const noexcept
Definition MallocTrim.h:38
std::int64_t rssAfterKB
Definition MallocTrim.h:32
std::int64_t rssBeforeKB
Definition MallocTrim.h:31
T to_string(T... args)