Skip to content

Commit

Permalink
cut RNTuple allocation by half
Browse files Browse the repository at this point in the history
  • Loading branch information
Moelf committed Oct 10, 2023
1 parent dea08ef commit 6bc6d90
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
14 changes: 11 additions & 3 deletions src/RNTuple/bootstrap.jl
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,22 @@ function ROOT_3a3a_Experimental_3a3a_RNTuple(io, tkey::TKey, refs)
return rnt
end

function decompress_bytes(compbytes, NTarget)
function decompress_bytes(compbytes, NTarget::Integer)
uncomp_data = Vector{UInt8}(undef, NTarget)
decompress_bytes!(uncomp_data, compbytes, NTarget)
return uncomp_data

Check warning on line 48 in src/RNTuple/bootstrap.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/bootstrap.jl#L45-L48

Added lines #L45 - L48 were not covered by tests
end

function decompress_bytes!(uncomp_data, compbytes, NTarget::Integer)
resize!(uncomp_data, NTarget)

Check warning on line 52 in src/RNTuple/bootstrap.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/bootstrap.jl#L51-L52

Added lines #L51 - L52 were not covered by tests
# not compressed
length(compbytes) >= NTarget && return compbytes
if length(compbytes) >= NTarget
copyto!(uncomp_data, compbytes)

Check warning on line 55 in src/RNTuple/bootstrap.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/bootstrap.jl#L54-L55

Added lines #L54 - L55 were not covered by tests
end

# compressed
io = IOBuffer(compbytes)
fufilled = 0
uncomp_data = Vector{UInt8}(undef, NTarget)
while fufilled < NTarget # careful with 0/1-based index when thinking about offsets
compression_header = unpack(io, CompressionHeader)
cname, _, compbytes, uncompbytes = unpack(compression_header)
Expand Down
39 changes: 25 additions & 14 deletions src/RNTuple/footer.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,14 @@ end
meta_data_links::Vector{EnvLink}
end

function _read_locator(io, locator, uncomp_size)
function _read_locator(io, locator, uncomp_size::Integer)

Check warning on line 57 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L57

Added line #L57 was not covered by tests
decompress_bytes(read_seek_nb(io, locator.offset, locator.num_bytes), uncomp_size)
end

function _read_locator!(dst::Vector{UInt8}, io, locator, uncomp_size::Integer)
decompress_bytes!(dst, read_seek_nb(io, locator.offset, locator.num_bytes), uncomp_size)

Check warning on line 62 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L61-L62

Added lines #L61 - L62 were not covered by tests
end

@memoize LRU(maxsize = 200) function _read_envlink(io, link::EnvLink)
_read_locator(io, link.locator, link.uncomp_size)
end
Expand All @@ -68,8 +72,7 @@ end
end

# https://discourse.julialang.org/t/simd-gather-result-in-slow-down/95161/2
function split2_reinterpret(src::Vector{UInt8})
dst = similar(src)
function split2_reinterpret!(dst, src::Vector{UInt8})

Check warning on line 75 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L75

Added line #L75 was not covered by tests
count = length(src) ÷ 2
res = reinterpret(UInt16, dst)
@inbounds for i = 1:count
Expand All @@ -78,8 +81,7 @@ function split2_reinterpret(src::Vector{UInt8})
end
return dst
end
function split4_reinterpret(src::Vector{UInt8})
dst = similar(src)
function split4_reinterpret!(dst, src::Vector{UInt8})

Check warning on line 84 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L84

Added line #L84 was not covered by tests
count = length(src) ÷ 4
res = reinterpret(UInt32, dst)
@inbounds for i = 1:count
Expand All @@ -88,8 +90,7 @@ function split4_reinterpret(src::Vector{UInt8})
end
return dst
end
function split8_reinterpret(src::Vector{UInt8})
dst = similar(src)
function split8_reinterpret!(dst, src::Vector{UInt8})

Check warning on line 93 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L93

Added line #L93 was not covered by tests
count = length(src) ÷ 8
res = reinterpret(UInt64, dst)
@inbounds for i = 1:count
Expand All @@ -111,24 +112,34 @@ column since `pagedesc` only contains `num_elements` information.
"""
function read_pagedesc(io, pagedescs::Vector{PageDescription}, nbits::Integer; split=false)
res = map(pagedescs) do pagedesc
output_L = sum((p.num_elements for p in pagedescs))*nbits÷8
res = Vector{UInt8}(undef, output_L)

Check warning on line 116 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L115-L116

Added lines #L115 - L116 were not covered by tests

# a page max size is 64KB
tmp = Vector{UInt8}(undef, 65536)

Check warning on line 119 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L119

Added line #L119 was not covered by tests

tip = 1
for i in eachindex(pagedescs)
pagedesc = pagedescs[i]

Check warning on line 123 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L121-L123

Added lines #L121 - L123 were not covered by tests
# when nbits == 1 for bits, need RoundUp
uncomp_size = div(pagedesc.num_elements * nbits, 8, RoundUp)
tmp = _read_locator(io, pagedesc.locator, uncomp_size)
dst = @view res[tip:tip+uncomp_size-1]
_read_locator!(tmp, io, pagedesc.locator, uncomp_size)

Check warning on line 127 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L126-L127

Added lines #L126 - L127 were not covered by tests
if !split
tmp
dst .= tmp

Check warning on line 129 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L129

Added line #L129 was not covered by tests
elseif split
if nbits == 16
split2_reinterpret(tmp)
split2_reinterpret!(dst, tmp)

Check warning on line 132 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L132

Added line #L132 was not covered by tests
elseif nbits == 32
split4_reinterpret(tmp)
split4_reinterpret!(dst, tmp)

Check warning on line 134 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L134

Added line #L134 was not covered by tests
elseif nbits == 64
split8_reinterpret(tmp)
split8_reinterpret!(dst, tmp)

Check warning on line 136 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L136

Added line #L136 was not covered by tests
end
end
tip += uncomp_size

Check warning on line 139 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L139

Added line #L139 was not covered by tests
end

return reduce(vcat, res)::Vector{UInt8}
return res::Vector{UInt8}

Check warning on line 142 in src/RNTuple/footer.jl

View check run for this annotation

Codecov / codecov/patch

src/RNTuple/footer.jl#L142

Added line #L142 was not covered by tests
end

struct PageLink end
Expand Down

0 comments on commit 6bc6d90

Please sign in to comment.