From 0e59c9eea225ed186671de1e5fd0c249b1495c1d Mon Sep 17 00:00:00 2001 From: Zentrik Date: Fri, 5 Apr 2024 19:12:48 +0100 Subject: [PATCH] Use StringMemory instead of StringVector where possible (#53962) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit On `1.11.0-alpha2` Old: ```julia @benchmark Base.dec($0x1, $0, $false) BenchmarkTools.Trial: 10000 samples with 994 evaluations. Range (min … max): 33.702 ns … 4.242 μs ┊ GC (min … max): 0.00% … 97.61% Time (median): 37.626 ns ┊ GC (median): 0.00% Time (mean ± σ): 45.787 ns ± 147.794 ns ┊ GC (mean ± σ): 14.53% ± 4.47% ▄▅▆▇█▇▇▅▃▃▂▂▂▁ ▁▂▁▁▁ ▁▁ ▁ ▂ ▄▇███████████████▇▇██████▇█▆▆▄▄▃▄▅▄▆▇████████▆▅▅▇▆▅▆▄▄▅▄▄▄▁▅ █ 33.7 ns Histogram: log(frequency) by time 67.5 ns < Memory estimate: 88 bytes, allocs estimate: 3. ``` New: ```julia BenchmarkTools.Trial: 10000 samples with 995 evaluations. Range (min … max): 27.538 ns … 3.397 μs ┊ GC (min … max): 0.00% … 97.86% Time (median): 30.151 ns ┊ GC (median): 0.00% Time (mean ± σ): 34.547 ns ± 105.101 ns ┊ GC (mean ± σ): 10.37% ± 3.39% ▁ █▆▃ ▁ ▂▂▃▃▅█████▆████▆▄▄▃▃▃▃▃▃▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▂▁▂▂▂▂▂▁▂▂▂▂▂▂▂▂▂▂▂▂▂ ▃ 27.5 ns Histogram: frequency by time 43.8 ns < Memory estimate: 56 bytes, allocs estimate: 2. ``` Fixes #53950, actually now even faster than `1.10.2`. It doesn't look like the length is ever changed and we don't return these `StringMemory`s so this change should be fine. --- base/gmp.jl | 2 +- base/intfuncs.jl | 12 ++++++------ base/strings/util.jl | 2 +- base/uuid.jl | 2 +- stdlib/FileWatching/src/pidfile.jl | 2 +- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/base/gmp.jl b/base/gmp.jl index beeec879ed487..a7caa8dfcdafd 100644 --- a/base/gmp.jl +++ b/base/gmp.jl @@ -754,7 +754,7 @@ function string(n::BigInt; base::Integer = 10, pad::Integer = 1) iszero(n) && pad < 1 && return "" nd1 = ndigits(n, base=base) nd = max(nd1, pad) - sv = Base.StringVector(nd + isneg(n)) + sv = Base.StringMemory(nd + isneg(n)) GC.@preserve sv MPZ.get_str!(pointer(sv) + nd - nd1, base, n) @inbounds for i = (1:nd-nd1) .+ isneg(n) sv[i] = '0' % UInt8 diff --git a/base/intfuncs.jl b/base/intfuncs.jl index f5185b0a9fd17..a89d45eb55fc1 100644 --- a/base/intfuncs.jl +++ b/base/intfuncs.jl @@ -742,7 +742,7 @@ ndigits(x::Integer; base::Integer=10, pad::Integer=1) = max(pad, ndigits0z(x, ba function bin(x::Unsigned, pad::Int, neg::Bool) m = top_set_bit(x) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) # for i in 0x0:UInt(n-1) # automatic vectorization produces redundant codes # @inbounds a[n - i] = 0x30 + (((x >> i) % UInt8)::UInt8 & 0x1) # end @@ -769,7 +769,7 @@ end function oct(x::Unsigned, pad::Int, neg::Bool) m = div(top_set_bit(x) + 2, 3) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) i = n while i > neg @inbounds a[i] = 0x30 + ((x % UInt8)::UInt8 & 0x7) @@ -844,7 +844,7 @@ end function dec(x::Unsigned, pad::Int, neg::Bool) n = neg + ndigits(x, pad=pad) - a = StringVector(n) + a = StringMemory(n) append_c_digits_fast(n, x, a, 1) neg && (@inbounds a[1] = 0x2d) # UInt8('-') String(a) @@ -853,7 +853,7 @@ end function hex(x::Unsigned, pad::Int, neg::Bool) m = 2 * sizeof(x) - (leading_zeros(x) >> 2) n = neg + max(pad, m) - a = StringVector(n) + a = StringMemory(n) i = n while i >= 2 b = (x % UInt8)::UInt8 @@ -880,7 +880,7 @@ function _base(base::Integer, x::Integer, pad::Int, neg::Bool) b = (base % Int)::Int digits = abs(b) <= 36 ? base36digits : base62digits n = neg + ndigits(x, base=b, pad=pad) - a = StringVector(n) + a = StringMemory(n) i = n @inbounds while i > neg if b > 0 @@ -956,7 +956,7 @@ julia> bitstring(2.2) function bitstring(x::T) where {T} isprimitivetype(T) || throw(ArgumentError("$T not a primitive type")) sz = sizeof(T) * 8 - str = StringVector(sz) + str = StringMemory(sz) i = sz @inbounds while i >= 4 b = UInt32(sizeof(T) == 1 ? bitcast(UInt8, x) : trunc_int(UInt8, x)) diff --git a/base/strings/util.jl b/base/strings/util.jl index 219b329d7924d..4b701001a8676 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -1061,7 +1061,7 @@ function bytes2hex end function bytes2hex(itr) eltype(itr) === UInt8 || throw(ArgumentError("eltype of iterator not UInt8")) - b = Base.StringVector(2*length(itr)) + b = Base.StringMemory(2*length(itr)) @inbounds for (i, x) in enumerate(itr) b[2i - 1] = hex_chars[1 + x >> 4] b[2i ] = hex_chars[1 + x & 0xf] diff --git a/base/uuid.jl b/base/uuid.jl index 1ed0b81b3f178..9b2da3c6409db 100644 --- a/base/uuid.jl +++ b/base/uuid.jl @@ -90,7 +90,7 @@ let groupings = [36:-1:25; 23:-1:20; 18:-1:15; 13:-1:10; 8:-1:1] global string function string(u::UUID) u = u.value - a = Base.StringVector(36) + a = Base.StringMemory(36) for i in groupings @inbounds a[i] = hex_chars[1 + u & 0xf] u >>= 4 diff --git a/stdlib/FileWatching/src/pidfile.jl b/stdlib/FileWatching/src/pidfile.jl index 0ee86e70f8465..4c821a3d897e4 100644 --- a/stdlib/FileWatching/src/pidfile.jl +++ b/stdlib/FileWatching/src/pidfile.jl @@ -280,7 +280,7 @@ function open_exclusive(path::String; end function _rand_filename(len::Int=4) # modified from Base.Libc - slug = Base.StringVector(len) + slug = Base.StringMemory(len) chars = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" for i = 1:len slug[i] = chars[(Libc.rand() % length(chars)) + 1]