Skip to content

Commit

Permalink
improve performance for materializing a string from a vector of Char (J…
Browse files Browse the repository at this point in the history
…uliaLang#29551)

* improve performance for materializing a string from a vector of Char

* fixup names from review
  • Loading branch information
KristofferC authored Oct 12, 2018
1 parent 48bc266 commit e11b0b0
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 11 deletions.
13 changes: 13 additions & 0 deletions base/strings/io.jl
Original file line number Diff line number Diff line change
Expand Up @@ -576,6 +576,19 @@ function unindent(str::AbstractString, indent::Int; tabwidth=8)
String(take!(buf))
end

function String(a::AbstractVector{Char})
n = 0
for v in a
n += ncodeunits(v)
end
out = _string_n(n)
offs = 1
for v in a
offs += __unsafe_string!(out, v, offs)
end
return out
end

function String(chars::AbstractVector{<:AbstractChar})
sprint(sizehint=length(chars)) do io
for c in chars
Expand Down
34 changes: 23 additions & 11 deletions base/strings/substring.jl
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,28 @@ end
string(a::String) = String(a)
string(a::SubString{String}) = String(a)

@inline function __unsafe_string!(out, c::Char, offs::Integer)
x = bswap(reinterpret(UInt32, c))
n = ncodeunits(c)
unsafe_store!(pointer(out, offs), x % UInt8)
n == 1 && return n
x >>= 8
unsafe_store!(pointer(out, offs+1), x % UInt8)
n == 2 && return n
x >>= 8
unsafe_store!(pointer(out, offs+2), x % UInt8)
n == 3 && return n
x >>= 8
unsafe_store!(pointer(out, offs+3), x % UInt8)
return n
end

@inline function __unsafe_string!(out, s::Union{String, SubString{String}}, offs::Integer)
n = sizeof(s)
unsafe_copyto!(pointer(out, offs), pointer(s), n)
return n
end

function string(a::Union{Char, String, SubString{String}}...)
n = 0
for v in a
Expand All @@ -157,17 +179,7 @@ function string(a::Union{Char, String, SubString{String}}...)
out = _string_n(n)
offs = 1
for v in a
if v isa Char
x = bswap(reinterpret(UInt32, v))
for j in 1:ncodeunits(v)
unsafe_store!(pointer(out, offs), x % UInt8)
offs += 1
x >>= 8
end
else
unsafe_copyto!(pointer(out,offs), pointer(v), sizeof(v))
offs += sizeof(v)
end
offs += __unsafe_string!(out, v, offs)
end
return out
end
Expand Down

0 comments on commit e11b0b0

Please sign in to comment.