Raptor 3.0.0-rc.1
A fast and space-efficient pre-filter for querying very large collections of nucleotide sequences
 
memory_usage.hpp
Go to the documentation of this file.
1// --------------------------------------------------------------------------------------------------
2// Copyright (c) 2006-2023, Knut Reinert & Freie Universität Berlin
3// Copyright (c) 2016-2023, Knut Reinert & MPI für molekulare Genetik
4// This file may be used, modified and/or redistributed under the terms of the 3-clause BSD-License
5// shipped with this file and also available at: https://github.com/seqan/raptor/blob/main/LICENSE.md
6// --------------------------------------------------------------------------------------------------
7
13#pragma once
14
15#include <cassert>
16#include <string>
17
18#if __has_include(<sys/resource.h>)
19# include <sys/resource.h>
20#endif
21
22namespace raptor
23{
24
25namespace detail
26{
27
28#if __has_include(<sys/resource.h>)
29// Returns -1 if not available. Actually returns bytes instead of KiB on macOS.
30inline long peak_ram_in_KiB()
31{
32 rusage usage;
33 return getrusage(RUSAGE_SELF, &usage) == 0 ? usage.ru_maxrss : -1L;
34}
35#else
36inline long peak_ram_in_KiB()
37{
38 return -1L;
39}
40#endif
41
42[[nodiscard]] inline std::string formatted_peak_ram(size_t const bytes)
43{
44 assert(bytes > 0);
45
46 size_t iterations{};
47 size_t integer{bytes};
48
49 while (integer >> 10u && iterations < 6u)
50 {
51 integer >>= 10u;
52 ++iterations;
53 }
54
55 // While this is a bit more involved, we can avoid using floating point numbers.
56 auto first_decimal_position = [&]()
57 {
58 assert(iterations > 0u);
59 size_t decimal{bytes};
60 decimal -= integer << (iterations * 10u); // Substract bytes represented by integer, e.g. -5GiB
61 decimal >>= (iterations - 1u) * 10u; // Shift to next smallest unit, e.g. 800MiB
62 decimal = decimal * 1000u / 1024u; // Account for using decimal system, i.e. 800MiB != 0.8GiB
63 size_t const diff{decimal - (decimal / 100u) * 100u}; // We want to round up to 1 decimal position
64 uint32_t const round_up{diff >= 50u};
65 decimal += round_up * 100u - diff;
66 decimal /= 100u;
67 return decimal;
68 };
69
70 auto formatted_string = [&]()
71 {
72 static constexpr int8_t int_to_char_offset{'0'}; // int 0 as char: char{0 + 48} = '0'
73 size_t const decimal = iterations ? first_decimal_position() : 0u;
74 assert(decimal <= 10u);
75
76 if (!iterations) // No decimals for Bytes
77 return std::to_string(integer);
78 else if (decimal < 10u) // No need to round integer part
79 return std::to_string(integer) + '.' + static_cast<char>(decimal + int_to_char_offset);
80 else // Round integer part, e.g., 5.99 MiB should report 6.0 MiB
81 {
82 ++integer;
83 // Check whether rounding results in a change of unit, e.g. 1023.99MiB to 1.0GiB
84 if (integer >> 10u)
85 {
86 ++iterations;
87 integer >>= 10u;
88 }
89 return std::to_string(integer) + ".0";
90 }
91 };
92
93 std::string const formatted{formatted_string()};
94 switch (iterations)
95 {
96 case 0:
97 return "[Bytes]: " + formatted;
98 case 1:
99 return "[KiB]: " + formatted;
100 case 2:
101 return "[MiB]: " + formatted;
102 case 3:
103 return "[GiB]: " + formatted;
104 case 4:
105 return "[TiB]: " + formatted;
106 case 5:
107 return "[PiB]: " + formatted;
108 default:
109 return "[EiB]: " + formatted;
110 }
111}
112
113} // namespace detail
114
115[[nodiscard]] inline std::string formatted_peak_ram()
116{
117 long const peak_ram_KiB = detail::peak_ram_in_KiB();
118 if (peak_ram_KiB == -1L)
119 return {": Not available"}; // GCOVR_EXCL_LINE
120#if __APPLE__
121 return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB));
122#else
123 return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB) << 10);
124#endif
125}
126
127} // namespace raptor
T to_string(T... args)