From 767ea34a1d5d39f1f618a8e154c328a886de5219 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Thu, 8 Feb 2018 13:17:19 +0900 Subject: [PATCH 1/8] add sizehint keyword argument to IOBuffer --- base/iobuffer.jl | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index 422092f9ccd18..cffc42abf56d0 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -40,6 +40,7 @@ It may take optional keyword arguments: - `read`, `write`, `append`: restricts operations to the buffer; see `open` for details. - `truncate`: truncates the buffer size to zero length. - `maxsize`: specifies a size beyond which the buffer may not be grown. +- `sizehint`: suggests a capacity of the buffer (`data` must implement `sizehint!(data, size)`). When `data` is not given, the buffer will be both readable and writable by default. @@ -84,10 +85,14 @@ function IOBuffer( write::Union{Bool,Nothing}=nothing, append::Union{Bool,Nothing}=nothing, truncate::Union{Bool,Nothing}=nothing, - maxsize::Integer=typemax(Int)) + maxsize::Integer=typemax(Int), + sizehint::Union{Integer,Nothing}=nothing) if maxsize < 0 throw(ArgumentError("negative maxsize: $(maxsize)")) end + if sizehint !== nothing + sizehint!(data, sizehint) + end flags = open_flags(read=read, write=write, append=append, truncate=truncate) buf = GenericIOBuffer(data, flags.read, flags.write, true, flags.append, Int(maxsize)) if flags.truncate @@ -101,8 +106,9 @@ function IOBuffer(; write::Union{Bool,Nothing}=true, append::Union{Bool,Nothing}=nothing, truncate::Union{Bool,Nothing}=true, - maxsize::Integer=typemax(Int)) - size = maxsize == typemax(Int) ? 32 : Int(maxsize) + maxsize::Integer=typemax(Int), + sizehint::Union{Integer,Nothing}=nothing) + size = maxsize != typemax(Int) ? Int(maxsize) : sizehint !== nothing ? Int(sizehint) : 32 flags = open_flags(read=read, write=write, append=append, truncate=truncate) buf = IOBuffer( StringVector(size), From 19d9b342eb02dd550c807f382b62e4bb122046bd Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Thu, 8 Feb 2018 17:02:02 +0900 Subject: [PATCH 2/8] use sizehint in Base --- base/strings/basic.jl | 4 ++-- base/strings/io.jl | 6 +++--- base/strings/util.jl | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index a747ac39e5b8e..7e23b39a812f9 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -512,7 +512,7 @@ isascii(s::AbstractString) = all(isascii, s) ## string map, filter, has ## function map(f, s::AbstractString) - out = IOBuffer(StringVector(sizeof(s)), read=true, write=true) + out = IOBuffer(sizehint=sizeof(s), read=true, write=true) truncate(out, 0) for c in s c′ = f(c) @@ -525,7 +525,7 @@ function map(f, s::AbstractString) end function filter(f, s::AbstractString) - out = IOBuffer(StringVector(sizeof(s)), read=true, write=true) + out = IOBuffer(sizehint=sizeof(s), read=true, write=true) truncate(out, 0) for c in s f(c) && write(out, c) diff --git a/base/strings/io.jl b/base/strings/io.jl index 97dbf4eed89e6..8c7bb64bf2aae 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -81,7 +81,7 @@ julia> sprint(showcompact, 66.66666) ``` """ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) - s = IOBuffer(StringVector(sizehint), read=true, write=true) + s = IOBuffer(sizehint=sizehint, read=true, write=true) # specialized version of truncate(s,0) s.size = 0 s.ptr = 1 @@ -100,7 +100,7 @@ tostr_sizehint(x::Float32) = 12 function print_to_string(xs...; env=nothing) # specialized for performance reasons - s = IOBuffer(StringVector(tostr_sizehint(xs[1])), read=true, write=true) + s = IOBuffer(sizehint=tostr_sizehint(xs[1]), read=true, write=true) # specialized version of truncate(s,0) s.size = 0 s.ptr = 1 @@ -436,7 +436,7 @@ Returns: function unindent(str::AbstractString, indent::Int; tabwidth=8) indent == 0 && return str # Note: this loses the type of the original string - buf = IOBuffer(StringVector(sizeof(str)), read=true, write=true) + buf = IOBuffer(sizehint=sizeof(str), read=true, write=true) truncate(buf,0) cutting = true col = 0 # current column (0 based) diff --git a/base/strings/util.jl b/base/strings/util.jl index 9fe05fe6edcf5..d9a8c7d6806f1 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -383,7 +383,7 @@ function replace(str::String, pat_repl::Pair; count::Integer=typemax(Int)) i = a = firstindex(str) r = coalesce(findnext(pattern,str,i), 0) j, k = first(r), last(r) - out = IOBuffer(StringVector(floor(Int, 1.2sizeof(str))), read=true, write=true) + out = IOBuffer(sizehint=floor(Int, 1.2sizeof(str)), read=true, write=true) out.size = 0 out.ptr = 1 while j != 0 From f24f51d1de0458df59f1b67f934a3d6548f54b97 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Thu, 8 Feb 2018 17:13:36 +0900 Subject: [PATCH 3/8] fix NEWS.md --- NEWS.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/NEWS.md b/NEWS.md index fd68ecce6d5ed..2638f35c77490 100644 --- a/NEWS.md +++ b/NEWS.md @@ -581,6 +581,9 @@ Library improvements like other `AbstractDict` subtypes and its constructors mirror the ones of `Dict`. ([#25210]) + * `IOBuffer` can take the `sizehint` keyword argument to suggest a capacity of + the buffer ([#?????]). + Compiler/Runtime improvements ----------------------------- From 2e3f5e89c278e45207d920284e06565be875cf59 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Thu, 8 Feb 2018 17:58:04 +0900 Subject: [PATCH 4/8] fill PR serial [ci skip] --- NEWS.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NEWS.md b/NEWS.md index 2638f35c77490..ee9345f0e077b 100644 --- a/NEWS.md +++ b/NEWS.md @@ -582,7 +582,7 @@ Library improvements ones of `Dict`. ([#25210]) * `IOBuffer` can take the `sizehint` keyword argument to suggest a capacity of - the buffer ([#?????]). + the buffer ([#25944]). Compiler/Runtime improvements ----------------------------- From 231146dd9cc5f61aaa5af1ab798d21f3f7bec90d Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 9 Feb 2018 11:09:13 +0900 Subject: [PATCH 5/8] remove redundant arguments and operations --- base/strings/basic.jl | 6 ++---- base/strings/io.jl | 7 +++---- base/strings/util.jl | 4 +--- 3 files changed, 6 insertions(+), 11 deletions(-) diff --git a/base/strings/basic.jl b/base/strings/basic.jl index 7e23b39a812f9..6e83d9f263f4b 100644 --- a/base/strings/basic.jl +++ b/base/strings/basic.jl @@ -512,8 +512,7 @@ isascii(s::AbstractString) = all(isascii, s) ## string map, filter, has ## function map(f, s::AbstractString) - out = IOBuffer(sizehint=sizeof(s), read=true, write=true) - truncate(out, 0) + out = IOBuffer(sizehint=sizeof(s)) for c in s c′ = f(c) isa(c′, Char) || throw(ArgumentError( @@ -525,8 +524,7 @@ function map(f, s::AbstractString) end function filter(f, s::AbstractString) - out = IOBuffer(sizehint=sizeof(s), read=true, write=true) - truncate(out, 0) + out = IOBuffer(sizehint=sizeof(s)) for c in s f(c) && write(out, c) end diff --git a/base/strings/io.jl b/base/strings/io.jl index 8c7bb64bf2aae..074d1329266de 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -81,7 +81,7 @@ julia> sprint(showcompact, 66.66666) ``` """ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) - s = IOBuffer(sizehint=sizehint, read=true, write=true) + s = IOBuffer(sizehint=sizehint) # specialized version of truncate(s,0) s.size = 0 s.ptr = 1 @@ -100,7 +100,7 @@ tostr_sizehint(x::Float32) = 12 function print_to_string(xs...; env=nothing) # specialized for performance reasons - s = IOBuffer(sizehint=tostr_sizehint(xs[1]), read=true, write=true) + s = IOBuffer(sizehint=tostr_sizehint(xs[1])) # specialized version of truncate(s,0) s.size = 0 s.ptr = 1 @@ -436,8 +436,7 @@ Returns: function unindent(str::AbstractString, indent::Int; tabwidth=8) indent == 0 && return str # Note: this loses the type of the original string - buf = IOBuffer(sizehint=sizeof(str), read=true, write=true) - truncate(buf,0) + buf = IOBuffer(sizehint=sizeof(str)) cutting = true col = 0 # current column (0 based) for ch in str diff --git a/base/strings/util.jl b/base/strings/util.jl index d9a8c7d6806f1..9d6839665d053 100644 --- a/base/strings/util.jl +++ b/base/strings/util.jl @@ -383,9 +383,7 @@ function replace(str::String, pat_repl::Pair; count::Integer=typemax(Int)) i = a = firstindex(str) r = coalesce(findnext(pattern,str,i), 0) j, k = first(r), last(r) - out = IOBuffer(sizehint=floor(Int, 1.2sizeof(str)), read=true, write=true) - out.size = 0 - out.ptr = 1 + out = IOBuffer(sizehint=floor(Int, 1.2sizeof(str))) while j != 0 if i == a || i <= k unsafe_write(out, pointer(str, i), UInt(j-i)) From 65f45fb819846283591bd9a8af2e8e70a4237f2c Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 9 Feb 2018 11:20:33 +0900 Subject: [PATCH 6/8] fixup! remove redundant arguments and operations --- base/strings/io.jl | 6 ------ 1 file changed, 6 deletions(-) diff --git a/base/strings/io.jl b/base/strings/io.jl index 074d1329266de..36319b0c3f646 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -82,9 +82,6 @@ julia> sprint(showcompact, 66.66666) """ function sprint(f::Function, args...; context=nothing, sizehint::Integer=0) s = IOBuffer(sizehint=sizehint) - # specialized version of truncate(s,0) - s.size = 0 - s.ptr = 1 if context !== nothing f(IOContext(s, context), args...) else @@ -101,9 +98,6 @@ tostr_sizehint(x::Float32) = 12 function print_to_string(xs...; env=nothing) # specialized for performance reasons s = IOBuffer(sizehint=tostr_sizehint(xs[1])) - # specialized version of truncate(s,0) - s.size = 0 - s.ptr = 1 if env !== nothing env_io = IOContext(s, env) for x in xs From 4ee880bf4bc8ee30dcbb19772224d7c6b5601598 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 9 Feb 2018 15:44:32 +0900 Subject: [PATCH 7/8] check the length of arguments for safety --- base/strings/io.jl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/base/strings/io.jl b/base/strings/io.jl index 36319b0c3f646..86009bd456e27 100644 --- a/base/strings/io.jl +++ b/base/strings/io.jl @@ -96,6 +96,9 @@ tostr_sizehint(x::Float64) = 20 tostr_sizehint(x::Float32) = 12 function print_to_string(xs...; env=nothing) + if isempty(xs) + return "" + end # specialized for performance reasons s = IOBuffer(sizehint=tostr_sizehint(xs[1])) if env !== nothing From 0103483f6188a9c8ee6aaba5e1f03d3865daf260 Mon Sep 17 00:00:00 2001 From: Kenta Sato Date: Fri, 9 Feb 2018 23:21:00 +0900 Subject: [PATCH 8/8] make sizehint higer precedence than maxsize --- base/iobuffer.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/base/iobuffer.jl b/base/iobuffer.jl index cffc42abf56d0..b19b9b3a782bd 100644 --- a/base/iobuffer.jl +++ b/base/iobuffer.jl @@ -108,7 +108,7 @@ function IOBuffer(; truncate::Union{Bool,Nothing}=true, maxsize::Integer=typemax(Int), sizehint::Union{Integer,Nothing}=nothing) - size = maxsize != typemax(Int) ? Int(maxsize) : sizehint !== nothing ? Int(sizehint) : 32 + size = sizehint !== nothing ? Int(sizehint) : maxsize != typemax(Int) ? Int(maxsize) : 32 flags = open_flags(read=read, write=write, append=append, truncate=truncate) buf = IOBuffer( StringVector(size),