Skip to content

Commit e6d028d

Browse files
committed
change IOBuffer to use Memory internally
An Array is often still allocated on output, but this gives the compiler a chance to potentially elide that in certain cases. For measurement, it seems about 10% faster as a string builder: julia> @Btime repr("hello\nworld"^10); 1.096 μs (10 allocations: 640 bytes) # master 973.000 ns (9 allocations: 608 bytes) # PR 994.000 ns (8 allocations: 576 bytes) # also PR, after Revise-ing Base.wrap
1 parent 56e193e commit e6d028d

File tree

14 files changed

+230
-137
lines changed

14 files changed

+230
-137
lines changed

base/array.jl

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3067,7 +3067,8 @@ of [`unsafe_wrap`](@ref) utilizing `Memory` or `MemoryRef` instead of raw pointe
30673067
"""
30683068
function wrap end
30693069

3070-
@eval @propagate_inbounds function wrap(::Type{Array}, ref::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N}
3070+
# validity checking for _wrap calls, separate from allocation of Array so that it can be more likely to inline into the caller
3071+
function _wrap(ref::MemoryRef{T}, dims::NTuple{N, Int}) where {T, N}
30713072
mem = ref.mem
30723073
mem_len = length(mem) + 1 - memoryrefoffset(ref)
30733074
len = Core.checked_dims(dims...)
@@ -3076,18 +3077,35 @@ function wrap end
30763077
mem = ccall(:jl_genericmemory_slice, Memory{T}, (Any, Ptr{Cvoid}, Int), mem, ref.ptr_or_offset, len)
30773078
ref = MemoryRef(mem)
30783079
end
3079-
$(Expr(:new, :(Array{T, N}), :ref, :dims))
3080+
return ref
30803081
end
30813082

30823083
@noinline invalid_wrap_err(len, dims, proddims) = throw(DimensionMismatch(
30833084
"Attempted to wrap a MemoryRef of length $len with an Array of size dims=$dims, which is invalid because prod(dims) = $proddims > $len, so that the array would have more elements than the underlying memory can store."))
30843085

3085-
function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
3086-
wrap(Array, MemoryRef(m), dims)
3086+
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, dims::NTuple{N, Integer}) where {T, N}
3087+
dims = convert(Dims, dims)
3088+
ref = _wrap(m, dims)
3089+
$(Expr(:new, :(Array{T, N}), :ref, :dims))
3090+
end
3091+
3092+
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, dims::NTuple{N, Integer}) where {T, N}
3093+
dims = convert(Dims, dims)
3094+
ref = _wrap(MemoryRef(m), dims)
3095+
$(Expr(:new, :(Array{T, N}), :ref, :dims))
3096+
end
3097+
@eval @propagate_inbounds function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
3098+
dims = (Int(l),)
3099+
ref = _wrap(m, dims)
3100+
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
30873101
end
3088-
function wrap(::Type{Array}, m::MemoryRef{T}, l::Integer) where {T}
3089-
wrap(Array, m, (l,))
3102+
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
3103+
dims = (Int(l),)
3104+
ref = _wrap(MemoryRef(m), (l,))
3105+
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
30903106
end
3091-
function wrap(::Type{Array}, m::Memory{T}, l::Integer) where {T}
3092-
wrap(Array, MemoryRef(m), (l,))
3107+
@eval @propagate_inbounds function wrap(::Type{Array}, m::Memory{T}) where {T}
3108+
ref = MemoryRef(m)
3109+
dims = (length(m),)
3110+
$(Expr(:new, :(Array{T, 1}), :ref, :dims))
30933111
end

0 commit comments

Comments
 (0)