I am trying to define a Vector type where it has a pointer to a compressed vector and a pointer to an uncompressed vector. To save RAM initially only the compressed vector is stored in memory. Upon accessing an element of the vector, the compressed vector gets decompressed and now the uncompressed pointer will point to it. To illustrate
using Revise
using Blosc
using CmpVectors # defined below
a = rand(Int, 100_000_000)
b = Blosc.compress(a)
c = CmpVector{Int}(b)
c[1]
c[2]
c[1] # invariably crashes 1.3 on Windows 10
The above crash Julia 1.3-rc1. I think it might be a bug with Julia but I may not be understanding Julia memory correctly. Is what I am doing OK? Sorry for the long code, but it’s as simple a MWE as I can show.
If I set a = rand(Int, 3)
then it works and won’t crash. So I think the code is doing thing correctly somewhat.
The full module definition is below
module CmpVectors
using Blosc
import Base: show, getindex, setindex!, eltype, size
export CmpVector
mutable struct CmpVector{T} <: AbstractVector{T}
ptr_compressed::Ptr{UInt8}
ptr_uncompressed::Ptr{T}
inited::Bool
end
CmpVector{T}(ptr_compress::Ptr{UInt8}) where T= CmpVector{T}(ptr_compress, pointer_from_objref(T[zero(T)]), false)
CmpVector{T}(ptr_compress::Vector{UInt8}) where T= CmpVector{T}(pointer_from_objref(ptr_compress), pointer_from_objref(T[zero(T)]), false)
Base.eltype(cv::CmpVector{T}) where T = eltype(cv.ptr_uncompressed)
Base.size(cv::CmpVector{T}) where T = begin
decomp(cv)
size(unsafe_pointer_to_objref(cv.ptr_uncompressed))
end
decomp(cv) = begin
if !cv.inited
println("decompressing")
cv.ptr_uncompressed = Blosc.decompress(
eltype(cv),
unsafe_pointer_to_objref(cv.ptr_compressed)
) |> pointer_from_objref
cv.ptr_compressed = pointer_from_objref(UInt8[0])
cv.inited = true
println("decompressing: done")
else
println("didn't do nothing")
end
end
Base.getindex(cv::CmpVector{T}, i...) where T = begin
decomp(cv)
getindex(unsafe_pointer_to_objref(cv.ptr_uncompressed), i...)
end
Base.setindex!(cv::CmpVector{T}, i...) where T = begin
decomp(cv)
setindex!(unsafe_pointer_to_objref(cv.ptr_uncompressed), i...)
end
Base.show(io::IO, A::MIME"text/plain", cv::CmpVector{T}) where T = begin
if cv.inited
show(io, A, unsafe_pointer_to_objref(cv.ptr_uncompressed))
else
print("data in compressed form; not shown until first used")
end
end
end # module