Skip to content

performance issues #250

@lunixbochs

Description

@lunixbochs

I'm profiling/debugging performance bottlenecks in the python client.

Two things stuck out so far.

  • Calls to BufferedFormatter in logging, when logging was disabled. This can be fixed by gating any debug(), warn() etc calls behind an if _debug statement as shown in asyncio.
    • (Edit: fixed, see below)
  • walk(to_nvim) and walk(from_nvim) are extremely expensive calls on nested object trees. For example, if I have a 5000 line buffer and get/set the entire thing, these calls seem to account for at least 80% of the 20ms spent. I fixed this by adding the following functions on the Remote and Nvim classes and invoking it for buf_get_lines and buf_set_lines instead of request_raw:
class Remote:
    def request_raw(self, name, *args, **kwargs):
        return self._session.request_raw(name, self._session._to_nvim(self), *args, **kwargs)

class Nvim:
    def request_raw(self, name, *args, **kwargs):
        return self._session.request(name, *args, **kwargs)

Profiling data generated with yappi on Python 3.3 and my test script are attached.
after.txt
before.txt

import neovim

sample = ['a'] * 10000

def setup():
    n = neovim.attach('child', argv=['/Users/aegis/build/neovim/build/bin/nvim', '--embed'])
    buf = n.current.buffer
    buf[:] = sample
    return buf

def bufeq(buf):
    buf[:] = sample

def eqbuf(buf):
    _ = buf[:]

buf = setup()
for i in range(10):
    bufeq(buf)

for i in range(10):
    eqbuf(buf)

import sys
sys.exceptionhandler = lambda *a: 0

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions