Raptor 3.0.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 <cstdint>
17#include <string>
18
19#if __has_include(<sys/resource.h>)
20# include <sys/resource.h>
21#endif
22
23namespace raptor
24{
25
26namespace detail
27{
28
29#if __has_include(<sys/resource.h>)
30// Returns -1 if not available. Actually returns bytes instead of KiB on macOS.
31inline long peak_ram_in_KiB()
32{
33 rusage usage;
34 return getrusage(RUSAGE_SELF, &usage) == 0 ? usage.ru_maxrss : -1L;
35}
36#else
37inline long peak_ram_in_KiB()
38{
39 return -1L;
40}
41#endif
42
43[[nodiscard]] inline std::string formatted_peak_ram(size_t const bytes)
44{
45 assert(bytes > 0);
46
47 size_t iterations{};
48 size_t integer{bytes};
49
50 while (integer >> 10u && iterations < 6u)
51 {
52 integer >>= 10u;
53 ++iterations;
54 }
55
56 // While this is a bit more involved, we can avoid using floating point numbers.
57 auto first_decimal_position = [&]()
58 {
59 assert(iterations > 0u);
60 size_t decimal{bytes};
61 decimal -= integer << (iterations * 10u); // Substract bytes represented by integer, e.g. -5GiB
62 decimal >>= (iterations - 1u) * 10u; // Shift to next smallest unit, e.g. 800MiB
63 decimal = decimal * 1000u / 1024u; // Account for using decimal system, i.e. 800MiB != 0.8GiB
64 size_t const diff{decimal - (decimal / 100u) * 100u}; // We want to round up to 1 decimal position
65 uint32_t const round_up{diff >= 50u};
66 decimal += round_up * 100u - diff;
67 decimal /= 100u;
68 return decimal;
69 };
70
71 auto formatted_string = [&]()
72 {
73 static constexpr int8_t int_to_char_offset{'0'}; // int 0 as char: char{0 + 48} = '0'
74 size_t const decimal = iterations ? first_decimal_position() : 0u;
75 assert(decimal <= 10u);
76
77 if (!iterations) // No decimals for Bytes
78 return std::to_string(integer);
79 else if (decimal < 10u) // No need to round integer part
80 return std::to_string(integer) + '.' + static_cast<char>(decimal + int_to_char_offset);
81 else // Round integer part, e.g., 5.99 MiB should report 6.0 MiB
82 {
83 ++integer;
84 // Check whether rounding results in a change of unit, e.g. 1023.99MiB to 1.0GiB
85 if (integer >> 10u)
86 {
87 ++iterations;
88 integer >>= 10u;
89 }
90 return std::to_string(integer) + ".0";
91 }
92 };
93
94 std::string const formatted{formatted_string()};
95 switch (iterations)
96 {
97 case 0:
98 return "[Bytes]: " + formatted;
99 case 1:
100 return "[KiB]: " + formatted;
101 case 2:
102 return "[MiB]: " + formatted;
103 case 3:
104 return "[GiB]: " + formatted;
105 case 4:
106 return "[TiB]: " + formatted;
107 case 5:
108 return "[PiB]: " + formatted;
109 default:
110 return "[EiB]: " + formatted;
111 }
112}
113
114} // namespace detail
115
116[[nodiscard]] inline std::string formatted_peak_ram()
117{
118 long const peak_ram_KiB = detail::peak_ram_in_KiB();
119 if (peak_ram_KiB == -1L)
120 return {": Not available"}; // GCOVR_EXCL_LINE
121#if __APPLE__
122 return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB));
123#else
124 return detail::formatted_peak_ram(static_cast<size_t>(peak_ram_KiB) << 10);
125#endif
126}
127
128} // namespace raptor
T to_string(T... args)