-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
Re-enable tab completion of kwargs for large method tables #58012
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
while testing to ensure that absurdly large method tables don't tank the performance of the REPL
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You're just essentially demonstrating here that for your specific test case, the subtyping algorithm always takes the fast path--which is true, but seems hardly relevant to the actual point of having this limit
@vtjnash do you have suggestions on how to improve these tests? Or could you communicate how they're not testing what I think they're testing so I can fix them? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are opting into an algorithm that is too slow for interactive usage (O(n^2)
) in measurements when doing anything that doesn't just hit the fast paths like your test, which is why we have these limits. It has nothing to do with display limitations (those limits should not even occur, since display occurs elsewhere). We can opt into a somewhat faster version of the algorithm with -1
(maybe closer to O(n*log n)
but nobody has proved that) , but it is also still too slow, delaying keystrokes by much more than 10 ms of added perceptual latency.
This is also just measurements on a simple system image with hardly anything added.
julia> @time Base._methods_by_ftype(Tuple{DataType,Vararg}, 4000, Base.get_world_counter()) |> length
0.406149 seconds (16.67 k allocations: 1.171 MiB)
julia> @time Base._methods_by_ftype(Tuple{DataType,Vararg}, -1, Base.get_world_counter()) ;
0.113711 seconds (15.12 k allocations: 1.108 MiB)
julia> @time Base._methods_by_ftype(Tuple{Type,Vararg}, 4000, Base.get_world_counter()) |> length
0.858004 seconds (59.50 k allocations: 2.917 MiB)
2745
julia> @time Base._methods_by_ftype(Tuple{Type,Vararg}, -1, Base.get_world_counter()) |> length
0.231704 seconds (50.85 k allocations: 2.568 MiB)
2745
julia> @time Base._methods_by_ftype(Tuple{Type,Vararg}, 40, Base.get_world_counter());
0.000250 seconds (101 allocations: 7.312 KiB)
julia> @time Base._methods_by_ftype(Tuple{typeof(Core.kwcall),Vararg}, 4000, Base.get_world_counter()) |> length
0.105716 seconds (8.45 k allocations: 415.672 KiB)
1138
OK, that's interesting that the limit changes the algorithm — I wasn't aware of that and wouldn't have guessed it. But PR branch is using 500 as its cutoff (not 4000). It's also in contrast with the -1 limit when the REPL has no clue about the function it's calling (the pycall example). I'm trying to restore functionality that the fixes for #54131 broke without impacting perceptual performance in that catastrophic case.
The test-case seems to be adequately representing this distinction. But you may be right that it's still too slow.
Or for show:
|
OK, seems like there could be a better heuristic then. I just pushed a change to disable tab completion in cases where the REPL doesn't know the concrete function — that resolves the PyCall issue (where the function to be called was inferred as julia> using REPL, REPL.REPLCompletions
julia> @time completions((s="Core.kwcall(lim";), lastindex(s), @__MODULE__, false);
0.022046 seconds (18.23 k allocations: 934.469 KiB)
julia> function g54131 end
g54131 (generic function with 0 methods)
julia> for i in 1:498
@eval g54131(::Val{$i}) = i
end
julia> g54131(::Val{499}; kwarg=true) = 499*kwarg
g54131 (generic function with 499 methods)
julia> @time completions((s="g54131(lim";), lastindex(s), @__MODULE__, false)
0.002348 seconds (8.19 k allocations: 427.562 KiB)
(REPL.REPLCompletions.Completion[], 8:10, false)
julia> @time completions((s="g54131(kw";), lastindex(s), @__MODULE__, false)
0.002278 seconds (8.19 k allocations: 427.375 KiB)
(REPL.REPLCompletions.Completion[REPL.REPLCompletions.KeywordArgumentCompletion("kwarg")], 8:9, true)
julia> for i in 500:1000
@eval g54131(::Val{$i}) = i
end
julia> @time completions((s="g54131(kw";), lastindex(s), @__MODULE__, false)
0.006390 seconds (12.21 k allocations: 642.750 KiB)
(REPL.REPLCompletions.Completion[REPL.REPLCompletions.KeywordArgumentCompletion("kwarg")], 8:9, true)
julia> for i in 1001:2000
@eval g54131(::Val{$i}) = i
end
julia> @time completions((s="g54131(kw";), lastindex(s), @__MODULE__, false)
0.020564 seconds (20.22 k allocations: 1.051 MiB)
(REPL.REPLCompletions.Completion[REPL.REPLCompletions.KeywordArgumentCompletion("kwarg")], 8:9, true)
julia> for i in 2001:4000
@eval g54131(::Val{$i}) = i
end
julia> @time completions((s="g54131(kw";), lastindex(s), @__MODULE__, false)
0.073561 seconds (36.22 k allocations: 1.801 MiB)
(REPL.REPLCompletions.Completion[REPL.REPLCompletions.KeywordArgumentCompletion("kwarg")], 8:9, true) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the implementation change itself is fine.
Regarding tests using @elasped
, I think we can just omit them since ultimately what should be tested is our perceived speed, and I feel it is difficult to test this systematically.
I mean, the reason I added the test was because of #54131 — that's not just being perceptively slow, it's a being so slow you think it crashed. I suppose I could axe the tests, but they represent a real but less-common use case that can be easy to forget about. |
…#58012) while testing to ensure that ~~absurdly large method tables~~ tab completing over an abstract function call doesn't tank the performance of the REPL Fixes JuliaLang#57836 (cherry picked from commit 6f12957) (cherry picked from commit c8a4fd2) (cherry picked from commit 0d20fb9)
…#58012) while testing to ensure that ~~absurdly large method tables~~ tab completing over an abstract function call doesn't tank the performance of the REPL Fixes JuliaLang#57836 (cherry picked from commit 6f12957) (cherry picked from commit c8a4fd2)
) (#58928) Co-authored-by: Matt Bauman <mbauman@juliahub.com>
Backported PRs: - [x] #54840 <!-- Add boundscheck in speccache_eq to avoid OOB access due to data race --> - [x] #42080 <!-- recommend explicit `using Foo: Foo, ...` in package code (was: "using considered harmful") --> - [x] #58127 <!-- [DOC] Update installation docs: /downloads/ => /install/ --> - [x] #58202 <!-- [release-1.11] malloc: use jl_get_current_task to fix null check --> - [x] #58584 <!-- Make `Ptr` values static-show w/ type-information --> - [x] #58637 <!-- Make late gc lower handle insertelement of alloca use. --> - [x] #58837 <!-- fix null comparisons for non-standard address spaces --> - [x] #57826 <!-- Add a `similar` method for `Type{<:CodeUnits}` --> - [x] #58293 <!-- fix trailing indices stackoverflow in reinterpreted array --> - [x] #58887 <!-- Pkg: Allow configuring can_fancyprint(io::IO) using IOContext --> - [x] #58937 <!-- Fix nthreadpools size in JLOptions --> - [x] #58978 <!-- Fix precompilepkgs warn loaded setting --> - [x] #58998 <!-- Bugfix: Use Base.aligned_sizeof instead of sizeof in Mmap.mmap --> - [x] #59120 <!-- Fix memory order typo in "src/julia_atomics.h" --> - [x] #59170 <!-- Clarify and enhance confusing precompile test --> Need manual backport: - [ ] #56329 <!-- loading: clean up more concurrency issues --> - [ ] #56956 <!-- Add "mea culpa" to foreign module assignment error. --> - [ ] #57035 <!-- linux: workaround to avoid deadlock inside dl_iterate_phdr in glibc --> - [ ] #57089 <!-- Block thread from receiving profile signal with stackwalk lock --> - [ ] #57249 <!-- restore non-freebsd-unix fix for profiling --> - [ ] #58011 <!-- Remove try-finally scope from `@time_imports` `@trace_compile` `@trace_dispatch` --> - [ ] #58062 <!-- remove unnecessary edge from `exp_impl` to `pow` --> - [ ] #58157 <!-- add showing a string to REPL precompile workload --> - [ ] #58209 <!-- Specialize `one` for the `SizedArray` test helper --> - [ ] #58108 <!-- Base.get_extension & Dates.format made public --> - [ ] #58356 <!-- codegen: remove readonly from abstract type calling convention --> - [ ] #58415 <!-- [REPL] more reliable extension loading --> - [ ] #58510 <!-- Don't filter `Core` methods from newly-inferred list --> - [ ] #58110 <!-- relax dispatch for the `IteratorSize` method for `Generator` --> - [ ] #58965 <!-- Fix `hygienic-scope`s in inner macro expansions --> - [ ] #58971 <!-- Fix alignment of failed precompile jobs on CI --> - [ ] #59066 <!-- build: Also pass -fno-strict-aliasing for C++ --> Contains multiple commits, manual intervention needed: - [ ] #55877 <!-- fix FileWatching designs and add workaround for a stat bug on Apple --> - [ ] #56755 <!-- docs: fix scope type of a `struct` to hard --> - [ ] #57809 <!-- Fix fptrunc Float64 -> Float16 rounding through Float32 --> - [ ] #57398 <!-- Make remaining float intrinsics require float arguments --> - [ ] #56351 <!-- Fix `--project=@script` when outside script directory --> - [ ] #57129 <!-- clarify that time_ns is monotonic --> - [ ] #58134 <!-- Note annotated string API is experimental in Julia 1.11 in HISTORY.md --> - [ ] #58401 <!-- check that hashing of types does not foreigncall (`jl_type_hash` is concrete evaluated) --> - [ ] #58435 <!-- Fix layout flags for types that have oddly sized primitive type fields --> - [ ] #58483 <!-- Fix tbaa usage when storing into heap allocated immutable structs --> - [ ] #58512 <!-- Make more types jl_static_show readably --> - [ ] #58012 <!-- Re-enable tab completion of kwargs for large method tables --> - [ ] #58683 <!-- Add 0 predecessor to entry basic block and handle it in inlining --> - [ ] #59112 <!-- Add builtin function name to add methods error --> Non-merged PRs with backport label: - [ ] #59329 <!-- aotcompile: destroy LLVM context after serializing combined module --> - [ ] #58848 <!-- Set array size only when safe to do so --> - [ ] #58535 <!-- gf.c: include const-return methods in `--trace-compile` --> - [ ] #58038 <!-- strings/cstring: `transcode`: prevent Windows sysimage invalidation --> - [ ] #57604 <!-- `@nospecialize` for `string_index_err` --> - [ ] #57366 <!-- Use ptrdiff_t sized offsets for gvars_offsets to allow large sysimages --> - [ ] #56890 <!-- Enable getting non-boxed LLVM type from Julia Type --> - [ ] #56823 <!-- Make version of opaque closure constructor in world --> - [ ] #55958 <!-- also redirect JL_STDERR etc. when redirecting to devnull --> - [ ] #55956 <!-- Make threadcall gc safe --> - [ ] #55534 <!-- Set stdlib sources as read-only during installation --> - [ ] #55499 <!-- propagate the terminal's `displaysize` to the `IOContext` used by the REPL --> - [ ] #55458 <!-- Allow for generically extracting unannotated string --> - [ ] #55457 <!-- Make AnnotateChar equality consider annotations --> - [ ] #55220 <!-- `isfile_casesensitive` fixes on Windows --> - [ ] #53957 <!-- tweak how filtering is done for what packages should be precompiled --> - [ ] #51479 <!-- prevent code loading from lookin in the versioned environment when building Julia --> - [ ] #50813 <!-- More doctests for Sockets and capitalization fix --> - [ ] #50157 <!-- improve docs for `@inbounds` and `Base.@propagate_inbounds` --> --------- Co-authored-by: Kiran Pamnany <kpamnany@users.noreply.github.com> Co-authored-by: adienes <51664769+adienes@users.noreply.github.com> Co-authored-by: Gabriel Baraldi <baraldigabriel@gmail.com> Co-authored-by: Keno Fischer <keno@juliacomputing.com> Co-authored-by: Simeon David Schaub <simeon@schaub.rocks> Co-authored-by: Jameson Nash <vtjnash@gmail.com> Co-authored-by: Alex Arslan <ararslan@comcast.net> Co-authored-by: Fons van der Plas <fonsvdplas@gmail.com> Co-authored-by: Ian Butterworth <i.r.butterworth@gmail.com> Co-authored-by: JonasIsensee <jonas.isensee@web.de> Co-authored-by: Curtis Vogt <curtis.vogt@gmail.com> Co-authored-by: Dilum Aluthge <dilum@aluthge.com> Co-authored-by: DilumAluthgeBot <43731525+DilumAluthgeBot@users.noreply.github.com> Co-authored-by: DilumAluthge <5619885+DilumAluthge@users.noreply.github.com>
while testing to ensure that
absurdly large method tablestab completing over an abstract function call doesn't tank the performance of the REPLFixes #57836