Stroika Library 3.0d16
 
Loading...
Searching...
No Matches
Memory.h
1/*
2 * Copyright(c) Sophist Solutions, Inc. 1990-2025. All rights reserved
3 */
4#ifndef _Stroika_Framework_SystemPerformance_Instruments_Memory_h_
5#define _Stroika_Framework_SystemPerformance_Instruments_Memory_h_ 1
6
7#include "Stroika/Frameworks/StroikaPreComp.h"
8
9#include <optional>
10
11#include "Stroika/Foundation/DataExchange/ObjectVariantMapper.h"
12#include "Stroika/Frameworks/SystemPerformance/Instrument.h"
13
14/*
15 * \file
16 *
17 * \note Code-Status: <a href="Code-Status.md#Beta">Beta</a>
18 *
19 */
20
21namespace Stroika::Frameworks::SystemPerformance::Instruments::Memory {
22
23 using DataExchange::ObjectVariantMapper;
24
25 /**
26 * @see https://www.centos.org/docs/5/html/5.1/Deployment_Guide/s2-proc-meminfo.html
27 * @see https://github.com/torvalds/linux/blob/master/Documentation/filesystems/proc.txt
28 */
29 struct Info {
30 /**
31 * Details (statistics) focused on Physical RAM.
32 *
33 * \note TOTAL_RAM = FREE + INACTIVE + ACTIVE + OS-RESERVED
34 */
36 /**
37 * The amount of physical RAM, left unused by the system (in bytes).
38 *
39 * From Linux:
40 * /proc/meminfo::MemFree
41 *
42 * From Windows:
43 * ::GlobalMemoryStatusEx (&statex), statex.ullAvailPhys
44 *
45 */
46 optional<uint64_t> fFree{};
47
48 /**
49 * The amount of physical RAM which is actively being used.
50 *
51 * For AIX:
52 * perfstat_memory_total_t::real_process
53 * Number of pages used by process segments.
54 *
55 * This is a WEAK definition for AIX, but I haven't yet found better. I cannot even find free's list of 'cached and buffers' to subtract from
56 * total RAM. Also no working-set-size
57 *
58 * From Linux:
59 * /proc/meminfo::Active
60 * Memory that has been used more recently and usually not
61 * reclaimed unless absolutely necessary.
62 *
63 * (possibly should add kernel meminfo::Buffers to this?)
64 *
65 * From Windows:
66 * MEMORYSTATUSEX::dwMemoryLoad * MEMORYSTATUSEX::ullTotalPhys / 100
67 */
68 optional<uint64_t> fActive{};
69
70 /**
71 * The amount of physical RAM which is in use, but not actively. Windows calls this 'Standby'
72 *
73 * For AIX:
74 * @todo - WRONG
75 * perfstat_memory_total_t::real_process
76 * Number of pages used by process segments.
77 *
78 * This is a WEAK definition for AIX, but I haven't yet found better. I cannot even find free's list of 'cached and buffers' to subtract from
79 * total RAM. Also no working-set-size
80 *
81 * From Linux:
82 * /proc/meminfo::Inactive
83 * Inactive: Memory which has been less recently used. It is more
84 * eligible to be reclaimed for other purposes.
85 *
86 * From Windows:
87 * @todo Total RAM - ActiveMemory(MEMORYSTATUSEX::dwMemoryLoad * MEMORYSTATUSEX::ullTotalPhys / 100) - Free-Memory(how)
88 */
89 optional<uint64_t> fInactive{};
90
91 /**
92 * This can be thought of as roughly Free and Inactive memory.
93 *
94 * Where possible, it is retrieved from the OS, as an indication of the amount of memory that can be
95 * allocated by new workloads without causing significant paging.
96 *
97 * On Linux (see https://github.com/torvalds/linux/blob/master/Documentation/filesystems/proc.txt
98 * 'MemAvailable', or (@todo future) summing used working set sizes of processes).
99 *
100 * On AIX, this is 'real_avail': ... memory available without paging out working segments
101 */
102 optional<uint64_t> fAvailable{};
103
104 /**
105 * This is for kernel/OS memory, not otherwise accounted. On Linux, this appears to be largely made up of
106 * 'Slab', 'KernelStack' and perhaps 'PageTables'.
107 */
108 optional<uint64_t> fOSReserved{};
109
110#if 0
111 optional<uint64_t> TotalRAM () const
112 {
113 return fFree + fInactive + fActive + fOSReserved;
114 }
115#endif
116 /**
117 * @see Characters::ToString ();
118 */
119 nonvirtual String ToString () const;
120 };
121 PhysicalRAMDetailsType fPhysicalMemory;
122
123 /**
124 * Details (statistics) virtual Memory (excluding paging since thats between VM and Physical)
125 */
127 /**
128 * DEFINITION UNCLEAR (cross-platform):
129 * But roughtly - this is the number of bytes of pagefile allocated + number of bytes of physical memory.
130 *
131 * We use as our definition of this "Limit" from http://en.wikipedia.org/wiki/Commit_charge
132 * Limit is the maximum possible value for Total; it is the sum of the current pagefile size plus the physical memory
133 * available for pageable contents (this excludes RAM that is assigned to non-pageable areas).
134 * The corresponding performance counter is called "Commit Limit".
135 *
136 * From Linux:
137 * /proc/meminfo::CommitLimit
138 *
139 * Note - on Linux - this value is controlled BOTH by the amount of RAM, and overcommit ratio.
140 * @see https://www.kernel.org/doc/Documentation/vm/overcommit-accounting about
141 * sysctl vm.overcommit_memory vm.overcommit_ratio
142 *
143 * So from: http://liyiadam.blogspot.com/2008/01/procmeminfo.html
144 * CommitLimit: Based on the overcommit ratio ('vm.overcommit_ratio'),
145 * this is the total amount of memory currently available to
146 * be allocated on the system. This limit is only adhered to
147 * if strict overcommit accounting is enabled (mode 2 in
148 * 'vm.overcommit_memory').
149 *
150 * The CommitLimit is calculated with the following formula:
151 * CommitLimit = ('vm.overcommit_ratio' * Physical RAM) + Swap
152 *
153 * For example, on a system with 1G of physical RAM and 7G
154 * of swap with a `vm.overcommit_ratio` of 30 it would
155 * yield a CommitLimit of 7.3G
156 *
157 * (note that overcommit_ratio is a PERCENTAGE).
158 *
159 * From Windows:
160 * WMI: "Memory(_Total)/Commit Limit"
161 *
162 * Commit Limit is the amount of virtual memory that can be committed without having to extend
163 * the paging file(s). It is measured in bytes.
164 * Committed memory is the physical memory which has space reserved on the disk paging files.
165 * There can be one paging file on each logical drive). If the paging file(s) are be expanded,
166 * this limit increases accordingly.
167 */
168 optional<uint64_t> fCommitLimit{};
169
170 /**
171 * From Windows:
172 * WMI: "Memory(_Total)/Committed Bytes"
173 *
174 * Committed Bytes is the amount of committed virtual memory, in bytes.
175 * Committed memory is the physical memory which has space reserved on the disk paging file(s).
176 * There can be one or more paging files on each physical drive.
177 *
178 * From Linux (http://lwn.net/Articles/28345/)
179 * /proc/meminfo: Committed_AS:
180 *
181 * An estimate of how much RAM you would need to make a
182 * 99.99% guarantee that there never is OOM (out of memory)
183 * for this workload. Normally the kernel will overcommit
184 * memory. That means, say you do a 1GB malloc, nothing
185 * happens, really. Only when you start USING that malloc
186 * memory you will get real memory on demand, and just as
187 * much as you use. So you sort of take a mortgage and hope
188 * the bank doesn't go bust. Other cases might include when
189 * you mmap a file that's shared only when you write to it
190 * and you get a private copy of that data. While it normally
191 * is shared between processes. The Committed_AS is a
192 * guesstimate of how much RAM/swap you would need
193 * worst-case.
194 *
195 * From https://github.com/torvalds/linux/blob/master/Documentation/filesystems/proc.txt
196 * Committed_AS:
197 * The amount of memory presently allocated on the system.
198 * The committed memory is a sum of all of the memory which
199 * has been allocated by processes, even if it has not been
200 * "used" by them as of yet. A process which malloc()'s 1G
201 * of memory, but only touches 300M of it will show up as
202 * using 1G. This 1G is memory which has been "committed" to
203 * by the VM and can be used at any time by the allocating
204 * application. With strict overcommit enabled on the system
205 * (mode 2 in 'vm.overcommit_memory'),allocations which would
206 * exceed the CommitLimit (detailed above) will not be permitted.
207 * This is useful if one needs to guarantee that processes will
208 * not fail due to lack of memory once that memory has been
209 * successfully allocated.
210 *
211 * For AIX:
212 * RAM IN USE + PageFile INUSE
213 *
214 * So in ALL cases it represents 'total reserved VM' but in the Linux case, its a weaker
215 * form of reservation.
216 */
217 optional<uint64_t> fCommittedBytes{};
218
219 /**
220 * Total size of all loaded swapfiles (or on windows pagefiles).
221 *
222 * On Linux:
223 * /proc/meminfo::SwapTotal
224 * On Windows:
225 * MEMORYSTATUSEX::ullTotalPageFile
226 */
227 optional<uint64_t> fPagefileTotalSize{};
228
229 /**
230 * @see Characters::ToString ();
231 */
232 nonvirtual String ToString () const;
233 };
234 VirtualMemoryDetailsType fVirtualMemory;
235
236 /**
237 * Details(statistics) related to paging between virtual and physical RAM
238 */
240 /**
241 * @see http://en.wikipedia.org/wiki/Page_fault
242 * @see http://www.linuxinsight.com/proc_vmstat.html
243 *
244 * fMajorPageFaultsSinceBoot is the number of major (requiring a disk read)
245 * faults since the system booted.
246 *
247 * @see /proc/vmstat::pgmajfault
248 * @see /proc/vmstat::pgfault
249 */
250 optional<uint64_t> fMajorPageFaultsSinceBoot{};
251
252 /**
253 * @see http://en.wikipedia.org/wiki/Page_fault
254 * @see http://www.linuxinsight.com/proc_vmstat.html
255 *
256 * fMinorPageFaultsSinceBoot is the number of minor (not requiring a disk read)
257 * faults since the system booted.
258 *
259 * @see /proc/vmstat::pgfault and proc/vmstat::pgmajfault (this is pgfault-pgmajfault)
260 */
261 optional<uint64_t> fMinorPageFaultsSinceBoot{};
262
263 /**
264 * Total number of (dirty) pages written to the page store.
265 *
266 * Linux /proc/vmstat : pgpgout
267 * CANNOT find docs on this but it appears to be the total number of pages paged out since boot
268 */
269 optional<uint64_t> fPageOutsSinceBoot{};
270
271 /**
272 * @see fMajorPageFaultsSinceBoot.
273 *
274 * This is not computed in the first call to the intstrument, but based on successive calls
275 */
276 optional<double> fMajorPageFaultsPerSecond{};
277
278 /**
279 * @see fMinorPageFaultsSinceBoot.
280 *
281 * This is not computed in the first call to the intstrument, but based on successive calls
282 */
283 optional<double> fMinorPageFaultsPerSecond{};
284
285 /**
286 * @see fPageOutsSinceBoot.
287 */
288 optional<double> fPageOutsPerSecond{};
289
290 /**
291 * @see Characters::ToString ();
292 */
293 nonvirtual String ToString () const;
294 };
295 PagingDetailsType fPaging;
296
297 /**
298 * @see Characters::ToString ();
299 */
300 nonvirtual String ToString () const;
301 };
302
303 /**
304 * To control the behavior of the instrument.
305 */
306 struct Options {
307 /**
308 * To compute averages, the instrument may keep around some earlier snapshots of data. This time interval is regulated by how often
309 * the capture is called (typically the Captureset::'run interval'. However, this value can be used to override that partly, and provide
310 * a minimum time for averaging.
311 *
312 * If you call capture more frequently than this interval, some (averaged) items maybe missing from the result.
313 *
314 * \pre fMinimumAveragingInterval > 0
315 */
317 };
318
319 /**
320 * This class is designed to be object-sliced into just the SystemPerformance::Instrument
321 *
322 * \note Constructing the instrument does no capturing (so sb quick/cheap) - capturing starts when you
323 * first call i.Capture()
324 */
326 public:
327 Instrument (const Options& options = Options{});
328
329 public:
330 /**
331 * For Instruments::Memory::Info, etc types.
332 */
334 };
335
336}
337
338namespace Stroika::Frameworks::SystemPerformance {
339 /*
340 * Specialization to improve performance
341 */
342 template <>
344}
345
346/*
347 ********************************************************************************
348 ***************************** Implementation Details ***************************
349 ********************************************************************************
350 */
351
352#endif /*_Stroika_Framework_SystemPerformance_Instruments_Memory_h_*/
chrono::duration< double > DurationSeconds
chrono::duration<double> - a time span (length of time) measured in seconds, but high precision.
Definition Realtime.h:57
String is like std::u32string, except it is much easier to use, often much more space efficient,...
Definition String.h:201
ObjectVariantMapper can be used to map C++ types to and from variant-union types, which can be transp...
An Instrument is a stateful object from which you can Capture () a series of measurements about a sys...
Definition Instrument.h:69
nonvirtual T CaptureOneMeasurement(Range< TimePointSeconds > *measurementTimeOut=nullptr)