Skip to content

patch_stdout is surprisingly slow #682

Open
@vlovich

Description

@vlovich

patch_stdout slows down the program (by ~5x) if there's a lot of output which seems really large considering that what it's trying to do conceptually doesn't seem too complicated.

from prompt_toolkit.completion import WordCompleter
from prompt_toolkit.eventloop.defaults import use_asyncio_event_loop
from prompt_toolkit.patch_stdout import patch_stdout
from prompt_toolkit.shortcuts import CompleteStyle
from prompt_toolkit.shortcuts.prompt import prompt
from threading import Thread
from prompt_toolkit.application import get_app

import sys

def spam_print():
  i = 1
  while True:
    print("This is spam", i)
    i += 1
    if i == 1000:
      try:
        get_app(raise_exception=True).exit(exception=KeyboardInterrupt())
      except:
        sys.exit(0)
      return

thread = None

while True:
  with patch_stdout():
  # with open("/dev/null"):
    if not thread:
      thread = Thread(target=spam_print)
      thread.start()
    prompt("> ", rprompt="test", complete_style=CompleteStyle.MULTI_COLUMN,
            completer=WordCompleter(list(chr(c) * 20 for c in range(ord("a"), ord("z")))))

time python3 test.py

Without patch_stdout: ~0.2s
With patch_stdout: ~1s (including getting hit by #681).

Attached captured profile but viewing it in snakeviz doesn't seem to immediately point me to the source of performance issues (aside from that it does look like there's a hotspot). Maybe run_until_complete in patch_stdout prints 1 line at a time instead of all lines that have been buffered?

profile.bin.zip

profile_without_patch_stdout.bin.zip

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions