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