@@ -8,6 +8,12 @@ use std::{fmt, result};
8
8
9
9
use common:: StableDeref ;
10
10
use fs4:: FileExt ;
11
+
12
+ #[ cfg( feature = "madvise" ) ]
13
+ use crate :: AccessPattern ;
14
+ #[ cfg( not( feature = "madvise" ) ) ]
15
+ type AccessPattern = ( ) ;
16
+
11
17
use memmap2:: Mmap ;
12
18
use serde:: { Deserialize , Serialize } ;
13
19
use tempfile:: TempDir ;
@@ -32,7 +38,11 @@ pub(crate) fn make_io_err(msg: String) -> io::Error {
32
38
33
39
/// Returns `None` iff the file exists, can be read, but is empty (and hence
34
40
/// cannot be mmapped)
35
- fn open_mmap ( full_path : & Path ) -> result:: Result < Option < Mmap > , OpenReadError > {
41
+ #[ allow( unused_variables) ]
42
+ fn open_mmap (
43
+ full_path : & Path ,
44
+ access_pattern_opt : Option < AccessPattern > ,
45
+ ) -> result:: Result < Option < Mmap > , OpenReadError > {
36
46
let file = File :: open ( full_path) . map_err ( |io_err| {
37
47
if io_err. kind ( ) == io:: ErrorKind :: NotFound {
38
48
OpenReadError :: FileDoesNotExist ( full_path. to_path_buf ( ) )
@@ -50,11 +60,20 @@ fn open_mmap(full_path: &Path) -> result::Result<Option<Mmap>, OpenReadError> {
50
60
// instead.
51
61
return Ok ( None ) ;
52
62
}
53
- unsafe {
63
+ let mmap_opt : Option < memmap2 :: Mmap > = unsafe {
54
64
memmap2:: Mmap :: map ( & file)
55
65
. map ( Some )
56
66
. map_err ( |io_err| OpenReadError :: wrap_io_error ( io_err, full_path. to_path_buf ( ) ) )
67
+ } ?;
68
+ #[ cfg( feature = "madvise" ) ]
69
+ match ( & mmap_opt, access_pattern_opt) {
70
+ ( Some ( mmap) , Some ( access_pattern) ) => {
71
+ use madvise:: AdviseMemory ;
72
+ let _ = mmap. advise_memory_access ( access_pattern) ;
73
+ }
74
+ _ => { }
57
75
}
76
+ Ok ( mmap_opt)
58
77
}
59
78
60
79
#[ derive( Default , Clone , Debug , Serialize , Deserialize ) ]
@@ -72,13 +91,21 @@ pub struct CacheInfo {
72
91
pub mmapped : Vec < PathBuf > ,
73
92
}
74
93
75
- #[ derive( Default ) ]
76
94
struct MmapCache {
77
95
counters : CacheCounters ,
78
96
cache : HashMap < PathBuf , WeakArcBytes > ,
97
+ access_pattern_opt : Option < AccessPattern > ,
79
98
}
80
99
81
100
impl MmapCache {
101
+ fn new ( access_pattern_opt : Option < AccessPattern > ) -> MmapCache {
102
+ MmapCache {
103
+ counters : CacheCounters :: default ( ) ,
104
+ cache : HashMap :: default ( ) ,
105
+ access_pattern_opt,
106
+ }
107
+ }
108
+
82
109
fn get_info ( & self ) -> CacheInfo {
83
110
let paths: Vec < PathBuf > = self . cache . keys ( ) . cloned ( ) . collect ( ) ;
84
111
CacheInfo {
@@ -109,7 +136,7 @@ impl MmapCache {
109
136
}
110
137
self . cache . remove ( full_path) ;
111
138
self . counters . miss += 1 ;
112
- let mmap_opt = open_mmap ( full_path) ?;
139
+ let mmap_opt = open_mmap ( full_path, self . access_pattern_opt ) ?;
113
140
Ok ( mmap_opt. map ( |mmap| {
114
141
let mmap_arc: ArcBytes = Arc :: new ( mmap) ;
115
142
let mmap_weak = Arc :: downgrade ( & mmap_arc) ;
@@ -144,9 +171,13 @@ struct MmapDirectoryInner {
144
171
}
145
172
146
173
impl MmapDirectoryInner {
147
- fn new ( root_path : PathBuf , temp_directory : Option < TempDir > ) -> MmapDirectoryInner {
174
+ fn new (
175
+ root_path : PathBuf ,
176
+ temp_directory : Option < TempDir > ,
177
+ access_pattern_opt : Option < AccessPattern > ,
178
+ ) -> MmapDirectoryInner {
148
179
MmapDirectoryInner {
149
- mmap_cache : Default :: default ( ) ,
180
+ mmap_cache : RwLock :: new ( MmapCache :: new ( access_pattern_opt ) ) ,
150
181
_temp_directory : temp_directory,
151
182
watcher : FileWatcher :: new ( & root_path. join ( * META_FILEPATH ) ) ,
152
183
root_path,
@@ -165,8 +196,12 @@ impl fmt::Debug for MmapDirectory {
165
196
}
166
197
167
198
impl MmapDirectory {
168
- fn new ( root_path : PathBuf , temp_directory : Option < TempDir > ) -> MmapDirectory {
169
- let inner = MmapDirectoryInner :: new ( root_path, temp_directory) ;
199
+ fn new (
200
+ root_path : PathBuf ,
201
+ temp_directory : Option < TempDir > ,
202
+ access_pattern_opt : Option < AccessPattern > ,
203
+ ) -> MmapDirectory {
204
+ let inner = MmapDirectoryInner :: new ( root_path, temp_directory, access_pattern_opt) ;
170
205
MmapDirectory {
171
206
inner : Arc :: new ( inner) ,
172
207
}
@@ -182,6 +217,7 @@ impl MmapDirectory {
182
217
Ok ( MmapDirectory :: new (
183
218
tempdir. path ( ) . to_path_buf ( ) ,
184
219
Some ( tempdir) ,
220
+ None ,
185
221
) )
186
222
}
187
223
@@ -190,6 +226,22 @@ impl MmapDirectory {
190
226
/// Returns an error if the `directory_path` does not
191
227
/// exist or if it is not a directory.
192
228
pub fn open < P : AsRef < Path > > ( directory_path : P ) -> Result < MmapDirectory , OpenDirectoryError > {
229
+ Self :: open_with_access_pattern_impl ( directory_path. as_ref ( ) , None )
230
+ }
231
+
232
+ /// Opens a MmapDirectory in a directory, with a given access pattern.
233
+ #[ cfg( feature = "madvise" ) ]
234
+ pub fn open_with_access_pattern < P : AsRef < Path > > (
235
+ directory_path : & Path ,
236
+ access_pattern : AccessPattern ,
237
+ ) -> Result < MmapDirectory , OpenDirectoryError > {
238
+ Self :: open_with_access_pattern_impl ( directory_path. as_ref ( ) , Some ( access_pattern) )
239
+ }
240
+
241
+ fn open_with_access_pattern_impl (
242
+ directory_path : & Path ,
243
+ access_pattern_opt : Option < AccessPattern > ,
244
+ ) -> Result < MmapDirectory , OpenDirectoryError > {
193
245
let directory_path: & Path = directory_path. as_ref ( ) ;
194
246
if !directory_path. exists ( ) {
195
247
return Err ( OpenDirectoryError :: DoesNotExist ( PathBuf :: from (
@@ -217,7 +269,7 @@ impl MmapDirectory {
217
269
directory_path,
218
270
) ) ) ;
219
271
}
220
- Ok ( MmapDirectory :: new ( canonical_path, None ) )
272
+ Ok ( MmapDirectory :: new ( canonical_path, None , access_pattern_opt ) )
221
273
}
222
274
223
275
/// Joins a relative_path to the directory `root_path`
0 commit comments