Skip to content

Commit a0b3014

Browse files
feat: implement advise wrapper and update some tools scripts (#33)
1 parent 40d16fe commit a0b3014

11 files changed

Lines changed: 539 additions & 332 deletions

File tree

include/mio/page.hpp

Lines changed: 92 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,17 @@
4343
#ifndef MIO_PAGE_HPP
4444
#define MIO_PAGE_HPP
4545

46+
#include <errno.h>
47+
#include <stddef.h>
48+
#include <system_error> // std::error_code
4649
#ifdef _WIN32
50+
// !! NOTE DO NOT Reverse the include order of these two windows api files
51+
// build errors could trigger !!
4752
#include <windows.h>
53+
#include <memoryapi.h> // PrefetchVirtualMemory
4854
#else
4955
#include <unistd.h>
56+
#include <sys/mman.h> // madvise
5057
#endif
5158

5259
namespace mio {
@@ -61,12 +68,96 @@ enum class access_mode
6168
write
6269
};
6370

71+
/**
72+
* This is used by madvice to determine Memory access pattern hints
73+
*/
74+
enum class advice
75+
{
76+
will_need,
77+
dont_need,
78+
sequential,
79+
random
80+
};
81+
82+
/**
83+
* This is a cross platform Wrapper around linux madvice function mainly for
84+
* windows users, which under the hood uses PrefetchVirtualMemory() from WinAPI
85+
* @note Windows does not have a direct equivalent to all madvise() behaviors
86+
* only advice::will_need is implemented, for other arguments we will
87+
* simply throw an invalid argument error code, fo unix platforms (Linux, MacOS)
88+
* all option are mapped nativlly to unix madvice internal flags
89+
* given this limitation, the performance will be heavily impacted by Windows memory
90+
* manager
91+
*/
92+
std::error_code advise(void* addr, std::size_t len, advice hint);
93+
6494
/**
6595
* Determines the operating system's page allocation granularity.
6696
* On the first call to this function, it invokes the operating system specific syscall
6797
* to determine the page size, caches the value, and returns it. Any subsequent call to
6898
* this function serves the cached value, so no further syscalls are made.
6999
*/
100+
inline size_t page_size();
101+
102+
/**
103+
* Alligns `offset` to the operating's system page size such that it subtracts the
104+
* difference until the nearest page boundary before `offset`, or does nothing if
105+
* `offset` is already page aligned.
106+
*/
107+
inline size_t make_offset_page_aligned(size_t offset) noexcept;
108+
109+
// --------------------------------------------------------------------------
110+
111+
std::error_code advise(void* addr, std::size_t len, advice hint) {
112+
if(addr == nullptr) {
113+
return std::make_error_code(std::errc::invalid_argument);
114+
}
115+
116+
if(len == 0) {
117+
return {};
118+
}
119+
120+
#ifdef _WIN32
121+
122+
switch(hint) {
123+
case advice::will_need: {
124+
WIN32_MEMORY_RANGE_ENTRY range{};
125+
range.VirtualAddress = addr;
126+
range.NumberOfBytes = len;
127+
128+
if(!PrefetchVirtualMemory(GetCurrentProcess(), 1, &range, 0)) {
129+
return std::error_code(static_cast<int>(GetLastError()), std::system_category());
130+
}
131+
132+
return {};
133+
}
134+
case advice::dont_need:
135+
case advice::sequential:
136+
case advice::random: return {};
137+
}
138+
return std::make_error_code(std::errc::invalid_argument);
139+
140+
#else // UNIX
141+
142+
int madvise_flag;
143+
144+
switch(hint) {
145+
case advice::will_need: madvise_flag = MADV_WILLNEED; break;
146+
case advice::dont_need: madvise_flag = MADV_DONTNEED; break;
147+
case advice::sequential: madvise_flag = MADV_SEQUENTIAL; break;
148+
case advice::random: madvise_flag = MADV_RANDOM; break;
149+
default: return std::make_error_code(std::errc::invalid_argument);
150+
}
151+
152+
if(madvise(addr, len, madvise_flag) != 0) {
153+
return std::error_code(errno, std::generic_category());
154+
}
155+
156+
return {};
157+
#endif // _WIN32
158+
}
159+
160+
// --------------------------------------------------------------------------
70161
inline size_t page_size() {
71162
static const size_t page_size = [] {
72163
#ifdef _WIN32
@@ -80,11 +171,7 @@ inline size_t page_size() {
80171
return page_size;
81172
}
82173

83-
/**
84-
* Alligns `offset` to the operating's system page size such that it subtracts the
85-
* difference until the nearest page boundary before `offset`, or does nothing if
86-
* `offset` is already page aligned.
87-
*/
174+
// --------------------------------------------------------------------------
88175
inline size_t make_offset_page_aligned(size_t offset) noexcept {
89176
const size_t page_size_ = page_size();
90177
// Use integer division to round down to the nearest page alignment.

mio.pc.in

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,45 @@
1+
/* Copyright 2017 https://github.com/mandreyel
2+
*
3+
* Permission is hereby granted, free of charge, to any person obtaining a copy of this
4+
* software and associated documentation files (the "Software"), to deal in the Software
5+
* without restriction, including without limitation the rights to use, copy, modify,
6+
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
7+
* permit persons to whom the Software is furnished to do so, subject to the following
8+
* conditions:
9+
*
10+
* The above copyright notice and this permission notice shall be included in all copies
11+
* or substantial portions of the Software.
12+
*
13+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
14+
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
15+
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
16+
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
17+
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
18+
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19+
*/
20+
21+
/*
22+
* Copyright 2026 Maxtek Consulting
23+
*
24+
* Permission is hereby granted, free of charge, to any person obtaining a copy
25+
* of this software and associated documentation files (the "Software"), to deal
26+
* in the Software without restriction, including without limitation the rights
27+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
28+
* copies of the Software, and to permit persons to whom the Software is
29+
* furnished to do so, subject to the following conditions:
30+
*
31+
* The above copyright notice and this permission notice shall be included in all
32+
* copies or substantial portions of the Software.
33+
*
34+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
35+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
36+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
37+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
38+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
39+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
40+
* SOFTWARE.
41+
*/
42+
143
prefix=@CMAKE_INSTALL_PREFIX@
244
includedir=@CMAKE_INSTALL_PREFIX@/@CMAKE_INSTALL_INCLUDEDIR@/@PROJECT_NAME@
345

0 commit comments

Comments
 (0)