Skip to content

Commit 98d1300

Browse files
authored
Add Mmap.madvise! (#37369)
1 parent 2fe2b43 commit 98d1300

File tree

3 files changed

+80
-2
lines changed

3 files changed

+80
-2
lines changed

NEWS.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,6 +191,10 @@ Standard library changes
191191
* Change `uuid1` and `uuid4` to use `Random.RandomDevice()` as default random number generator ([#35872]).
192192
* Added `parse(::Type{UUID}, ::AbstractString)` method
193193

194+
#### Mmap
195+
* On Unix systems, the `Mmap.madvise!` function (along with OS-specific `Mmap.MADV_*`
196+
constants) has been added to give advice on handling of memory-mapped arrays. ([#37369])
197+
194198
Deprecated or removed
195199
---------------------
196200

stdlib/Mmap/src/Mmap.jl

Lines changed: 62 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,10 @@ const MS_SYNC = 4
335335
Forces synchronization between the in-memory version of a memory-mapped `Array` or
336336
[`BitArray`](@ref) and the on-disk version.
337337
"""
338-
function sync!(m::Array{T}, flags::Integer=MS_SYNC) where T
338+
function sync!(m::Array, flags::Integer=MS_SYNC)
339339
offset = rem(UInt(pointer(m)), PAGESIZE)
340340
ptr = pointer(m) - offset
341-
mmaplen = length(m) * sizeof(T) + offset
341+
mmaplen = sizeof(m) + offset
342342
GC.@preserve m @static if Sys.isunix()
343343
systemerror("msync",
344344
ccall(:msync, Cint, (Ptr{Cvoid}, Csize_t, Cint), ptr, mmaplen, flags) != 0)
@@ -349,4 +349,64 @@ function sync!(m::Array{T}, flags::Integer=MS_SYNC) where T
349349
end
350350
sync!(B::BitArray, flags::Integer=MS_SYNC) = sync!(B.chunks, flags)
351351

352+
@static if Sys.isunix()
353+
const MADV_NORMAL = 0
354+
const MADV_RANDOM = 1
355+
const MADV_SEQUENTIAL = 2
356+
const MADV_WILLNEED = 3
357+
const MADV_DONTNEED = 4
358+
if Sys.islinux()
359+
const MADV_FREE = 8
360+
const MADV_REMOVE = 9
361+
const MADV_DONTFORK = 10
362+
const MADV_DOFORK = 11
363+
const MADV_MERGEABLE = 12
364+
const MADV_UNMERGEABLE = 13
365+
const MADV_HUGEPAGE = 14
366+
const MADV_NOHUGEPAGE = 15
367+
const MADV_DONTDUMP = 16
368+
const MADV_DODUMP = 17
369+
const MADV_WIPEONFORK = 18
370+
const MADV_KEEPONFORK = 19
371+
const MADV_COLD = 20
372+
const MADV_PAGEOUT = 21
373+
const MADV_HWPOISON = 100
374+
const MADV_SOFT_OFFLINE = 101
375+
elseif Sys.isapple()
376+
const MADV_FREE = 5
377+
elseif Sys.isfreebsd() || Sys.isdragonfly()
378+
const MADV_FREE = 5
379+
const MADV_NOSYNC = 6
380+
const MADV_AUTOSYNC = 7
381+
const MADV_NOCORE = 8
382+
const MADV_CORE = 9
383+
if Sys.isfreebsd()
384+
const MADV_PROTECT = 10
385+
else
386+
const MADV_INVAL = 10
387+
const MADV_SETMAP = 11
388+
end
389+
elseif Sys.isopenbsd() || Sys.isnetbsd()
390+
const MADV_SPACEAVAIL = 5
391+
const MADV_FREE = 6
392+
end
393+
394+
"""
395+
Mmap.madvise!(array, flag::Integer = Mmap.MADV_NORMAL)
396+
397+
Advises the kernel on the intended usage of the memory-mapped `array`, with the intent
398+
`flag` being one of the available `MADV_*` constants.
399+
"""
400+
function madvise!(m::Array, flag::Integer=MADV_NORMAL)
401+
offset = rem(UInt(pointer(m)), PAGESIZE)
402+
ptr = pointer(m) - offset
403+
mmaplen = sizeof(m) + offset
404+
GC.@preserve m begin
405+
systemerror("madvise",
406+
ccall(:madvise, Cint, (Ptr{Cvoid}, Csize_t, Cint), ptr, mmaplen, flag) != 0)
407+
end
408+
end
409+
madvise!(B::BitArray, flag::Integer=MADV_NORMAL) = madvise!(B.chunks, flag)
410+
end # Sys.isunix()
411+
352412
end # module

stdlib/Mmap/test/runtests.jl

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,20 @@ n = similar(m, 12)
307307
@test size(n) == (12,)
308308
finalize(m); m = nothing; GC.gc()
309309

310+
if Sys.isunix()
311+
file = tempname()
312+
write(file, rand(Float64, 20))
313+
A = Mmap.mmap(file, Vector{Float64}, 20)
314+
@test Mmap.madvise!(A, Mmap.MADV_WILLNEED) === nothing # checking for no error
315+
finalize(A); A = nothing; GC.gc()
316+
317+
write(file, BitArray(rand(Bool, 20)))
318+
b = Mmap.mmap(file, BitArray, 20)
319+
@test Mmap.madvise!(b, Mmap.MADV_WILLNEED) === nothing
320+
finalize(b); b = nothing; GC.gc()
321+
rm(file)
322+
end
323+
310324
# test #14885
311325
file = tempname()
312326
touch(file)

0 commit comments

Comments
 (0)