Skip to content
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

tab completion hinting slows down paste on Windows #56884

Open
WalterMadelim opened this issue Dec 22, 2024 · 25 comments · May be fixed by #56895
Open

tab completion hinting slows down paste on Windows #56884

WalterMadelim opened this issue Dec 22, 2024 · 25 comments · May be fixed by #56895
Labels
completions Tab and autocompletion in the repl REPL Julia's REPL (Read Eval Print Loop)

Comments

@WalterMadelim
Copy link

WalterMadelim commented Dec 22, 2024

I use win11. The text editor is VScode. I use the portable version of Julia release.
If a block of code is copied from a *.jl text file, and pasted to a julia REPL in VScode, then the code can be checked and executed.
This workflow worked well, until yesterday I decided to use the latest stable release of Julia, which is 1.11.2.

Then I found that the code refreshing speed is manifestly slowed, compared with the previous version (1.10.2).
Could you tell me the reason and ways to sort it out?

I really did an experiment to exhibit this difference. For a 100-line code block, If 1.10.2 is used, the finishing time of code checking is 1.87 seconds.
If 1.11.2 is used, the time is 10.55 seconds.

(in Julia REPL, after the code is pasted)
The code review process of 1.10.2 seems to be line-by-line and it is fast, which is pleasant.
But the code review process of 1.11.2 seems to be word-by-word and it is very slow, which is annoying.

I append the code block (it is an expression indeed, you can easily use another block instead) here for convenience

quote
    function one(cb_data, cb_where::Cint)
        jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
        jvcb(x) = jvcb_scalar.(x)
        cb_where == Gurobi.GRB_CB_MIPSOL || return
        Gurobi.load_callback_variable_primal(cb_data, cb_where)
        o1po2, lbℶ1 = jvcb_scalar(o1) + jvcb_scalar(o2), jvcb_scalar(o3)
        u_, v_, x_, β1_ = jvcb(u), jvcb(v), jvcb(x), jvcb(β1)
        while true # must generate violating cut, or terminate
            iY = argmaxindY(u_, v_, x_, yM, β1_)
            ubℶ1 = ub_φ1(u_, v_, x_, yM, iY, β1_)
            β2, oℶ2 = get_β2_oℶ2(ℶ2, u_, v_, x_, yM[:, :, iY])
            Z = argmaxZ(u_, v_, x_, yM[:, :, iY], β2)
            Δ2_saturated = evalPush_Δ2(u_, v_, x_, yM, iY, Z, β2)
            cutSuccV[2] = true
            tryPush_ℶ2(Z, yM, iY, oℶ2, u_, v_, x_, β2)
            cutSuccV[1] = true
            ℶ1_saturated = tryPush_ℶ1(yM, iY, lbℶ1, u_, v_, x_, β1_)
            if ℶ1_saturated
                if Δ2_saturated && cutSuccV[2] == false
                    @info " ℶ2, ℶ1, Δ2 S⋅A⋅T, thus return without a violating cut"
                    return
                end
            else
                cutSuccV[1] || @error "ℶ1 is unupdated when it is unsaturated"
                ı = ℶ1CntV[1]
                ı += 1
                cut_expr = ℶ1["cn"][ı] + ip(ℶ1["pu"][ı], u) + ip(ℶ1["pv"][ı], v) + ip(ℶ1["px"][ı], x) + ip(ℶ1[""][ı], β1)
                JuMP.MOI.submit(ø, JuMP.MOI.LazyConstraint(cb_data), JuMP.@build_constraint(o3 >= cut_expr))
                ℶ1CntV[1] = ı
                return
            end
        end
    end
    function another(cb_data, cb_where::Cint)
        jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
        jvcb(x) = jvcb_scalar.(x)
        cb_where == Gurobi.GRB_CB_MIPSOL || return
        Gurobi.load_callback_variable_primal(cb_data, cb_where)
        o1po2, lbℶ1 = jvcb_scalar(o1) + jvcb_scalar(o2), jvcb_scalar(o3)
        u_, v_, x_, β1_ = jvcb(u), jvcb(v), jvcb(x), jvcb(β1)
        while true # must generate violating cut, or terminate
            iY = argmaxindY(u_, v_, x_, yM, β1_)
            ubℶ1 = ub_φ1(u_, v_, x_, yM, iY, β1_)
            β2, oℶ2 = get_β2_oℶ2(ℶ2, u_, v_, x_, yM[:, :, iY])
            Z = argmaxZ(u_, v_, x_, yM[:, :, iY], β2)
            Δ2_saturated = evalPush_Δ2(u_, v_, x_, yM, iY, Z, β2)
            cutSuccV[2] = true
            tryPush_ℶ2(Z, yM, iY, oℶ2, u_, v_, x_, β2)
            cutSuccV[1] = true
            ℶ1_saturated = tryPush_ℶ1(yM, iY, lbℶ1, u_, v_, x_, β1_)
            if ℶ1_saturated
                if Δ2_saturated && cutSuccV[2] == false
                    @info " ℶ2, ℶ1, Δ2 S⋅A⋅T, thus return without a violating cut"
                    return
                end
            else
                cutSuccV[1] || @error "ℶ1 is unupdated when it is unsaturated"
                ı = ℶ1CntV[1]
                ı += 1
                cut_expr = ℶ1["cn"][ı] + ip(ℶ1["pu"][ı], u) + ip(ℶ1["pv"][ı], v) + ip(ℶ1["px"][ı], x) + ip(ℶ1[""][ı], β1)
                JuMP.MOI.submit(ø, JuMP.MOI.LazyConstraint(cb_data), JuMP.@build_constraint(o3 >= cut_expr))
                ℶ1CntV[1] = ı
                return
            end
        end
    end
    function yetanother(cb_data, cb_where::Cint)
        jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
        jvcb(x) = jvcb_scalar.(x)
        cb_where == Gurobi.GRB_CB_MIPSOL || return
        Gurobi.load_callback_variable_primal(cb_data, cb_where)
        o1po2, lbℶ1 = jvcb_scalar(o1) + jvcb_scalar(o2), jvcb_scalar(o3)
        u_, v_, x_, β1_ = jvcb(u), jvcb(v), jvcb(x), jvcb(β1)
        while true # must generate violating cut, or terminate
            iY = argmaxindY(u_, v_, x_, yM, β1_)
            ubℶ1 = ub_φ1(u_, v_, x_, yM, iY, β1_)
            β2, oℶ2 = get_β2_oℶ2(ℶ2, u_, v_, x_, yM[:, :, iY])
            Z = argmaxZ(u_, v_, x_, yM[:, :, iY], β2)
            Δ2_saturated = evalPush_Δ2(u_, v_, x_, yM, iY, Z, β2)
            cutSuccV[2] = true
            tryPush_ℶ2(Z, yM, iY, oℶ2, u_, v_, x_, β2)
            cutSuccV[1] = true
            ℶ1_saturated = tryPush_ℶ1(yM, iY, lbℶ1, u_, v_, x_, β1_)
            if ℶ1_saturated
                if Δ2_saturated && cutSuccV[2] == false
                    @info " ℶ2, ℶ1, Δ2 S⋅A⋅T, thus return without a violating cut"
                    return
                end
            else
                cutSuccV[1] || @error "ℶ1 is unupdated when it is unsaturated"
                ı = ℶ1CntV[1]
                ı += 1
                cut_expr = ℶ1["cn"][ı] + ip(ℶ1["pu"][ı], u) + ip(ℶ1["pv"][ı], v) + ip(ℶ1["px"][ı], x) + ip(ℶ1[""][ı], β1)
                JuMP.MOI.submit(ø, JuMP.MOI.LazyConstraint(cb_data), JuMP.@build_constraint(o3 >= cut_expr))
                ℶ1CntV[1] = ı
                return
            end
        end
    end
end
@WalterMadelim
Copy link
Author

WalterMadelim commented Dec 22, 2024

Seems like that we should use this command

Base.active_repl.options.hint_tab_completes = false

But this command cannot be executed at startup.jl.
Is there anyway to ban this auto_complete? it takes too much pointless time.
I suggest that we revert to 1.10.2, What's your opinion? It is so uncomfortable to use.

PS just as uncomfortable as ios18, which removes the video review bar in its photos app, what a pity.

@KristofferC
Copy link
Member

My guess is that in windows the REPL see this as just entering characters quickly (since no bracket paste mode) and the tab complete suggestion will run after every character. This would indeed slow things down.

@WalterMadelim
Copy link
Author

WalterMadelim commented Dec 22, 2024

Maybe it's true for windows.

We really don't need this superfluous prompt. If I want to, I can press Tab handily.
Since copy-paste is a convenient workflow, I think we should speed up this process rather than hinder it.

By the way, is there any other method to speed up? Since I catch this problem today.

There is a saying: "I could have withstood darkness, if I had never seen brightness".

If I learn Julia from version 1.11.2, I would recognize this 10 seconds for 100 line of code as a normal speed. 💀

@LilithHafner
Copy link
Member

I tried to emulate this with pyautogui.write on linux. It was substantially slower than pasting on all Julia versions, but 1.11 was a similar speed to 1.10.

@IanButterworth
Copy link
Member

@WalterMadelim the instructions to disable tab complention hinting in startup.jl is here and here

if VERSION >= v"1.11.0-0"
  atreplinit() do repl
      repl.options.hint_tab_completes = false
  end
end

We need to figure out how to implement cancelling completion generation on the next keystroke. It's discussed here #55434 (comment)

@IanButterworth IanButterworth added REPL Julia's REPL (Read Eval Print Loop) completions Tab and autocompletion in the repl labels Dec 22, 2024
@IanButterworth
Copy link
Member

Otherwise, is there any way to identify when stuff is being pasted in in Windows, so we can disable hinting temporarily?

@WalterMadelim
Copy link
Author

@IanButterworth Thanks, it works.

@KristofferC
Copy link
Member

@IanButterworth, we could maybe piggy back on

# cancel auto-indent when next character is entered within this time frame :
auto_indent_time_threshold::Float64
which was created to solve a similar issue with copy paste in windows?

@IanButterworth
Copy link
Member

Can a windows user check the proposed fix here #56895

@IanButterworth IanButterworth changed the title the code refreshing speed after copy-paste in Julia REPL is greatly slowed, after updating Julia from 1.10.2 (2024-03-01) to 1.11.2 (2024-12-01) tab completion hinting slows down paste on Windows Dec 23, 2024
@IanButterworth
Copy link
Member

Bump. @WalterMadelim are you able to check #56895 ?

@WalterMadelim
Copy link
Author

@IanButterworth I'm using win11. But I don't know how to check 🤨.
I'm not familiar with Github actions.
I only know how to download a new release (1.11.3?) and see if the functionality is realized there.

@LilithHafner
Copy link
Member

LilithHafner commented Jan 6, 2025

If you're using juliaup (i.e. you've installed Julia from the windows store e.g. via winget install julia -s msstore) then you should be able to install the build of Julia for that PR with juliaup add pr56895 and launch it with juliaup +pr56895.

You should only do this if you trust the master version of Julia and have either reviewed the diff at https://github.com/JuliaLang/julia/pull/56895/files or trust @IanButterworth (a reasonable choice if you're not a high risk target because he has write access to this repo).

When you're done, you can uninstall that version of Julia with juliaup remove pr56895 to save disk space (though maybe you'll have to delete some files manually JuliaLang/juliaup#1129, https://discourse.julialang.org/t/juliaup-doesnt-garbage-collect/111118)

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 6, 2025

@LilithHafner I see. But I am more familiar with the windows 64-bit portable release.
Because the internet in my region is restricted. For example, if I want to install a package, I'll have to use a mirror website.
So I don't really want a Microsoft store option.

PS K:\uc24> winget install julia -s msstore
The `msstore` source requires that you view the following agreements before using.
Terms of Transaction: https://aka.ms/microsoft-store-terms-of-transaction
The source requires the current machine's 2-letter geographic region to be sent to the backend service to function properly (ex. "US").

Do you agree to all the source agreements terms?
[Y] Yes  [N] No: n

Is there a way to bypass the juliaup. Maybe like to install a specific version of a package.
For example, if I want to install a specific version of a package, I could pkg> add Example#c37b675
Is there a similar command update julia#f812726 😅.

Or you can adopt this update boldly and release 1.11.3, I'll test it there immediately after releasing. I think it won't cost much.

@LilithHafner
Copy link
Member

You can find the binary by navigating to #56895, clicking "show all checks", clicking "details" next to the build step, finding the "build x86_64-w64-mingw32" job and opening the "artifacts" tab.

Here's a direct link: https://buildkite.com/organizations/julialang/pipelines/julia-master/builds/43230/jobs/0193f498-ac54-4871-a7b0-6331cd4fc6fa/artifacts/0193f4b8-d403-4ae0-aa3e-f28be0e2e5bd.

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 7, 2025

@LilithHafner I've downloaded that artifact and tried it. @IanButterworth I'm afraid that this version is unusable. I'll list some experiences below.

A pristine welcome page is like this:

Microsoft Windows [Version 10.0.22631.4602]
(c) Microsoft Corporation. All rights reserved.

K:\julia_new\julia-f812726e6e\bin>julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1783 (2024-12-23)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/f812726e6e (fork: 1 commits, 19 days)
|__/                   |


�[0K�[32m�[1mjulia> �[0m�[0m
�[7C
�[7C

Then I type abcdefg with my keyboard and press enter, then it looks like

K:\julia_new\julia-f812726e6e\bin>julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1783 (2024-12-23)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/f812726e6e (fork: 1 commits, 19 days)
|__/                   |


�[0K�[32m�[1mjulia> �[0m�[0m
�[7C
�[7Cabcdefg
�[0K�[32m�[1mjulia> �[0m�[0m
�[7Cabcdefg
�[14C
�[?2004l�[0m�[91m�[1mERROR: �[22m�[39mUndefVarError: `abcdefg` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

�[0K
�[0K�[32m�[1mjulia> �[0m�[0m
�[7C
�[7C�[?2004hm�[0m
�[7C
�[7Culia> �[0

The above 2 blocks are tested with the windows cmd. When I test it in VScode, which uses PowerShell, it looks like

PS K:\uc24> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1783 (2024-12-23)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/f812726e6e (fork: 1 commits, 19 days)
|__/                   |

julia> abcdefg
ERROR: UndefVarError: `abcdefg` not defined in `Main`
Suggestion: check for spelling errors or missing imports.

C

Notice that it is not returned, (i.e., there is not a new julia> prompt).

Finally, I copy the 100-line quote-end block in my first comment in this webpage and paste it to the PowerShell terminal in VScode. And the outcome looks like

PS K:\uc24> julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1783 (2024-12-23)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/f812726e6e (fork: 1 commits, 19 days)
|__/                   |

julia> quote                                                                                                                                                                                                                                      C
           function one(cb_data, cb_where::Cint)
         

Notice that it gets stuck at the second line, and at the rightmost end of line 2, there is a Captital C.. When I press enter, the status is unaltered.

After an reversion to 1.11.2 with the modification in my startup.jl, things became normal.
PS I feel like that the package loading speed (in 1.11) is typically a bit slower than some previous version (maybe slower than 1.10?) I don't know why.

@IanButterworth
Copy link
Member

I think I've fixed the issue in #56895 (at least it works as expected for me in a windows VM)

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 7, 2025

@IanButterworth Unfortunately you didn't. 🥲. The refreshing process is still word-by-word, hence slow. (The animation looks smooth though) (But we don't want animation, we merely want to paste our code asap).
In addition,
I still test with the 100-line quote-end code block in my 1st comment. There are some duplications remnant on the screen after pasting. something like:

K:\julia2\julia-921a1ff33e-windows-x86_64\julia-921a1ff33e\bin>julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1849 (2025-01-07)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/921a1ff33e (fork: 3 commits, 0 days)
|__/                   |
julia> quote
julia> quote
           function one(cb_data, cb_where::Cint)
julia> quote
           function one(cb_data, cb_where::Cint)
               jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
julia> quote
           function one(cb_data, cb_where::Cint)
               jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
               jvcb(x) = jvcb_scalar.(x)
julia> quote
           function one(cb_data, cb_where::Cint)
               jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
               jvcb(x) = jvcb_scalar.(x)
                       cb_where == Gurobi.GRB_CB_MIPSOL || return
julia> quote
           function one(cb_data, cb_where::Cint)
               jvcb_scalar(x) = JuMP.callback_value(cb_data, x)
               jvcb(x) = jvcb_scalar.(x)
                       cb_where == Gurobi.GRB_CB_MIPSOL || return
               Gurobi.load_callback_variable_primal(cb_data, cb_where)
julia> quote
... (omission)

One more noteworthy point which is different from my initial report 2 weeks ago is that the final remaining code on the screen has color. e.g. keywords quote, function, end are red, true and @error are pink, strings are in green, and name of functions while invoking are in blue.

The auto-completion works properly though.

The "duplications remnant" mentioned above is not in this patch release alone. This phenomenon also exists if I revert to 1.11.2 with my startup.jl file modified to ban auto-completion. But that is tolerable insofar as I can paste quickly.

@IanButterworth
Copy link
Member

Seems improved to me. Are you seeing slower than this?

Screen.Recording.2025-01-07.at.1.34.57.PM.mov

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 8, 2025

@IanButterworth The resullts in your video is fast. However this is not for me. I use windows cmd also and the julia version is

Microsoft Windows [Version 10.0.22631.4602]
(c) Microsoft Corporation. All rights reserved.

K:\julia2\julia-921a1ff33e-windows-x86_64\julia-921a1ff33e\bin>julia
               _
   _       _ _(_)_     |  Documentation: https://docs.julialang.org
  (_)     | (_) (_)    |
   _ _   _| |_  __ _   |  Type "?" for help, "]?" for Pkg help.
  | | | | | | |/ _` |  |
  | | |_| | | | (_| |  |  Version 1.12.0-DEV.1849 (2025-01-07)
 _/ |\__'_|_|_|\__'_|  |  IanButterworth:ib/repl_hint_paste_off/921a1ff33e (fork: 3 commits, 1 day)

If I configure my startup.jl file to ban autocompletion, the result is 3 seconds.
If I use the default setting, it will takes 9 seconds.
I'll record a video for both to let you know the difference.

The default setting is:
https://github.com/user-attachments/assets/32607a40-6fe9-4bad-9e58-35217adb5469

After adding VERSION >= v"1.11.0-0" && atreplinit(repl -> (repl.options.hint_tab_completes = false)) in my startup.jl, the result is:
https://github.com/user-attachments/assets/1c8f6c7e-d2a8-46db-bf9b-e05ff1d1ba4e

@IanButterworth
Copy link
Member

Can you try increasing this threshold and if it helps figure out what the lowest good value is.
Perhaps double it to start?

julia> Base.active_repl.options.auto_indent_time_threshold
0.005

@WalterMadelim
Copy link
Author

It seems it won't help by tuning this parameter to some value.
I would recommend that we revert to the previous setting.
I don't think this IntelliSense is necessary in julia REPL.
Users usually write code in text editors, e.g. in VScode, which already has this IntelliSense feature.
It suffices to have the tab function to list all relevant names in REPL, which were already realized before julia 1.9

@IanButterworth
Copy link
Member

What values did you try?

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 8, 2025

@IanButterworth any value such that 1e-5 ≤ value ≤ 1e-1

There is few differences by tuning this parameter: The cursor just move from left to right, then from top to bottom.

As a comparison, if I add that line to ban this hint, the motion is visibly different. It just refresh line by line.

Or, if I just press 'ctrl + D' to quit julia REPL, and revert to the windows cmd, then I paste that 100-line quote-end code block (although this behavior is pointless), The motion will be substantially faster.

@IanButterworth
Copy link
Member

There is few differences by tuning this parameter

Do you mean no difference? Or if you mean there is a difference (I.e. speed improvement), what value does it start at?

@WalterMadelim
Copy link
Author

WalterMadelim commented Jan 8, 2025

@IanButterworth I did a test, with the help of 'time()', let's see the results.

# [ Info: value = 0.005, time_spent = 8.123999834060669
# [ Info: value = 0.0075, time_spent = 7.429999828338623
# [ Info: value = 0.01125, time_spent = 7.184999942779541
# [ Info: value = 0.0253125, time_spent = 6.797999858856201
# [ Info: value = 0.056953125, time_spent = 6.625999927520752
# [ Info: value = 0.12814453125, time_spent = 6.748000144958496
# [ Info: value = 0.5, time_spent = 6.692000150680542
# [ Info: value = 1.0, time_spent = 6.880000114440918

If I ban auto-completion in startup.jl then

[ Info: value = 0.005, time_spent = 1.8029999732971191

If I switch julia to 1.9.4, then

[ Info: value = 0.005, time_spent = 1.434000015258789

Test code is:

Base.active_repl.options.auto_indent_time_threshold = some_value
t0 = time()
# code block
@info "value = $(Base.active_repl.options.auto_indent_time_threshold), time_spent = $(time() - t0)"

For every experiment, I open a pristine julia REPL and execute only once. Of course by pasting, not include("test.jl")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completions Tab and autocompletion in the repl REPL Julia's REPL (Read Eval Print Loop)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants