Skip to content

Instantly share code, notes, and snippets.

@li1
Last active April 22, 2020 14:03
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save li1/95371ff5032ee4c55297551008919d4d to your computer and use it in GitHub Desktop.
Save li1/95371ff5032ee4c55297551008919d4d to your computer and use it in GitHub Desktop.
Comparison of hand-written allocation vs. Julia GC for buffer management
module pagingtests
using Blobs
import Blobs
free_mem() = Sys.free_memory() / 2^20
const MB = 2^20
const MEMTARGET = 2048MB
const STATIC_SLOTS = convert(Int, MEMTARGET/MB/8)
const STATIC_PAGESIZE = convert(Int, (STATIC_SLOTS / 8) * MB)
mutable struct Page
mem::Int64
content::Vector{Int64}
end
function blobs()
# 2 allocations
pages = Tuple{Int64, Blob}[]
sizehint!(pages, 64)
memory_used = 0
for i in 1:100
# Uncomment to switch between var mem and static mem
# mem = rand(1MB:convert(Int, MEMTARGET/8))
mem = STATIC_PAGESIZE
memory_used += mem * 8
# Eviction
while memory_used >= MEMTARGET
@assert !isempty(pages)
(inmem, page) = pop!(pages)
Blobs.free(page)
memory_used -= inmem
end
# 2 allocations
page = Blobs.malloc_and_init(BlobVector{Int64}, mem)
for j in 1:mem
page[j][] = j
end
push!(pages, (mem*8, page))
end
end
function dynamic()
# 2 allocations
pages = Page[]
sizehint!(pages, 64)
memory_used = 0
for i in 1:100
# Uncomment to switch between var mem and static mem
# mem = rand(1MB:convert(Int, MEMTARGET/8))
mem = STATIC_PAGESIZE
memory_used += mem * 8
# Eviction
while memory_used >= MEMTARGET
@assert !isempty(pages)
page = pop!(pages)
memory_used -= page.mem
end
# 2 allocations
page = Page(mem * 8, fill(i % 10, mem))
# finalizer(page) do p @async println("F", i) end
# 1 allocation
push!(pages, page)
end
end
function static()
pool = Libc.malloc(MEMTARGET)
pool = convert(Ptr{Array}, pool)
# 3 allocations
free_offsets = collect(1:STATIC_SLOTS-1)
full_offsets = Int[]
sizehint!(full_offsets, STATIC_SLOTS)
for i in 1:100
if isempty(free_offsets)
# evict
offset = pop!(full_offsets)
push!(free_offsets, offset)
end
offset = pop!(free_offsets)
# 2 allocations
unsafe_store!(pool+offset, fill(i % 10, STATIC_PAGESIZE))
push!(full_offsets, offset)
end
Libc.free(pool)
end
function bench()
GC.gc()
@info "blob"
@time blobs()
@info "free mem", free_mem()
GC.gc()
@info "after GC", free_mem()
@info "----------"
@time blobs()
@info "free mem", free_mem()
GC.gc()
@info "after GC", free_mem()
@info "=========="
@info "dynamic"
@time dynamic()
@info "free mem", free_mem()
GC.gc()
@info "after GC", free_mem()
@info "----------"
@time dynamic()
@info "free mem", free_mem()
GC.gc()
@info "after GC", free_mem()
@info "=========="
@info "static"
@time static()
@info "free", free_mem()
GC.gc()
@info "after GC", free_mem()
@info "----------"
@time static()
@info "free", free_mem()
GC.gc()
@info "after GC", free_mem()
end
export dynamic, free_mem, static, bench, blobs
end # module
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment