From unknown Sat Jun 21 12:25:04 2025 Content-Disposition: inline Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 X-Mailer: MIME-tools 5.509 (Entity 5.509) Content-Type: text/plain; charset=utf-8 From: bug#77588 <77588@debbugs.gnu.org> To: bug#77588 <77588@debbugs.gnu.org> Subject: Status: Catastrophic slowdown in eglot via `flymake-diag-region' Reply-To: bug#77588 <77588@debbugs.gnu.org> Date: Sat, 21 Jun 2025 19:25:04 +0000 retitle 77588 Catastrophic slowdown in eglot via `flymake-diag-region' reassign 77588 emacs submitter 77588 JD Smith severity 77588 normal thanks From debbugs-submit-bounces@debbugs.gnu.org Sun Apr 06 18:50:53 2025 Received: (at submit) by debbugs.gnu.org; 6 Apr 2025 22:50:53 +0000 Received: from localhost ([127.0.0.1]:50058 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u1YpJ-00028Q-3E for submit@debbugs.gnu.org; Sun, 06 Apr 2025 18:50:53 -0400 Received: from lists.gnu.org ([2001:470:142::17]:60528) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1u1YpG-00027l-LB for submit@debbugs.gnu.org; Sun, 06 Apr 2025 18:50:51 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u1Yp7-0001f1-NO for bug-gnu-emacs@gnu.org; Sun, 06 Apr 2025 18:50:41 -0400 Received: from mail-il1-x131.google.com ([2607:f8b0:4864:20::131]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1u1Yp5-0005L4-IY for bug-gnu-emacs@gnu.org; Sun, 06 Apr 2025 18:50:41 -0400 Received: by mail-il1-x131.google.com with SMTP id e9e14a558f8ab-3d5ebc2b725so10027675ab.3 for ; Sun, 06 Apr 2025 15:50:38 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1743979837; x=1744584637; darn=gnu.org; h=to:date:message-id:subject:mime-version:from:from:to:cc:subject :date:message-id:reply-to; bh=qIoQNB8cTOkQmTILeCBQFnu0znz5jXn2sF2XvvaAeaw=; b=fIdZl7cCkJ4isdm/Wlv+GmQdruKzzH5fcf4UbP09ISHlDDdRVRiVeOZVDuN8tHQUga d2/nGsHZ+0SVcfzO/wq/Y2RSWNIz0+6QoEavkiNlEGobhg5ecFBlvQtlUD5UoBHOFXAG BdcdwYF7tbHuQx0AyY1uUtPKYxHrLZ4KMHGfv7nN9oeO+8bdhxDyfvz/XZl9Y4depEPE xmhAA29/JLEGg0wLgb6ptXB0Pj8IsIzf8w9GUgHQYEfa2aMIcEuMi1L1Dz17biP1ykYy A+CvkIggelmPhGxSRe4obFMFz4xXs0vfy/xzaWEKJVInB1IFAB9aVmT0hHNZrc996OWM ltrw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1743979837; x=1744584637; h=to:date:message-id:subject:mime-version:from:x-gm-message-state :from:to:cc:subject:date:message-id:reply-to; bh=qIoQNB8cTOkQmTILeCBQFnu0znz5jXn2sF2XvvaAeaw=; b=JpUPjd1kihHog9JQ4l2RubszFpLNPBBBuTElgIuQGmDl9wO7uvq2tKkPd+8FSzqkjg oOGV8QgRbIbW5yhfZaDvfXiKNiXj9+siPa8h6Dx2HcjlSwT8iMOjeVn69Cz1UTiwpWaf UweR53qOX/fIIlarSyJ8qp8OIYeMwncLxII//KYXrhZMrCR4+6Xy8g7yBG299hU4zd89 AYllaesz565v9Fl2CMnPGHey7m5Ca0avM1glCpVfSDkvVR+ypyHGLneD9XRksP2g/s4d HBuSDGDV2+J58Gzjrs6S0zgCKBo72UT7Tum+ldtBfR4kK3PH7PJ0M/+s9MBB0RjIjqEy NOcA== X-Gm-Message-State: AOJu0Ywb2xD8X4BPS+uW2Sy8ELs5/1LhPi0IyG2y2Lg4bTvPFIXoC4og eP4dI61h7oTif4cncXk4ps7L6iG4/sWUIaos7DQoauSpWWewAteXawFCMg== X-Gm-Gg: ASbGncuBDVl0cvgMWI4Y4kVqyrrDSo+9udINbDFdwMX00tRhc1FCh0xZVwkadI3bglN dD1KRNauOUrR6WmnCwHkzuesoaUGq2D/7WBVJoq32F3vY6Gj2O2zNE5brsuCkYbzeHXyxpoDAsj BELYKl3W7D/IodP66ZNJmERw9segNEr5XnYI1pcEdOijhHeHZPOASDWoVRx61+6AJL9y+X7XDge 5vDo1WhqfIZ4SUgrVY6n99SegsJ1aI0/RzjbwWIRdV0okmDMJ1C06Hwl6JBr4TQ89plzyyOuoTL oPgsRV60LK0+04MadDvPeBdnqSczFjqhmZLWioMtpWnp9YACxjjE+YF+ZcrzupFclvtSoOUEFr/ nv7jFdfVu9iD3Ib3C9dPyJwEf178= X-Google-Smtp-Source: AGHT+IFPlXrLgiBwcKg5AtdYXuqGurSdXSn4OCxIZZk3A00fH3UKmIT6AfquLnIU7SL95T6OA3qigw== X-Received: by 2002:a05:6e02:2218:b0:3d5:dec0:7c03 with SMTP id e9e14a558f8ab-3d6e534ad64mr114040475ab.12.1743979837132; Sun, 06 Apr 2025 15:50:37 -0700 (PDT) Received: from smtpclient.apple (cm-24-53-185-196.buckeyecom.net. [24.53.185.196]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4f4b5d247c7sm1997251173.89.2025.04.06.15.50.36 for (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Sun, 06 Apr 2025 15:50:36 -0700 (PDT) From: JD Smith Content-Type: multipart/alternative; boundary="Apple-Mail=_B8DC673C-8435-40E0-93A5-DE6AD84F4615" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.400.131.1.6\)) Subject: Catastrophic slowdown in eglot via `flymake-diag-region' Message-Id: Date: Sun, 6 Apr 2025 18:50:26 -0400 To: bug-gnu-emacs@gnu.org X-Mailer: Apple Mail (2.3826.400.131.1.6) Received-SPF: pass client-ip=2607:f8b0:4864:20::131; envelope-from=jdtsmith@gmail.com; helo=mail-il1-x131.google.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-Spam-Score: 1.0 (+) X-Debbugs-Envelope-To: submit X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.0 (/) --Apple-Mail=_B8DC673C-8435-40E0-93A5-DE6AD84F4615 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=us-ascii I was diagnosing a painful eglot pause of about 10 seconds that would = reliably occur every few edits when completing candidates and working in = a long python file (~8k lines). I am using the basedpyright LSP server. = I narrowed this down to eglot's `textDocument/publishDiagnostics' = notification handler. The file I was working on has several hundred warnings and errors, so = that represents a substantial message from the LSP server. After a fair = bit of timing and sleuthing, I narrowed it down further. A few = interrelated misbehaviors combined to produce the huge intermittent = pauses: When completing text directly after entering/removing a newline, the = Diagnostics ranges received by eglot are out of date and "one line off". Some of these off-by-one-line diagnostic message ranges now land on = blank lines in the file, so the effective range there is empty. Seeing an empty range, eglot declares the server has "botched" it, so it = tries to make a by-hand recalculation of the range using = `flymake-diag-region'. `flymake-diag-region' for some reason calls (end-of-thing 'sexp) and = (end-of-thing 'symbol). =20 In some positions in a long python file these commands are VERY SLOW. = Rather than the typical call time of ~1ms, at these certain positions = `flymake-diag-region' takes ~400ms. It doesn't take too many "botched eglot ranges" interacting with slow = `thingatpt' misbehavior to add up to a 10s delay. I'm not certain of the best solution. A few ideas, from hardest to = easiest: Teach eglot textDocument/diagnostic ++++++++++++++++++++++++++++ textDocument/publishDiagnostics messages arrive way too frequently IMO, = after every buffer change of any kind. They are pushed to eglot from = the LSP server, and if they contain hundreds of errors, this becomes = very inefficient (re-painting with flymake the same hundreds of regions = over and over after each keystroke). The best solution here would probably be to adopt "pull" diagnostics = using textDocument/diagnostic, perhaps in an idle-timer whose duration = the user can configure. I don't believe EGLOT can do diagnostic pulls = at the moment. Don't use thingatpt in `flymake-diag-region' +++++++++++++++++++++++++++++++++ `flymake-diag-region' should perhaps not use thingapt, which is subject = to the performance vagaries of the major-mode and underlying file. I am = uncertain why it relies on that. Perhaps the performance of those will = be improved with treesitter variants. Eglot could detect off-by-one diagnostics +++++++++++++++++++++++++++++++ Hard to know the best heuristic, but lots of null effective ranges is a = good one. Eglot can simply ignore null range diagnostics +++++++++++++++++++++++++++++++++++ Eglot doesn't need to use `flymake-diag-region' to try to calculate an = update range if it encounters a null diagnostic range. It could simply = drop those, as they are probably wrong anyway, and will shortly be = updated. --Apple-Mail=_B8DC673C-8435-40E0-93A5-DE6AD84F4615 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=us-ascii

I was diagnosing a painful eglot = pause of about 10 seconds that would reliably occur every few edits when = completing candidates and working in a long python file (~8k lines). =  I am using the basedpyright LSP server.  I narrowed this down = to eglot's `textDocument/publishDiagnostics' notification = handler.

The file I was working on has several = hundred warnings and errors, so that represents a substantial message = from the LSP server.  After a fair bit of timing and sleuthing, I = narrowed it down further.  A few interrelated misbehaviors combined = to produce the huge intermittent = pauses:

  1. When completing = text directly after entering/removing a newline, the Diagnostics ranges = received by eglot are out of date and "one line off".
  2. Some of = these off-by-one-line diagnostic message ranges now land on blank lines = in the file, so the effective range there is empty.
  3. Seeing an = empty range, eglot declares the server has "botched" it, so it tries to = make a by-hand recalculation of the range using = `flymake-diag-region'.
  4. `flymake-diag-region' for some reason = calls (end-of-thing 'sexp) and (end-of-thing 'symbol). =  
  5. In some positions in a long python file these commands = are VERY SLOW.  Rather than the typical call time of ~1ms, at these = certain positions `flymake-diag-region' takes = ~400ms.

It doesn't take too many "botched = eglot ranges" interacting with slow `thingatpt' misbehavior to add up to = a 10s delay.

I'm not certain of the best = solution.  A few ideas, from hardest to = easiest:

Teach eglot = textDocument/diagnostic
++++++++++++++++++++++++++++

 textDocument/publishDiagnostics messages arrive way = too frequently IMO, after every buffer change of any kind.  They = are pushed to eglot from the LSP server, and if they contain hundreds of = errors, this becomes very inefficient (re-painting with flymake the same = hundreds of regions over and over after each = keystroke).

The best = solution here would probably be to adopt "pull" diagnostics = using textDocument/diagnostic, perhaps in an idle-timer whose = duration the user can configure.  I don't believe EGLOT can do = diagnostic pulls at the moment.

Don't = use thingatpt in = `flymake-diag-region'
+++++++++++++++++++++++++++++++++

`flymake-diag-region' should perhaps not use thingapt, = which is subject to the performance vagaries of the major-mode and = underlying file.  I am uncertain why it relies on that. =  Perhaps the performance of those will be improved with treesitter = variants.

Eglot could detect = off-by-one = diagnostics
+++++++++++++++++++++++++++++++

=
Hard to know the best heuristic, but lots of null effective ranges = is a good one.

Eglot can simply ignore null = range = diagnostics
+++++++++++++++++++++++++++++++++++

Eglot doesn't need to use `flymake-diag-region' to try to = calculate an update range if it encounters a null diagnostic range. =  It could simply drop those, as they are probably wrong anyway, and = will shortly be = updated.

= --Apple-Mail=_B8DC673C-8435-40E0-93A5-DE6AD84F4615-- From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 07 07:21:53 2025 Received: (at 77588) by debbugs.gnu.org; 7 Apr 2025 11:21:53 +0000 Received: from localhost ([127.0.0.1]:53015 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u1kY5-0006kL-5r for submit@debbugs.gnu.org; Mon, 07 Apr 2025 07:21:53 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:36236) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.84_2) (envelope-from ) id 1u1kY2-0006jn-DZ for 77588@debbugs.gnu.org; Mon, 07 Apr 2025 07:21:50 -0400 Received: from fencepost.gnu.org ([2001:470:142:3::e]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1u1kXu-00014l-Kd; Mon, 07 Apr 2025 07:21:43 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=gnu.org; s=fencepost-gnu-org; h=MIME-version:References:Subject:In-Reply-To:To:From: Date; bh=/1Lx7Zs2uPy1q2aLAMUKvchmRhEbCRsJXFnD5ycL7P0=; b=iC6o0OU6ivhe9a1DmbB9 h35dXXKGRXFe0dTNKmQfmCRKY8MS0m91geitK2fbRSousYF3VxTFvx5AyR3jzdsJuyDHofMWtadJZ pykBJsOcMOF19VufyjYqnJvmmM0tC2Sbx5cg9SsnjisNBaTJEvtFghCBzywM0ka6dRtmWI6qV9F4g 34SYhhxDmrvXzh4FPRgDt2RMeuVRgk9MNbHxYcUWt4z6B7V7rtOqUujxkD0VZw94oXf3kdAr4GqCU 6g7djSb6H44OgrKjF1/nduPx0J8AhmY9KVaUq/6i+Sa+ok397b/qUu5GmpchCivnr9Fo+0wI+H5dU PrqrOp7iJkpfSg==; Date: Mon, 07 Apr 2025 14:21:38 +0300 Message-Id: <86v7rgtdx9.fsf@gnu.org> From: Eli Zaretskii To: JD Smith , =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= , Spencer Baugh In-Reply-To: (message from JD Smith on Sun, 6 Apr 2025 18:50:26 -0400) Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' References: MIME-version: 1.0 Content-type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Spam-Score: -2.3 (--) X-Debbugs-Envelope-To: 77588 Cc: 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -3.3 (---) > From: JD Smith > Date: Sun, 6 Apr 2025 18:50:26 -0400 > > I was diagnosing a painful eglot pause of about 10 seconds that would reliably occur every few edits when > completing candidates and working in a long python file (~8k lines). I am using the basedpyright LSP server. > I narrowed this down to eglot's `textDocument/publishDiagnostics' notification handler. > > The file I was working on has several hundred warnings and errors, so that represents a substantial message > from the LSP server. After a fair bit of timing and sleuthing, I narrowed it down further. A few interrelated > misbehaviors combined to produce the huge intermittent pauses: > > 1 When completing text directly after entering/removing a newline, the Diagnostics ranges received by eglot > are out of date and "one line off". > 2 Some of these off-by-one-line diagnostic message ranges now land on blank lines in the file, so the > effective range there is empty. > 3 Seeing an empty range, eglot declares the server has "botched" it, so it tries to make a by-hand > recalculation of the range using `flymake-diag-region'. > 4 `flymake-diag-region' for some reason calls (end-of-thing 'sexp) and (end-of-thing 'symbol). > 5 In some positions in a long python file these commands are VERY SLOW. Rather than the typical call time > of ~1ms, at these certain positions `flymake-diag-region' takes ~400ms. > > It doesn't take too many "botched eglot ranges" interacting with slow `thingatpt' misbehavior to add up to a > 10s delay. > > I'm not certain of the best solution. A few ideas, from hardest to easiest: > > Teach eglot textDocument/diagnostic > ++++++++++++++++++++++++++++ > > textDocument/publishDiagnostics messages arrive way too frequently IMO, after every buffer change of any > kind. They are pushed to eglot from the LSP server, and if they contain hundreds of errors, this becomes > very inefficient (re-painting with flymake the same hundreds of regions over and over after each keystroke). > > The best solution here would probably be to adopt "pull" diagnostics using textDocument/diagnostic, perhaps > in an idle-timer whose duration the user can configure. I don't believe EGLOT can do diagnostic pulls at the > moment. > > Don't use thingatpt in `flymake-diag-region' > +++++++++++++++++++++++++++++++++ > > `flymake-diag-region' should perhaps not use thingapt, which is subject to the performance vagaries of the > major-mode and underlying file. I am uncertain why it relies on that. Perhaps the performance of those will be > improved with treesitter variants. > > Eglot could detect off-by-one diagnostics > +++++++++++++++++++++++++++++++ > > Hard to know the best heuristic, but lots of null effective ranges is a good one. > > Eglot can simply ignore null range diagnostics > +++++++++++++++++++++++++++++++++++ > > Eglot doesn't need to use `flymake-diag-region' to try to calculate an update range if it encounters a null > diagnostic range. It could simply drop those, as they are probably wrong anyway, and will shortly be updated. Adding João and Spencer to the discussion. From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 07 11:59:52 2025 Received: (at 77588) by debbugs.gnu.org; 7 Apr 2025 15:59:52 +0000 Received: from localhost ([127.0.0.1]:56443 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u1ot5-0001VO-KV for submit@debbugs.gnu.org; Mon, 07 Apr 2025 11:59:52 -0400 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]:51285) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u1ot3-0001Uq-Fw for 77588@debbugs.gnu.org; Mon, 07 Apr 2025 11:59:50 -0400 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-3913b539aabso2656583f8f.2 for <77588@debbugs.gnu.org>; Mon, 07 Apr 2025 08:59:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744041583; x=1744646383; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=4Y1o7i4WhMHjpwrtedkmEzikdDtCfDo+4ACjsfsc7ow=; b=YirhRxIu0CAsvQJZfch3TVA/zPCN5EoGZLoJr086wOp0ZcRw5i2+TnboLQ04rCfdrT SiBoa7JhNsNmF6wUNP5iJnC030fg8+1Z1NF3Bw8lqIHnh1jRG8SRJ//D/472Ky4PX07a o9v9QTwM9bdZ9WN5JcUw9zTrSipzSzmtNGo4h+tb1DyWo56sVDx4dKhfqmGfz7FkV2Up 0YZPZ58mYr6lguD/9ZObhm1J4jN1f0BqZpjx5QMVtYXPK7pu7Y6xeVgO9CgA5tlahLdy ru+PgUHB5LSFSP4Ig5aM9qpDIY1ONqTK+3I9IJLCV1wpvMdWCozn7422X+l9jlcG9vEl kxkw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744041583; x=1744646383; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=4Y1o7i4WhMHjpwrtedkmEzikdDtCfDo+4ACjsfsc7ow=; b=SMq7cFQ5H76E9CRz5NEPx5v2WxEOXBHZVVRiOuK/6qV6zf9THFGqYERv3lG3Tfovsf K2v6CsZ5T9aU1wHg0oafQIs2poTDBTqxEK5GL6aG+tL5UOGoGMlVSz06a94QNb0TgIkR 2FKEqUqngQzMBYmKWHCQHL80wFEoHxVPFXcsCLzOop0y8/zRRU4XzL1zJcwgufknila2 UfqvkoAzFQ6Ms9hrZJpdPavYbFI+yFGHWh+LY/7VoU/ADuctvZbSbOw1LwDuxpvbLE2G XeRU8nRiCvJB/CFmaFAU2PtK+bXtsLoDeFoZGUd32CR2AH8ar4etK9nv1nSvtWhZjn1Y Ie0w== X-Forwarded-Encrypted: i=1; AJvYcCXSz6dzPA+uGcHRdSCuGxIPwL5TL5uHvMfhKEyfsn09XwFWp/23hJEAOHsCgt3H27RE88DKZQ==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yzj1Id3C3NTqYdQ5SDvO23rKTjbhmJ5ht0np99xi8/LOC/WqCNq fiICSZTFOph8NuTTTrrkhQ4c8f0qjEwe3Fyw36r5PHGuxhX2V4UuHO7bGA== X-Gm-Gg: ASbGnct5nyllokPiOHl3Q1B7BC4rCZtiwvIGP9Xr4ZAe4XRG0ztHa9k+Jiyhq1HmSWT lYQk98Irq6xKnlN5u9mAS3ULCj8aFRvTAniL87h2Sr5i995UdyOf0aihUPFNHps2mjFGhOOP67J GSEm9xaqDjVgTAOjuSSDseMGdGosWEB5irxFbAjh08gE57h+t7pbIakpBtd+oDAEaG/0+PrSdJR dhh0rJHtTd8MQdV/0+F9CD/rqtOrbwy6pSZRn9D1CP57+qhbURGyPngCNkGL5TrD75uAz0ValgM EfpWj8GUc20QO/kGqjEbjns2K0JAcs+vCuVH7Vk8XQdP96S7IuIgTVwu+YTtOA== X-Google-Smtp-Source: AGHT+IF3Wo16hEAawy39wh2Om9e5r0mhuWPzkdxm1rbN/h4tp/q25oZojTaGkJt9zLsXundXmvLJZw== X-Received: by 2002:a5d:5c84:0:b0:391:4559:8761 with SMTP id ffacd0b85a97d-39cba9333a6mr11101276f8f.36.1744041582601; Mon, 07 Apr 2025 08:59:42 -0700 (PDT) Received: from krug (87-196-75-121.net.novis.pt. [87.196.75.121]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43ec34af0e6sm135991775e9.16.2025.04.07.08.59.40 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 07 Apr 2025 08:59:42 -0700 (PDT) From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= To: Eli Zaretskii Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' In-Reply-To: <86v7rgtdx9.fsf@gnu.org> References: <86v7rgtdx9.fsf@gnu.org> Date: Mon, 07 Apr 2025 17:00:13 +0100 Message-ID: <87wmbw7yia.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , 77588@debbugs.gnu.org, JD Smith X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) Eli Zaretskii writes: >> It doesn't take too many "botched eglot ranges" interacting with slow >> `thingatpt' misbehavior to add up to a 10s delay. ACK. =20 >> I'm not certain of the best solution. A few ideas, from hardest to easi= est: >>=20 >> Teach eglot textDocument/diagnostic >> ++++++++++++++++++++++++++++ >>=20 >> textDocument/publishDiagnostics messages arrive way too frequently IMO,= after every buffer change of any >> kind. They are pushed to eglot from the LSP server, and if they contain= hundreds of errors, this becomes >> very inefficient (re-painting with flymake the same hundreds of regions = over and over after each keystroke). >>=20 >> The best solution here would probably be to adopt "pull" diagnostics usi= ng textDocument/diagnostic, perhaps >> in an idle-timer whose duration the user can configure. I don't believe= EGLOT can do diagnostic pulls at the >> moment. You're right it can't. A patch that implements without much code repetition and keeps support for the "push" diagnostics model is welcome. Would you like to work on it, JD? As far as I understand, this model is much more complicated and allows you to pull diagnostics for individual LSP documents or the whole project. One of the difficulties I envison is to do it in a way that maintains support for project-wide diagnostics. But its certainly not impossible and would be a wonderful addition, fixing many problems such as https://github.com/joaotavora/eglot/issues/1296. >>=20 >> Don't use thingatpt in `flymake-diag-region' >> +++++++++++++++++++++++++++++++++ >>=20 >> `flymake-diag-region' should perhaps not use thingapt, which is >> subject to the performance vagaries of the major-mode and underlying >> file. I am uncertain why it relies on that. Perhaps the performance >> of those will be improved with treesitter variants. When a Flymake backend passes on to Flymake a 0-dimensional point in a file you still want Flymake to create a diagnostic emcompassing a 1-dimensional span of buffer positions. thingatpt.el is, AFAICT, the standard Emacs's way to move from the 0 dimension to the 1 dimension space. It needs, quite understandibly, help from the major mode to do that job. If that help comes at a dog slow pace, I think that's a problem in itself. It takes around 10~20 microsseconds on my machine in Emacs Lisp mode as measured by: (/ (car (benchmark-run 10000 (thing-at-point 'sexp))) 10000) Even less in c++-ts-mode, around 4 microsseconds. So if python-mode is taking around a hundred thousand times (!) more to compute that piece of information for some buffer positions, I'd say it's definitely something to look at... >From a quick check it seems indeed that the time it takes to compute it is proportional to the value of point the buffer. Suggest creating a bug for python-mode, or calling in whoever wrote that part. =20 >> Eglot could detect off-by-one diagnostics >> +++++++++++++++++++++++++++++++ >>=20 >> Hard to know the best heuristic, but lots of null effective ranges is >> a good one. >>=20 >> Eglot can simply ignore null range diagnostics >> +++++++++++++++++++++++++++++++++++ >>=20 >> Eglot doesn't need to use `flymake-diag-region' to try to calculate an u= pdate range if it encounters a null >> diagnostic range. It could simply drop those, as they are probably wron= g anyway, and will shortly be updated. Maybe, IF we can confidently say that the server is in the wrong.=20 But I added it there for a reason, and quite a long time ago. See the commit log for commit 7826b265a0ecd9357719b2fb9491c9bcb517d4cc Author: Jo=C3=A3o T=C3=A1vora Date: Thu Jun 21 23:32:14 2018 +0100 I'm moderately sure someone somewhere expects the botches ranges to be auto-corrected by Eglot (though admittedly not at the expense of large delays). Jo=C3=A3o From debbugs-submit-bounces@debbugs.gnu.org Mon Apr 07 17:42:18 2025 Received: (at 77588) by debbugs.gnu.org; 7 Apr 2025 21:42:18 +0000 Received: from localhost ([127.0.0.1]:57296 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u1uES-00030N-H1 for submit@debbugs.gnu.org; Mon, 07 Apr 2025 17:42:18 -0400 Received: from mail-yb1-xb2a.google.com ([2607:f8b0:4864:20::b2a]:52724) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u1uEO-0002zq-VN for 77588@debbugs.gnu.org; Mon, 07 Apr 2025 17:42:14 -0400 Received: by mail-yb1-xb2a.google.com with SMTP id 3f1490d57ef6-e3978c00a5aso3860031276.1 for <77588@debbugs.gnu.org>; Mon, 07 Apr 2025 14:42:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744062127; x=1744666927; darn=debbugs.gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=uQ/ozv0shzWiPpUQl5PMYgWVc55s7YdvoKfqrtAWNPc=; b=QkI+bMlPcJi+DwLaX91RyCvGq16i45QE9b0vc3jj60FrxhAIMuPKRQPKBgjbF2Vrqe N885PHVQPbQZT44gHw5E2E4fV0RuJk3DXGnmIrrRlsKQHFZq+QM3Y7u4xAzjMZX9OKzy n7WfOtQZwPj0Vagn1d+Yn94GJ/ouKg1fsA8vfbFjGoKzUx3U8jL7sY9hKvE5e/d1lYoC QoZ1VGGkH15QX3/036/tyxIyiar9r7fci2vTOoA+yQVqYe5oOCjRdD0IWTHb8wrq+qOY 4O+XMI0mGV1VT+7cmFAzNoBOQqDCbYJ48WxLabQX8gEEiBi3pdYOP4KKkV41I+dOMjIY ftcQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744062127; x=1744666927; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=uQ/ozv0shzWiPpUQl5PMYgWVc55s7YdvoKfqrtAWNPc=; b=D777mF6IYJf4EMPV1UoNSb7FjblNJQ2mEdw+lhyc95k6Q6G5F9vaoD5PnZGEtaia3g Pnc2W85aH6q6nEdpCTLYtcL/IiHao1GiYy/AOEVgl47afZd/NpR04INXUrqGfoMbL5SV eWK//iWxBX+DKGbQhHzMUF52WJWM0mW4bqTibycKEoOe/aVVpDIDtJ3i25ARCG0T1qLx NE3KGRcMy1w1VRSctz/j+Uemq7w5GhstoAHLlcHkiLxdo85zc+jGSGXn3mn4SLr07iWl BTDLuLHQfYKWUJepC2Isqj+GRMlGblhug1kk7cXT1Vsnp/ve8mcosxFj5i22uNo/IyIJ wnMA== X-Forwarded-Encrypted: i=1; AJvYcCWenX13rSKe71HXA67pjTdfE9FeTDRKf66AeAXrLuxAMMX+s95VKd6okIVUNJVZSol27b9sDA==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yy+anFy9HdUTEdkVDP5Eld4dz9Vj7F8d3a2lfT9qOqzPPdzaLD0 BI/Y971LK9Ihp53I2EEjI4QJ41XzaQUmyg1PghxkqXZleq+C6f6w X-Gm-Gg: ASbGncveH1rchg9nqDSMvQl+BBJ2yr9REG7CEfGDiLakqNtHhsuhFXe7eeZTW1oRga7 5i56+MRom0QX3uXZFJLmqtnrJQp0/H0eXea0BX53ROJ6TleR9mfLIvFxDOm+/Mm+27jxJkm07+n vg9/m7EYqznhNLvfq8IhRr4uaBbwk8EojZH0wpdwzCTpfrUCUo1E3tm8qsG8a9Yqyo+q/PvLnGS YNLroHSKJqKGQHpTt2pHoJidx7/6BJYGeWRCCo97RrLHzwS2q+1/Cq5cQV9baFf70l0t2l3Yh6v Xj9lCo0C6wt66oIAxSirlbrbTbCuLlbJB222RgXUJAG+SLatBvB6uZ4zftFIMw== X-Google-Smtp-Source: AGHT+IEWoPk7XBE7Lpc/cJTTrNLomYWMnDS+KRNAIGJUYArmWplJjHN7uzbY9ktdV36ALi4KpDVtUQ== X-Received: by 2002:a05:6902:168e:b0:e6d:f6a6:be02 with SMTP id 3f1490d57ef6-e6e1c3d2b0dmr25041125276.33.1744062126930; Mon, 07 Apr 2025 14:42:06 -0700 (PDT) Received: from smtpclient.apple ([131.183.188.117]) by smtp.gmail.com with ESMTPSA id 3f1490d57ef6-e6e0cacded5sm2452251276.53.2025.04.07.14.42.06 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 07 Apr 2025 14:42:06 -0700 (PDT) From: JD Smith Message-Id: <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_7F7BDA75-D954-4190-B871-D4FA93AE8E6D" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.400.131.1.6\)) Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' Date: Mon, 7 Apr 2025 17:41:55 -0400 In-Reply-To: <87wmbw7yia.fsf@gmail.com> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> X-Mailer: Apple Mail (2.3826.400.131.1.6) X-Spam-Score: 0.7 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.3 (/) --Apple-Mail=_7F7BDA75-D954-4190-B871-D4FA93AE8E6D Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Apr 7, 2025, at 12:00=E2=80=AFPM, Jo=C3=A3o T=C3=A1vora = wrote: >=20 > Eli Zaretskii writes: >=20 >>> It doesn't take too many "botched eglot ranges" interacting with = slow >>> `thingatpt' misbehavior to add up to a 10s delay. >=20 > ACK. >=20 >>> I'm not certain of the best solution. A few ideas, from hardest to = easiest: >>>=20 >>> Teach eglot textDocument/diagnostic >>> ++++++++++++++++++++++++++++ >>>=20 >>> textDocument/publishDiagnostics messages arrive way too frequently = IMO, after every buffer change of any >>> kind. They are pushed to eglot from the LSP server, and if they = contain hundreds of errors, this becomes >>> very inefficient (re-painting with flymake the same hundreds of = regions over and over after each keystroke). >>>=20 >>> The best solution here would probably be to adopt "pull" diagnostics = using textDocument/diagnostic, perhaps >>> in an idle-timer whose duration the user can configure. I don't = believe EGLOT can do diagnostic pulls at the >>> moment. >=20 > You're right it can't. A patch that implements without much code > repetition and keeps support for the "push" diagnostics model is > welcome. Would you like to work on it, JD? >=20 > As far as I understand, this model is much more complicated and allows > you to pull diagnostics for individual LSP documents or the whole > project. One of the difficulties I envison is to do it in a way that > maintains support for project-wide diagnostics. >=20 > But its certainly not impossible and would be a wonderful addition, > fixing many problems such as > https://github.com/joaotavora/eglot/issues/1296. I agree diagnostics pull would be a great addition. I know neovim added = support over a year ago[1]. That said, I don't know much about how this = has been implemented in other clients, and there are many questions:=20 When is the appropriate time to pull? Should pull be done in idle time? Driven by flymake? When should you ask for the full project's diagnostics vs. just the = current buffer? Always? Should diagnostics be versioned (likely)? As well, my familiarity with eglot/jsonrpc's internal structure and comm = model is rudimentary at best. I'd be happy to help with logic and = provide deep testing, but I'm afraid it's not something I could tackle = alone. >>> Don't use thingatpt in `flymake-diag-region' >>> +++++++++++++++++++++++++++++++++ >>>=20 >>> `flymake-diag-region' should perhaps not use thingapt, which is >>> subject to the performance vagaries of the major-mode and underlying >>> file. I am uncertain why it relies on that. Perhaps the = performance >>> of those will be improved with treesitter variants. >=20 > When a Flymake backend passes on to Flymake a 0-dimensional point in a > file you still want Flymake to create a diagnostic emcompassing a > 1-dimensional span of buffer positions. > thingatpt.el is, AFAICT, the standard Emacs's way to move from the 0 > dimension to the 1 dimension space. It needs, quite understandibly, > help from the major mode to do that job. That's a good way to put it. The situation here is a bit more subtle. = The LSP server provides a valid range, such as: (:start (:line 5272 :character 48) :end (:line 5272 :character 61)) but it is out of date compared to the current state of the buffer. = Since in some instances the range points at a blank line or similar bad = location, eglot collapses it down to dimension 0, then asks flymake for = help to expand it back to 1d. > If that help comes at a dog slow pace, I think that's a problem in > itself. >=20 > It takes around 10~20 microsseconds on my machine in Emacs Lisp mode = as > measured by: >=20 > (/ (car (benchmark-run 10000 (thing-at-point 'sexp))) 10000) >=20 > Even less in c++-ts-mode, around 4 microsseconds. At a randomly selected position at around line 8200 in a python-ts-mode = file, I get 19ms. After a few tries on subsequent lines, I found a = position that takes 583ms for the same (had to drop to 10 iterations). =20= In case people want to play along, try Jo=C3=A3o's test at the start of = L8817 in this file (no eglot needed; either python-mode or = python-ts-mode is fine, as both show the same issue): = https://raw.githubusercontent.com/matplotlib/matplotlib/refs/heads/main/li= b/matplotlib/axes/_axes.py=EF=BF=BC _axes Text Document =C2=B7 353 KB I will open a separate bug for that. > So if python-mode is taking around a hundred thousand times (!) more = to > compute that piece of information for some buffer positions, I'd say > it's definitely something to look at... >=20 > =46rom a quick check it seems indeed that the time it takes to compute = it > is proportional to the value of point the buffer. Suggest creating a > bug for python-mode, or calling in whoever wrote that part. I agree it's suboptimal for python-mode to be so (intermittently) slow = at computing end-of-thing. It's certainly an issue worth solving, but = not the main issue IMO. =20 The main issue is that eglot is trying to "correct" a region using data = which is already outdated, and therefore not likely to result in = anything useful, however hard flymake tries. >>> Eglot could detect off-by-one diagnostics >>> +++++++++++++++++++++++++++++++ >>>=20 >>> Hard to know the best heuristic, but lots of null effective ranges = is >>> a good one. >>>=20 >>> Eglot can simply ignore null range diagnostics >>> +++++++++++++++++++++++++++++++++++ >>>=20 >>> Eglot doesn't need to use `flymake-diag-region' to try to calculate = an update range if it encounters a null >>> diagnostic range. It could simply drop those, as they are probably = wrong anyway, and will shortly be updated. >=20 > Maybe, IF we can confidently say that the server is in the wrong.=20 >=20 > But I added it there for a reason, and quite a long time ago. See the > commit log for >=20 > commit 7826b265a0ecd9357719b2fb9491c9bcb517d4cc > Author: Jo=C3=A3o T=C3=A1vora > Date: Thu Jun 21 23:32:14 2018 +0100 >=20 > I'm moderately sure someone somewhere expects the botches ranges to be > auto-corrected by Eglot (though admittedly not at the expense of large > delays). It appears from that commit message that the issue is rather that = certain servers send null ranges up front. One middle ground here would = then be to attempt to correct ranges only if they start out null from = the server, not if they are collapsed that way by eglot. Implementing = this makes performance not that great, but predictable: no 10s pauses. Another much better option I just discovered: avoid applying out-of-date = diagnostics in the first place. After taking another look, I noticed = that since LSP spec v3.15 (v3.17 current), = textDocument/publishDiagnostics includes: /** * Optional the version number of the document the diagnostics are = published * for. * * @since 3.15.0 */ version?: integer; It seems eglot keeps track of the "document version" in = `eglot--versioned-identifier'. I believe that can be compared to the = one in the `textDocument/diagnostic' message to avoid this mess = altogether. =20 See attached patch for both of these options rolled together; this has = performance which is now actually quite decent in my long file. It = drops the outdated push diagnostics of my chatty server, which seem to = be about half of them. Not only does this eliminate the "off by one" = catastrophic flymake issue, it improves performance overall = significantly, probably due to less flymake overlay churn. Best, JD [1] https://atlee.ca/posts/pull-diagnostic-support-for-neovim/ =EF=BF=BC= --Apple-Mail=_7F7BDA75-D954-4190-B871-D4FA93AE8E6D Content-Type: multipart/mixed; boundary="Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0" --Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

On Apr 7, 2025, at 12:00=E2=80=AFPM, Jo=C3=A3o = T=C3=A1vora <joaotavora@gmail.com> wrote:

Eli Zaretskii = <eliz@gnu.org> writes:

It doesn't take too many "botched eglot ranges" = interacting with slow
`thingatpt' misbehavior to add up to a 10s = delay.

ACK.

I'm not certain of the best = solution.  A few ideas, from hardest to easiest:

Teach eglot = textDocument/diagnostic
++++++++++++++++++++++++++++

= textDocument/publishDiagnostics messages arrive way too frequently IMO, = after every buffer change of any
kind.  They are pushed to eglot = from the LSP server, and if they contain hundreds of errors, this = becomes
very inefficient (re-painting with flymake the same hundreds = of regions over and over after each keystroke).

The best solution = here would probably be to adopt "pull" diagnostics using = textDocument/diagnostic, perhaps
in an idle-timer whose duration the = user can configure.  I don't believe EGLOT can do diagnostic pulls = at the
moment.

You're right it = can't.  A patch that implements without much code
repetition and = keeps support for the "push" diagnostics model is
welcome. =  Would you like to work on it, JD?

As far as I understand, = this model is much more complicated and allows
you to pull = diagnostics for individual LSP documents or the whole
project. =  One of the difficulties I envison is to do it in a way = that
maintains support for project-wide diagnostics.

But its = certainly not impossible and would be a wonderful addition,
fixing = many problems such = as
https://github.com/joaotavora/eglot/issues/1296.

I agree diagnostics pull would be a great = addition.  I know neovim added support over a year ago[1]. =  That said, I don't know much about how this has been implemented = in other clients, and there are many = questions: 

  • When is the appropriate time to = pull?
  • Should pull be done in idle time?  Driven by = flymake?
  • When should you ask for the full project's diagnostics = vs. just the current buffer?  Always?
  • Should diagnostics be = versioned (likely)?

As well, my = familiarity with eglot/jsonrpc's internal structure and comm model is = rudimentary at best.  I'd be happy to help with logic and provide = deep testing, but I'm afraid it's not something I could tackle = alone.

Don't use thingatpt in = `flymake-diag-region'
+++++++++++++++++++++++++++++++++

`flymake= -diag-region' should perhaps not use thingapt, which is
subject to = the performance vagaries of the major-mode and underlying
file. =  I am uncertain why it relies on that.  Perhaps the = performance
of those will be improved with treesitter = variants.

When a Flymake backend passes = on to Flymake a 0-dimensional point in a
file you still want Flymake = to create a diagnostic emcompassing a
1-dimensional span of buffer = positions.

thingatpt.el is, AFAICT, the standard Emacs's = way to move from the 0
dimension to the 1 dimension space.  It = needs, quite understandibly,
help from the major mode to do that = job.

That's a = good way to put it.  The situation here is a bit more subtle. =  The LSP server provides a valid range, such = as:

(:start (:line 5272 :character 48) :end (:line = 5272 :character 61))

but it = is out of date compared to the current state of the = buffer.  Since in some instances the range points at a blank line = or similar bad location, eglot collapses it down to dimension 0, then = asks flymake for help to expand it back to = 1d.

If= that help comes at a dog slow pace, I think that's a problem = in
itself.

It takes around 10~20 microsseconds on my machine = in Emacs Lisp mode as
measured by:

(/ (car (benchmark-run = 10000 (thing-at-point 'sexp))) 10000)

Even less in c++-ts-mode, = around 4 = microsseconds.

At a = randomly selected position at around line 8200 in a python-ts-mode file, = I get 19ms.  After a few tries on subsequent lines, I found a = position that takes 583ms for the same (had to drop to 10 iterations). =  

In case people want to play along, try = Jo=C3=A3o's test at the start of L8817 in this file (no eglot needed; = either python-mode or python-ts-mode is fine, as both show the same = issue):

= --Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0 Content-Disposition: inline; filename=preview.png Content-Type: image/png; x-unix-mode=0666; name="preview.png" Content-Transfer-Encoding: base64 iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAERlWElmTU0A KgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAAAQKADAAQAAAAB AAAAQAAAAABGUUKwAAAN2ElEQVR4Ae3by69W1RkG8M31cFERFT0gyuGm4i1qookJ4w46aJOmTRx1 1L+io8466KCTDkw66j/QQQcdVNNEB0YGGpV4wQviFRBFBEFRhK7f6nkO69t85zv7g0MnZSX7W/e1 3ud5L2vtfaDrbqQbDNxg4P+ZgRVDwR87dmzj+vXr/3Lp0qXflDnrS76ynVvqbbVbqj4yuFQuXrzo +amkwyX/6/bt2/+8YsWKC/1xy10fTMDXX3/9t5UrV/62AIN0YV4LtC0TdKl6CwYBFy5c6H788cfu /Pnz3c033/zPb7/99ld79+49345b7vKIFicsvqZo49fz/aOqbiaVMU2tsLREfWTwfAUB33//fbdq 1aqfb9y48R/vvffezLhxy9U2lIB1Bcw6m5Z8ZQtMuV9vhWv75ue33Qtl1sIKigt0P/zwAwK6NWvW /Ox6kzCUgJkCZGRsH9gCklLo9y1Vj6v0CSgu161evfq6krC6FXxCeZU+QCJs6m+++WZ3/Pjx7tZb b+22bNnSEXrt2rXdF198UevGvf76693OnTu7O++8s/vkk0+qn/P3u+++u4595513qvZLkO1uu+22 7vPPP+8eeeQRU2sq+4aEXyx3TBjRajYcky84d6tNZNx1110VyB133NHdcsst3YYNGzpAlL/77rtu 06ZN3a5duypQZm1cCXDdunXrmHjNrYE8bdY0xz7Ge66nJSwAGwO6bZo9ffr00bYhllCOx+7w4cNV gwSXaBbIN954oyvzuieeeKI7depUd/LkSSZdgxwrOXPmTAWsDVCESYjYv39/XdM+4kKeYjn/Onv2 7LJZwlAXGGv+fJa2d+zYUYHEOgAA6sEHH6zuoZ2L0OS5c+eqdehHmDYgc/whSlm7ZA/kJJW1ltUd hrpA3T8AIwwhHVknTpyoz/vvv1+FFROef/757oUXXqh+zwo+/fTTCrzcJ2p8YCHlnK/tX375ZY0N 1uIW4oq189i3dYflPB0GW0BAEybmL/fwez6/devWahEE5/cCnUvNTTfdVNtnZma6++67r7Y56rQn Dtx+++21nVsIhPaxTlLfEhoSrskdLu+QnRbJW+2nLGeuH3zwQfVf7nDw4MGuXF5q0BPYXnrppRoj +DzNOhG4CFPPicByWAg/dyIUH68EhITraQmDg2Ax1xoEo3080Yrnm2++qQIDSXhAgExgkyOHdhFG wxIXkLiFOeYjxRrPPPNMta5YWfaSa0tQlF9LYLwmF6Ah4AIIGO7QJmaehISWQC6hLhjyf1ahzHVo HdikSe5Q5LjqwDg1AQQCnOByR5vjS5RHBuElvk3bQIj4xsj1sw6JpstVt/q+0yHWYxzNtqCNb+vW tV/S1caEqyLApiEBoA8//LAC3b17d5Xnq6++6u65557q10i4//77KzjtCHvooYeqxmP2R44cqQQ5 PRDCisSOp556qmMlQy2hEMcS/l6U88si36BX6aljQBiXswL+K9KL6o422uPbLEKfFNPXDqCxND47 O1s1LQAilGUgwXrGGqfNmtoQwaWsQfssQs7aPGIIwsp+vy/fE/5YN1/i56otwLqEdgf4+OOPK8i5 ubm6nfoDDzxQwQAKCAEJu2fPnkqckwOBufsD6gbJDbiLHGhEAv7ZZ5/Va7fjEgHA5+mTUdb9XRHk T+VZ0gqu2QIIB6BEEKQwbUmZi7QERGjtCFC3hnpywNUTB4zjSkgynpat7VFPWT6/70/lTuJefrY2 TPgZbAEWJ0g/Ac3EpfQz2dRpPi5QG+d/tEtAKptjPhIAVc5681MWgGpvwNbu1OfHio4z5Vk+Aizc J0HdNZa/etVFhkDHF/mqY42w2gF1W2Ta7gPmxpyd/TkSadRYGmf+cSFW4a3RfEcmC7Fn/9gl53z6 L8OpLZIPtoDMb0mIhrwR0ppXXbc6JwBAvgnQaB5BEhniRtyCP7tISYAjc/PmzfUtEpHigTaAXbXN 970AEeayLjKNSWMb++MGDSqTZsuG9SaYBYD30LKXHYmWSvStwh09erQKS0s0+dFHH9V65gFHyzQu sRjrWE/bzvIBBYmCH/A0jSDWg2AEOlLtF5erC83/FGVsLcVjbdu48lTvAi3Tyh5CAEdTHsITDjh1 ZQISXJk2lT3AGsekJdo1n0UYx3IQiViu4FHWzgK4WwgcB25I2zW5gA2YK4ES7LjDtm3bahvNIYiZ PvbYY90rr7xSNU2bBM9lCUFcCGFxJe7iOGXm2iTaRo6Y4RtE9qGIuGMdOMXPYAto12wtwcbqNBnN yIESA4BChKRNPS4T7bEAfdppmHb1CZo5LbiC9lhXrCayJG/lHFIebAE2aFlOneAA53Lidudmx8ef fPLJWgaEZcilmLp5ytZ499136xWZWXslTjtLQJrPaoInksSURP8WeGQaAjxjBhNgQn8DdRphloRi 6gluyAJQ37333lv3A9LRR7sAGE+T/D0xQ65unqAnIYCrsQZxgFu1rjFOMXXigJ/Bp0ARYuEUaDd0 d6c1GpMQ4rqrPdryTgDw3NzcSNACMG5gLldRj1bbfZAppa8/tx1rXCF60CkwlQVYWGotgcZEdATQ Jh8W3AhoHG2KBSxEn4AGjD6PcoQHXjlglT3GpS9Woa1N6lmnbV+qPLrK4qNnC7ij/Q0CJNOilf64 9Ld5O6YtGzOpPqmvnTvUAqY6Bfqs00oivM1ZQUhpxxKapbSp7W/L7ZiU2/62rH+petZYLJ/aBWzY aoGvu/4Kfj50IMQHEqYuHiDFhxLW8eqrr9a6QOhe//bbb1dirCmoCXbcR8B76623at3Joc3rMxey T/nzWI0pkaMvU5+UxcBrn5oAk7IhARxTojzh1AU7d3Z1UTunA8twLXaWu/a65gKHGLEDaCSYY30E IUSZpek3zhzHZj9Fpn77UvUrV1pkRn8DdUmkd111pEmut3kPyAuRN8ad5W4PhIBImyzFzY610Koz HoHGSNZAGoIlRHlYnFNFcEWojygIkvoy1sYlfgYTsNgGBCQIHycAIrQRiqac27kf6J8rR2HOcYCB N5ZV5ETxZdgfUBCnzTrWiJUh1loB3mKcloSpCOiTYDMW4PWU6dMYE/cwX5/FmKw/hgALhFuiJB48 +uijlTx/SDEXaHHj5Zdfri7CSqzrjy379u2r3xDr5Pkfaya1ZXINTVMTYOGwbFO+KjFLddry+NYn pyUvLfF5MQE5fN0DON83F2DaN16Zxq2RfvtyAykgzVOOTLVzip+hVM0WzSx5DyBMm9QjoHbCx2z7 YzMPIca0/W3ZuEn19JVYMugmONU9IEImJ6jInBSt0BwNRjO5A+S6nD5g+ykEmYuwjM04ALNP2tp6 W07/pHwqF8jiYdnC/uApsvscxg2efvrpmnvxYfYPP/xwrXsbNI+fA+X9gTuID94agfX+L+XuYL54 YLw7hngj+rt6uwsIvklki1yRM32T8qlcoF3IZh4CAQOAIAcUAN7mHIn+QszXjZEboz/+DYxACaQT g88LhNoQALSYIaYYYz/9wFsroCNb6kWO6+8CNgXUP5EBTsQ+cOBAfbcnHNN3zvsSBJgjj8ZpyFcd 4Bx//jHFa6+9Vi3JGMDdElmXcYgE7MiRI7Vdv/Wlvrb79Tpows9gCyhgrgiChEKAcz1/IVYHwlXY cWhMNJ5ojgwXH3NYgnHIQ1jAuQOwAm2xCOPEDSeFtVqw0XywljHLbwHthjZSZ8K0zP8JSjNy/0DK x1KWgYB8G3QP4OsI0u5WiAjz3CfMRRCXkUsshSXo1+7ewB3a1Jet7ZtUnsoCslDYlgNOKFqRAKBF fgsUoLSYI5AGCW+uPhbDDViNtbQ5CcQDayLYePONQ6g660BgZOnLNtQCpjoFsgm2bSwHgHbUBbxD hw7VYTvL3V9yTBLeGyMTFr0J73YHtPcBGmbSyOHn2iXjnDBZw7860yblCI0stbH89OtpXyy/KgvI YoSgfZGZ1mkEWALzaXUBLO8KgLIQr7fmsBKvxuZ4tEk0TfOIECM8XpLsgUTrsg5gk/qWUIgaFAMG W8A4ZpkqAvh3BAISMbQFFI16PY4FAEGLAOqPtrWzHm93fF9csT73kRDFGnwxdud4/PHHR7Q9Tr6Q Mym/TOGkUeVPY8Xv6kfRlmllgGnZG2D801J8GBHiABBcRRlgdwV1mjTHK258Xx05LMg4awCHjMQO ZSTJpVam1JfdAupO5adlWtlxJeL7x80AaQPSuU6rIjyzVQaM2XuzczM0DnGsQ78HAYDRcgjNnkAH rLak9Kc+TX55lcmzFiwgwwjiiVa0E8STNkBosNUUs5eAM5Z1AKbdYzwizAnYOqH89OtpT972F2KX NwaUTby5LLw8hfWAI0TagANEaoHojxYJ61GPmStnDX3KUoClrzaO+Wn6r3zLGjNe0+AgWMaeL4// LHWxbFSJAC5CWiyJwC0xAZB+edvGddp6v78BtkBQu1bKZY0qW8nJOigtaHSJ0ZdKUHuOIOUZcZte tS7Tb1Mf19buOU1/f2zWKe1VthJznittox8nMqiXX/6Xhr2OXnV9Mc+D5U/cO0q03l4YXpXNjBsn 0Li23ppXzOvPmVTv9xWZAD5fTqR/P/vss3948cUXT5b6uf6e/fqINvudTd2n2S3l8f1rY3mGEleG /k+TCOsfRh0vz4nynCnPxDQ0Bvjsc2p+Jf8YOAQMJXCiEMvQGXNHAK2T9fKnqgkbTAPAv7ryTzVm yoOAaeaW4dc9IQEBAiDwo3+LKw030hgG/gMjlCnyydKoaAAAAABJRU5ErkJggg== --Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0 Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8

I will open a separate bug = for that.

So if = python-mode is taking around a hundred thousand times (!) more = to
compute that piece of information for some buffer positions, I'd = say
it's definitely something to look at...

=46rom a quick = check it seems indeed that the time it takes to compute it
is = proportional to the value of point the buffer.  Suggest creating = a
bug for python-mode, or calling in whoever wrote that = part.

I agree it's = suboptimal for python-mode to be so (intermittently) slow at computing = end-of-thing.  It's certainly an issue worth solving, but not the = main issue IMO.  

The main issue is that = eglot is trying to "correct" a region using data which is already = outdated, and therefore not likely to result in anything useful, however = hard flymake tries.

Eglot could detect off-by-one = diagnostics
+++++++++++++++++++++++++++++++

Hard to know the = best heuristic, but lots of null effective ranges is
a good = one.

Eglot can simply ignore null range = diagnostics
+++++++++++++++++++++++++++++++++++

Eglot doesn't = need to use `flymake-diag-region' to try to calculate an update range if = it encounters a null
diagnostic range.  It could simply drop = those, as they are probably wrong anyway, and will shortly be = updated.

Maybe, IF we can confidently = say that the server is in the wrong.

But I added it there for a = reason, and quite a long time ago. See the
commit log = for

commit 7826b265a0ecd9357719b2fb9491c9bcb517d4cc
Author: = Jo=C3=A3o T=C3=A1vora <joaotavora@gmail.com>
Date: =   Thu Jun 21 23:32:14 2018 +0100

I'm moderately sure = someone somewhere expects the botches ranges to be
auto-corrected by = Eglot (though admittedly not at the expense of = large
delays).

It= appears from that commit message that the issue is rather that certain = servers send null ranges up front.  One middle ground here would = then be to attempt to correct ranges only if they start out null = from the server, not if they are collapsed that way by eglot. =  Implementing this makes performance not that great, but = predictable: no 10s pauses.

Another much better = option I just discovered: avoid applying out-of-date diagnostics in = the first place.  After taking another look, I noticed that = since LSP spec v3.15 (v3.17 current), textDocument/publishDiagnostics = includes:

/**
 * = Optional the version number of the document the diagnostics are = published
 * = for.
 *
 * @since = 3.15.0
 */
version?: integer;

It seems eglot = keeps track of the "document version" in `eglot--versioned-identifier'. =  I believe that can be compared to the one in the = `textDocument/diagnostic' message to avoid this mess altogether. =  

See attached patch for both of these options rolled together; this = has performance which is now actually quite decent in my = long file.  It drops the outdated push diagnostics of my chatty = server, which seem to be about half of them.  Not only does this = eliminate the "off by one" catastrophic flymake issue, it improves = performance overall significantly, probably due to less flymake = overlay = churn.

Best,
JD
<= br>
[1] https:= //atlee.ca/posts/pull-diagnostic-support-for-neovim/
= --Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0 Content-Disposition: attachment; filename=null-ranges-only-use-version.patch Content-Type: application/octet-stream; x-unix-mode=0644; name="null-ranges-only-use-version.patch" Content-Transfer-Encoding: 7bit diff -u /var/folders/by/19mt78cj63v5_tslqh826g7w0000gn/T/jka-comE4qbay /var/folders/by/19mt78cj63v5_tslqh826g7w0000gn/T/buffer-content-RmDvVc --- /var/folders/by/19mt78cj63v5_tslqh826g7w0000gn/T/jka-comE4qbay 2025-04-07 17:14:54 +++ /var/folders/by/19mt78cj63v5_tslqh826g7w0000gn/T/buffer-content-RmDvVc 2025-04-07 17:14:54 @@ -1139,6 +1139,14 @@ (beg (eglot--lsp-position-to-point st markers)) (end (eglot--lsp-position-to-point (plist-get range :end) markers))) (cons beg end))) + +(defun eglot--range-null-p (range) + "Return non-nil if RANGE is a null range (spanning no characters)." + (let ((start (plist-get range :start)) + (end (plist-get range :end))) + (and start end + (eq (plist-get start :line) (plist-get end :line)) + (eq (plist-get start :character) (plist-get end :character))))) (defun eglot-server-capable (&rest feats) "Determine if current server is capable of FEATS." @@ -2426,7 +2434,7 @@ expensive cached value of `file-truename'.") (cl-defmethod eglot-handle-notification - (server (_method (eql textDocument/publishDiagnostics)) &key uri diagnostics + (server (_method (eql textDocument/publishDiagnostics)) &key uri version diagnostics &allow-other-keys) ; FIXME: doesn't respect `eglot-strict-mode' "Handle notification publishDiagnostics." (cl-flet ((eglot--diag-type (sev) @@ -2447,51 +2455,53 @@ (if-let* ((path (expand-file-name (eglot-uri-to-path uri))) (buffer (find-it path))) (with-current-buffer buffer - (cl-loop - initially - (setq flymake-list-only-diagnostics - (assoc-delete-all path flymake-list-only-diagnostics)) - for diag-spec across diagnostics - collect (eglot--dbind ((Diagnostic) range code message severity source tags) - diag-spec - (setq message (mess source code message)) - (pcase-let - ((`(,beg . ,end) (eglot-range-region range))) - ;; Fallback to `flymake-diag-region' if server - ;; botched the range - (when (= beg end) - (if-let* ((st (plist-get range :start)) - (diag-region - (flymake-diag-region - (current-buffer) (1+ (plist-get st :line)) - (plist-get st :character)))) - (setq beg (car diag-region) end (cdr diag-region)) - (eglot--widening - (goto-char (point-min)) - (setq beg - (eglot--bol - (1+ (plist-get (plist-get range :start) :line)))) - (setq end - (line-end-position - (1+ (plist-get (plist-get range :end) :line))))))) - (eglot--make-diag - (current-buffer) beg end - (eglot--diag-type severity) - message `((eglot-lsp-diag . ,diag-spec)) - (when-let ((faces - (cl-loop for tag across tags - when (alist-get tag eglot--tag-faces) - collect it))) - `((face . ,faces)))))) - into diags - finally (cond ((and - ;; only add to current report if Flymake - ;; starts on idle-timer (github#958) - (not (null flymake-no-changes-timeout)) - eglot--current-flymake-report-fn) - (eglot--report-to-flymake diags)) - (t - (setq eglot--diagnostics diags))))) + (unless (and version (/= version eglot--versioned-identifier)) + (cl-loop + initially + (setq flymake-list-only-diagnostics + (assoc-delete-all path flymake-list-only-diagnostics)) + for diag-spec across diagnostics + collect (eglot--dbind ((Diagnostic) range code message severity source tags) + diag-spec + (setq message (mess source code message)) + (pcase-let + ((`(,beg . ,end) (eglot-range-region range))) + ;; Fallback to `flymake-diag-region' if server + ;; sent a null range + (when (eglot--range-null-p range) + (if-let* ((st (plist-get range :start)) + (diag-region + (flymake-diag-region + (current-buffer) (1+ (plist-get st :line)) + (plist-get st :character)))) + (setq beg (car diag-region) end (cdr diag-region)) + (eglot--widening + (goto-char (point-min)) + (setq beg + (eglot--bol + (1+ (plist-get (plist-get range :start) :line)))) + (setq end + (line-end-position + (1+ (plist-get (plist-get range :end) :line))))))) + (unless (= beg end) + (eglot--make-diag + (current-buffer) beg end + (eglot--diag-type severity) + message `((eglot-lsp-diag . ,diag-spec)) + (when-let ((faces + (cl-loop for tag across tags + when (alist-get tag eglot--tag-faces) + collect it))) + `((face . ,faces))))))) + into diags + finally (cond ((and + ;; only add to current report if Flymake + ;; starts on idle-timer (github#958) + (not (null flymake-no-changes-timeout)) + eglot--current-flymake-report-fn) + (eglot--report-to-flymake diags)) + (t + (setq eglot--diagnostics diags)))))) (cl-loop for diag-spec across diagnostics collect (eglot--dbind ((Diagnostic) code range message severity source) diag-spec Diff finished. Mon Apr 7 17:14:54 2025 --Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0 Content-Transfer-Encoding: 7bit Content-Type: text/html; charset=us-ascii
--Apple-Mail=_39E789CF-09A6-4448-B31B-EF08C4CE59A0-- --Apple-Mail=_7F7BDA75-D954-4190-B871-D4FA93AE8E6D-- From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 04:00:36 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 08:00:37 +0000 Received: from localhost ([127.0.0.1]:58833 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u23sq-0002bs-Cu for submit@debbugs.gnu.org; Tue, 08 Apr 2025 04:00:36 -0400 Received: from mail-wr1-x436.google.com ([2a00:1450:4864:20::436]:50205) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u23sl-0002bH-PX for 77588@debbugs.gnu.org; Tue, 08 Apr 2025 04:00:34 -0400 Received: by mail-wr1-x436.google.com with SMTP id ffacd0b85a97d-39c31e4c3e5so3202692f8f.0 for <77588@debbugs.gnu.org>; Tue, 08 Apr 2025 01:00:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744099225; x=1744704025; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=Scln2jJp2fcJ0YLqsXzFV0q5yFpRfrS7lvCeG5meK5s=; b=PXUEnyG1qumerbNXvwCAF/jSay8ojAH/r13wZZln6sbrTqCanhFY8jlkmkjYyPdgLP 7UvqaTNH5CS2rQf8Z07U0rG3Li6Gih+yL3tpVrsHNc69LuyEQEUxrClh05DNwbptmhCd K1MKio6uyC207Goy8xyL6iwyZEUlAcL7RPxP+36tOTjtnylHcnOJToPVa9NzMWOpxCaD 4oHX0F8EQblzDZaSjM8p19hFrpvQHL7xtsEM1IjS/Ji6Jp+dwUZ0h+ytzs3/qRgr4uIe bj/5wW1qaSM2joCe71kq7KSb1LRwVHEoTrwEaCZzZ14u29/Q6xSj+K6dL774DA0h+WrB uDSQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744099225; x=1744704025; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=Scln2jJp2fcJ0YLqsXzFV0q5yFpRfrS7lvCeG5meK5s=; b=iDcb+5o0jHGMZH7QFHKDTsFbE6rA5WxTUt0uQtSJfXTfr/lQUcSYVMqy7iHNYQ9r4B ehw4IS7efWBkVfttFiSI7kqVYd5hqbB+cyz0innRK7cAnvIWkISXH1F7Wp1nwLvGiCMY uRI5j4dLEBYGAHv16MfG3m6rJpxeDwgctcUPKuoVALd+NXvzQnNjEzu56LHUwR1Jgf+q 3LcndOuwOcHhsDolEi+RM0vQhMD8S2HvHqwoYlccPFtLkK75v1zwEFEOXk5q3SN4BIze A3erc4KT94J8rCsr57C5HtVpwPFCakKNEcy3xlssq0XGTv5r8DozpBNz7HhqGXOsAP9o j1Og== X-Forwarded-Encrypted: i=1; AJvYcCXMofM709iAVRqVQnJ5ArhV0/dI8e/jEeNF3vHs+TgPtZVExQ0Eu52sQMzK9a5mw6/HSoRPdg==@debbugs.gnu.org X-Gm-Message-State: AOJu0YytnkvH1WjWV08DiTZHuXn9pObQp1+8+rJVEY9KOtSityB3sFIU 0mtKEj6/NiuZjAY1Tmhqv4ETfYmy+aWEg84iZbD6nOjRsTD1c03daSQU4Q== X-Gm-Gg: ASbGncviJno426zWRqmY5LlwzhlZyX3nJMTWMBpz52zGlZbLQ4MPBYSbu2GxNOCO6Pb yx500w7LV7cPAizTAVF4EoYMDifgaPA+SQiQgycWwQZuLr/Ug+DfBzOHA/TeVayjzEYa/45P2Sm nYx2Vs4Co8QMuCQTOxoUoulxnSBi3r5Xwpc7gi6EGmYIJ8qTohaAKs8lyeyk9vb6YDUeDt6SnyF 8uq8bJ04R7ddaaJztPLpP44CL2T9cn1aUyn/4LDoN1VeHUl8W/lzm5NqaQeK10bgd9xoxm9IOmI sQx9EM0oZB/nFANds4ekkHueRsFLZw/7Vj0IBoiQCToKrVf+JYGbxSqZtzJGDA== X-Google-Smtp-Source: AGHT+IGtKdXOJWrURjciC1+eeQ9vjT61UMA5ntaWyRwIcvwZgcunfkzPNsJ/TdDOQNoN7tBFiWuXXw== X-Received: by 2002:a5d:5f81:0:b0:38f:4d40:358 with SMTP id ffacd0b85a97d-39cb3575d11mr12376187f8f.9.1744099224534; Tue, 08 Apr 2025 01:00:24 -0700 (PDT) Received: from krug (87-196-72-236.net.novis.pt. [87.196.72.236]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-39d7c6d838bsm4051847f8f.69.2025.04.08.01.00.23 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Apr 2025 01:00:24 -0700 (PDT) From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= To: JD Smith Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' In-Reply-To: <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> Date: Tue, 08 Apr 2025 09:00:55 +0100 Message-ID: <87ldsb84lk.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) JD Smith writes: > know much about how this has been implemented in other clients, and there= are many questions:=20 > > * When is the appropriate time to pull? > * Should pull be done in idle time? Driven by flymake? You are overthinking things. Pull diagnostics are actually much closer to Flymake's original model than push diagnostics. You pull them when Flymake decides it's a good time to pull, and that's it. See https://www.gnu.org/software/emacs/manual/html_node/flymake/Backend-f= unctions.html > * When should you ask for the full project's diagnostics vs. just the > current buffer? Always? You could start with just the current buffer. > * Should diagnostics be versioned (likely)? I don't know what that means, but the answer is likely no. Flymake knows how to manage its objects. > As well, my familiarity with eglot/jsonrpc's internal structure and > comm model is rudimentary at best. I'd be happy to help with logic > and provide deep testing, but I'm afraid it's not something I could > tackle alone. You don't need to know any jsonrpc internals to implement this. As to Eglot's internals, you need to know no more than what you've demonstrated you already know in this issue. > I will open a separate bug for that. Paste the number here when you do that. > The main issue is that eglot is trying to "correct" a region using > data which is already outdated, and therefore not likely to result in > anything useful, however hard flymake tries. Agree. > It seems eglot keeps track of the "document version" in `eglot--versioned= -identifier'. I believe that can be compared to > the one in the `textDocument/diagnostic' message to avoid this mess > altogether. I've implemented this. Please test and let's close. The second thing you propose is too risky and redundant anyway. Eglot is generally not in the business of trying very hard to fix server flaws. So I will let the "botched ranged" code be. It was introduced early on when this policy was less clear and I wanted a young Eglot to work with flawed servers. I'll stay for backward compatibility reasons, I've been doing this long enough to know someonw will grumble if I delete it. I suggest you open bugs against the LSP server (and the ridiculously slow thingatpt.el for Python, which you already said you did) Jo=C3=A3o From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 09:46:35 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 13:46:35 +0000 Received: from localhost ([127.0.0.1]:60069 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u29Hf-0001fe-39 for submit@debbugs.gnu.org; Tue, 08 Apr 2025 09:46:35 -0400 Received: from mail-io1-xd2d.google.com ([2607:f8b0:4864:20::d2d]:55755) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u29Hc-0001es-8G for 77588@debbugs.gnu.org; Tue, 08 Apr 2025 09:46:32 -0400 Received: by mail-io1-xd2d.google.com with SMTP id ca18e2360f4ac-85b3f92c866so97189039f.3 for <77588@debbugs.gnu.org>; Tue, 08 Apr 2025 06:46:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744119986; x=1744724786; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=zyD+p1SYSbiQae8fEpaeAnS/YYfHNCKNeCIApTkyzq8=; b=FH3hr6wCEuWPDD9WT0RI8aQvk+ZN5c/DKsTGnf92EeATOo66Qp3zbUjASFrdRwV0f4 YeLlbnNjZ+WkAXT5H4a8NNZhC7XxmrfcgCfWhdBltN7XfhzLwG5IrKlSmNOFWJlvA8UQ WSmSxsCi2Orf/HMwQnj3D+ofM1v1LZPgOKjsBk8mFB4cx0MnsyKDxNO7V15AgklZbCuX xHteCiiCrD90JDfYbDd6wOqB8JXzwqIuNSHDdiI1UtcYErAUvwTVjCeKv/z5y8X9IMmb owchSkUOXF4FdvEx9jodrk74djzCtHdfayKFM5p3t4krpXZodsKYBJf1dS1Euo6HPOZ9 v2lQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744119986; x=1744724786; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=zyD+p1SYSbiQae8fEpaeAnS/YYfHNCKNeCIApTkyzq8=; b=rdCYpnrrBYNgUbCa0OQIQDnamxVSWrOM6Inwol16NUIW1ER4Asy6fTy459/IMbTX3Y 7Rn335rnxWzDyJaw3CWdZA0mjI6DfY+tDXJ7AdjA9a7BRro+iGvhrIXvy3mCLFfhmSRT GQLEedW3SSY80muZvit0s2dRSnotf3aYVUwu20BRjBoiE+zPtyFLXu/NAV8A/fq05gKW MIi5CnI+IWPYvc8Hjf71BFWCen93jP9IM3riIcfElCzl3knj4py5w9Wxxdzh1HLb0UlP B39NTnfWltwLIccB1/4FeqxP9drQ1GVGzUjYAoz8+ia4l5TapD15ux4X4j8UcBfwx90k Sifw== X-Forwarded-Encrypted: i=1; AJvYcCVmiy/WTDsBNzUpa2PEetGaYfv6Xx19ORBIehb6NAfxUddnSza3ivZycv1bAryftnlbbDfA2A==@debbugs.gnu.org X-Gm-Message-State: AOJu0Yw2zzeMDSuc+GoYtdeRNyVtUAoVbW70X/ddnUIFDfrH+CW1A1tg gO5/7kWwrrkpdAMRxF95GBISGEIW8rmNmiIlEn6Xr8lufNT45yW4 X-Gm-Gg: ASbGncsrKr4vZlVFyPiKgKaeYiaIUxdQjZo/jWbKIMtZE8lIRMCgKz2hIEoMJm0ExIU gEW7jTLg/b3bEYF1VotI8Sn2+jwjkaODupUD5wJSaZcat67owg+DdWQtJD3xAfcSITqbyE+il8U l+gt4fxNbl/9zte0PMbosaUKOTqMVTzFYlPLmrO4snqzPs5f6+POAXvXTzpWAxB1iD/phdMl1ly 23aV+PYWeWCIizT0114yT7kTKQx9Ab/i/xkedE6raWde9+XxtwRcmC9D+Cd0x0oiu5pKz7E6sOS RBCFmMPulqHYw+KkKTZwqRQowk4Mjo9LdZh4qqWoIjpXV0kYpkFrU/nrRtqUbLfUwxA/EXxkBU0 GslmHfOdyf5LZPfMP X-Google-Smtp-Source: AGHT+IELvQtN1UQq0LSXAKo4LupCqI+QL/UFV2EDqEH7+iF6EWZ7GfalnDkMU0CyultIhOMVoRFZuQ== X-Received: by 2002:a05:6602:3a83:b0:85e:2e8b:602 with SMTP id ca18e2360f4ac-8611b3eefcdmr1777719539f.2.1744119986269; Tue, 08 Apr 2025 06:46:26 -0700 (PDT) Received: from smtpclient.apple (cm-24-53-185-196.buckeyecom.net. [24.53.185.196]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4f4f44ba7e7sm497276173.95.2025.04.08.06.46.25 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Apr 2025 06:46:25 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.400.131.1.6\)) Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' From: JD Smith In-Reply-To: <87ldsb84lk.fsf@gmail.com> Date: Tue, 8 Apr 2025 09:46:13 -0400 Content-Transfer-Encoding: quoted-printable Message-Id: References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> <87ldsb84lk.fsf@gmail.com> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= X-Mailer: Apple Mail (2.3826.400.131.1.6) X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) > On Apr 8, 2025, at 4:00=E2=80=AFAM, Jo=C3=A3o T=C3=A1vora = wrote: >=20 > JD Smith writes: >=20 > You pull them when Flymake decides it's a good time to pull, and = that's it. I see. What I was thinking here is that since flymake doesn't = understand that it is talking with an LSP server, it may ask for updates = at inconvenient times. Ideally you'd arrange the timing of diagnostic = pulls to maximize the chances the document version matches.=20 >> * Should diagnostics be versioned (likely)? >=20 > I don't know what that means, but the answer is likely no. Flymake > knows how to manage its objects. I meant LSP version identifiers. After my success solving the current = problem using them, I believe ensuring the document version the LSP = server worked against when working up a response to the diagnostic pull = request matches the current version is vitally important. Luckily this = looks to be straightforward. >> As well, my familiarity with eglot/jsonrpc's internal structure and >> comm model is rudimentary at best. I'd be happy to help with logic >> and provide deep testing, but I'm afraid it's not something I could >> tackle alone. >=20 > You don't need to know any jsonrpc internals to implement this. As to > Eglot's internals, you need to know no more than what you've > demonstrated you already know in this issue. I'll take it under consideration, though I suspect it would be 10x = easier for someone more familiar with eglot's semantics and code = conventions, which are more complex than typical packages. >> I will open a separate bug for that. >=20 > Paste the number here when you do that. Opened at bug#77620. >> I believe that can be compared to the one in the = `textDocument/diagnostic' message to avoid this mess altogether. >=20 > I've implemented this. Please test and let's close. Thanks. This tests fine on master. Performance in my large python = buffer is now refreshingly acceptable. Two questions: - Can we be certain that `eglot--versioned-identifier' is always an = integer? - Any reason not to implement this on the emacs-30 branch? =20 > The second thing you propose is too risky and redundant anyway. Eglot > is generally not in the business of trying very hard to fix server > flaws. So I will let the "botched ranged" code be. =20 That's fine, it likely won't matter since that code will now rarely be = triggered, and possibly thingatpt performance can be improved in = python-mode for those rare times in which it is. > I suggest you open bugs against the LSP server (and the ridiculously > slow thingatpt.el for Python, which you already said you did) I don't think the LSP server is to blame here. Yes, it's sending large = messages (too often) and getting behind, but it is dutifully providing = the document version number. The client is presumably responsible to = act on that accordingly. That said, I suspect eglot predates the = availability of this particular version information. Thanks for your work on eglot. Used daily.= From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 11:42:33 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 15:42:34 +0000 Received: from localhost ([127.0.0.1]:34850 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u2B5t-0001Oe-Aw for submit@debbugs.gnu.org; Tue, 08 Apr 2025 11:42:33 -0400 Received: from mail-oa1-x2d.google.com ([2001:4860:4864:20::2d]:56585) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u2B5r-0001Nc-I3; Tue, 08 Apr 2025 11:42:32 -0400 Received: by mail-oa1-x2d.google.com with SMTP id 586e51a60fabf-2c68fd223bcso1837660fac.1; Tue, 08 Apr 2025 08:42:31 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744126945; x=1744731745; darn=debbugs.gnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=CUnLZYafAtev3ErmX3lNmqF+Y0TFg0g14bfBc67WnH8=; b=bBG7VT2XyZrxq94AHJ2R7ujchXkdJe/frRsHPH56T0UyoaDOHKkdkW3OaK9YscVy/6 c6kUsg9fkp80nexUkwoLiW2wI10Uripay40JMwB1IUhsUQpdWPPzlyDFEl3viiiSpotr Y22Yugbyhbs3tFLTmrKNUC8k9wpVMXuU1aPsGaRjVlKzpOTURc3h6dnJGSJtC1thQLrz FiBhoOHWKC9+Sadk2rfs2lpCwkYzHd8/DOEjKLtpt5NFQA3iuLWlrlHop9fB0JG5/ImZ u0AABo3okpY/lq03ksYdCAwjhLNXZ9mUIQRiH8uaSuBzzhHu7H+oy+5jp2s7P4Jdobak ouJA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744126945; x=1744731745; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=CUnLZYafAtev3ErmX3lNmqF+Y0TFg0g14bfBc67WnH8=; b=wg8Ynfw8/60rVhgi+f3tgFFhfiPT0/mEoxlMyvHA3PwcnvcyK04A7NN6YqyJ8PtXb0 8iicXbkaRgIykUE9CBKSSDrk4mT8jS4hgGOBmEuhI06TmBNy2emOdsOq8U+D4ob+sq52 IPdTme36JjkufIdZRlBKXPQq4GXRMR+/NxR/qWKyUT8NENp9QhjxMEz2ZH2igpzyZ6zN SOtlsg3CkNYb+CSqpyBOF+LhGQgGrfEqmVAfeqsV46n5+RdKReOtCIysUmRt55D9sg0r EzIU42qlhYxuev4DM8YV0T4MxieX40DDu4GN7x9oCZH4jRxhjoAyzF001iod1WK6heUL ojJg== X-Forwarded-Encrypted: i=1; AJvYcCW79AYc2HTHy1XAYfWJzGznt6481lLtyceturSiNJkiQHGrUmNdK99gL1GKGHtsvlA21t2eSAM=@debbugs.gnu.org, AJvYcCWR1TDTDNk7KPTBOeSBUiIEGgmRGvieBbDwFkYCMJZnPatyUXSst+P9e7mNUFKONf8K+q4+chAU2wYn@debbugs.gnu.org X-Gm-Message-State: AOJu0YwUC1Zc5M2Dl72ZbsM8Ibm6cTBEOA18gl2pXhCivynTEZaqFJkj yuq/+cE1uMnvAeZmMcLWGs08D8F+JOPWq+wK4ocrx0In9dml1HYKc4iNrmOxMIBwglSwjpkyyC8 wT1eCQieS1gKCGQJIGM4m6btOv30= X-Gm-Gg: ASbGnctuyrmKXX/97zXrW56jW07i0wSt+S49S1K/S17FV1K3cR4+HnioeozdBlm0YCk Szf/rI5T32RBSzN+TKBMD0ZZMgVgBnyd0sSgnhxFLbIwfrFikPcBoKH7XFjmUVaWBraz5QzZ8xk IS+LNZNhCqUZA6crn9yf15R+FQlg== X-Google-Smtp-Source: AGHT+IG1ItBt71FLtEXqH6xn3MYwqRIeO09/At2xPSthv/v+dbJMoLQsMDS3W0/9lYvNpqVMAgOjCw7myXj39aCin/0= X-Received: by 2002:a05:6871:4a17:b0:2d0:4a2c:7c22 with SMTP id 586e51a60fabf-2d04a3be5c6mr2762964fac.18.1744126945429; Tue, 08 Apr 2025 08:42:25 -0700 (PDT) MIME-Version: 1.0 References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> <87ldsb84lk.fsf@gmail.com> In-Reply-To: From: =?UTF-8?B?Sm/Do28gVMOhdm9yYQ==?= Date: Tue, 8 Apr 2025 16:42:15 +0100 X-Gm-Features: ATxdqUGNk8mQE2dkpc88o_XFPuHoU-iptdyiRYnU5RbgM7-n4KK1pNz5rTUbAvY Message-ID: Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' To: JD Smith Content-Type: multipart/alternative; boundary="00000000000006908b0632463389" X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org, 77588-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) --00000000000006908b0632463389 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable On Tue, Apr 8, 2025, 14:46 JD Smith wrote:. I meant LSP version identifiers. After my success solving the current > problem using them, I believe ensuring the document version the LSP serve= r > worked against when working up a response to the diagnostic pull request > matches the current version is vitally important. Luckily this looks to = be > straightforward. > Yes. I'll take it under consideration, though I suspect it would be 10x easier > for someone more familiar with eglot's semantics and code conventions, > which are more complex than typical packages. > The main difficulty seems to be finding a server which supports this mode. Clangd and basedpyright don't seem to. > > Thanks. This tests fine on master. Performance in my large python buffe= r > is now refreshingly acceptable. Two questions: > > - Can we be certain that `eglot--versioned-identifier' is always an > integer? > No. It can be nil. But what it's not nil, it's an integer as specified in the standard. - Any reason not to implement this on the emacs-30 branch? Eglot is a GNU Elpa :core package and so it has its own release rhythm. I don't think the LSP server is to blame here. Yes, it's sending large > messages (too often) and getting behind, but it is dutifully providing th= e > document version number. I beg to differ. A server that is sending useless junk down the wire, however legal that junk is, is a server that should be fixed. As you well know, performance problems arise often from just parsing JSON into expensive Lisp structures. Jo=C3=A3o --00000000000006908b0632463389 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable
On Tue, Apr 8, 2025, 14:46 JD Smith <= ;jdtsmith@gmail.com> wrote:.

I meant LSP version identifiers.=C2=A0 After my success solving the current= problem using them, I believe ensuring the document version the LSP server= worked against when working up a response to the diagnostic pull request m= atches the current version is vitally important.=C2=A0 Luckily this looks t= o be straightforward.

Yes.=C2=A0

I'll take it under consideration, though I suspect it would be 10x easi= er for someone more familiar with eglot's semantics and code convention= s, which are more complex than typical packages.

The main difficulty seems to be f= inding a server which supports this mode. Clangd and basedpyright don't= seem to.=C2=A0

Thanks.=C2=A0 This tests fine on master.=C2=A0 Performance in my large pyth= on buffer is now refreshingly acceptable.=C2=A0 Two questions:

- Can we be certain that `eglot--versioned-identifier' is always an int= eger?

N= o. It can be nil. But what it's not nil, it's an integer as specifi= ed in the standard.

- Any reason not to implement this on the emacs-30 branch?=C2=A0

Eglot is a GNU Elpa := core package and so it has its own release rhythm.
<= br>
I don't think the LSP server is to blame here.=C2=A0 Yes, it's send= ing large messages (too often) and getting behind, but it is dutifully prov= iding the document version number.=C2=A0

I beg to differ. A server that is sending use= less junk down the wire, however legal that junk is, is a server that shoul= d be fixed. As you well know, performance problems arise often from just pa= rsing JSON into expensive Lisp structures.

Jo=C3=A3o


--00000000000006908b0632463389-- From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 12:24:21 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 16:24:21 +0000 Received: from localhost ([127.0.0.1]:35034 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u2BkK-00064G-Uh for submit@debbugs.gnu.org; Tue, 08 Apr 2025 12:24:21 -0400 Received: from mail-yw1-x112e.google.com ([2607:f8b0:4864:20::112e]:51249) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u2BkI-00063Q-0Y; Tue, 08 Apr 2025 12:24:18 -0400 Received: by mail-yw1-x112e.google.com with SMTP id 00721157ae682-6fead015247so52282967b3.2; Tue, 08 Apr 2025 09:24:18 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744129452; x=1744734252; darn=debbugs.gnu.org; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:from:to:cc:subject:date:message-id:reply-to; bh=rapegJR+0nQrQC66vcpNoEhoaVsQkwhbkggr637cMvI=; b=Vk2YK5xQfKR9b8L/wboV0Suz7zM1bOBVILWn9O/x2SLq2cbXVdnnLCJUfIGYwspFwa cWNupBaRdUAua6UZoPhIXf7rdVq2gxKdm3FesJ1Qc6iaX60K9Q32Dr2F4nKkti0hF/14 vKytcWYvyXr5+/IWBZzp6hKBejPu90tlFOk0Rmoyo5SThHv+fpl//vSF7SaNa2Zi0kTB ZvH2rp+dxBw/0Kpg8DOlNw17sWwLlB0YjtCw/cfj7nwoQsZKySEKttgjzNW7yCHpMG1j Nx2a9X892pDSUPZJ0WqJ/DnybyQsDZIgOqwTZq2WWbb6PUYk10zZiD7YJb3rvGc/JK+4 QRAQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744129452; x=1744734252; h=references:to:cc:in-reply-to:date:subject:mime-version:message-id :from:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=rapegJR+0nQrQC66vcpNoEhoaVsQkwhbkggr637cMvI=; b=tE8a5TDcRg2AcDNLYWtHwsgnCo5deng9RTfjZVfUfht/fcm9U75hKY38fD9cKdvBar +792RyheRAt+Zkw/s8qx0Xe8STXp4sVRNgPf9BY9p/EL0qqkmEGZNMyB/ARdXweiLNs7 uuYv/ol1bafDtygT+X/qLJvKNWBfR/x78WoysvomuVC3iYT55TRbde2lfeDeOQy+7dcp HzDrencYz/3FE9SErK0/vvnvq91jXAe/UNrelu+gTEgYLMmTrD7OnfMdG+RXKkLxkQEt w1cFGOs3m4E1KQ5wck7uEHtIprFoopgVWX/wpe/7JK8wbGrCnSS+5HMAdsnHbV3A8CEc /nQQ== X-Forwarded-Encrypted: i=1; AJvYcCWwgl4/wNqBQFlzzfV79EqheKbuM9dVwmP1spKBCY8zlFABshVtUW4T1ooGP7f25MVwUy6/lWY=@debbugs.gnu.org, AJvYcCXk+m3ECIKMrbp9iw8bOiz9PgI3a29MMNEoz27sGG0lDvBcLInoEfzrF0DNtjKT4or4cMqPQoGIBpsU@debbugs.gnu.org X-Gm-Message-State: AOJu0Yw+Arbnt0gmy6fM1uORRz4r+evj3kUW4Syiv9lDiqKwd7rK0vcd X4taEsrfuS8T2MSX5KqxOuGgDB6e8E7/mm3x2NdTtkCqjaaSJOiv X-Gm-Gg: ASbGncuu7YOKdTgzSuW9qWtY+ioKjd+50MX6V2qE4qOiudPa8u+yedcf8QFjUVuj/pu f3Fh62xt/HvCHbAnHr5Q22+fGC7H27WwkXHJQQKEyUm7PX71IPHwP2zjokGn5wnUJByjS3puBS6 OhJdrIffZ2e6EFPluF2DlZn6yH02h1XxB6K7c8LSUqoc6iNPXyJk8KVdDglVophTR9QU7dukAFX ZhezAiDWkw5zeHFAPOdI4ZlytYvqtnPG/3h3xDq5ar8sIVOIwSUPYsWAqqb98uICjxKMMi0j1ij 0kYPvXMICDxjKLfs8QViBZuxjvfPrhfHPPopxjGQjnnS3E8hjE5YsJB6eMw/eA== X-Google-Smtp-Source: AGHT+IGyizMoIIxUpXZMFsO5tmrdm4v2X6kA8YleISaiGoirx+DTaqiOdaALGjntDkLuw+eSS5fF5A== X-Received: by 2002:a05:690c:688f:b0:6f6:ca9a:e9da with SMTP id 00721157ae682-703e14f81ebmr276428527b3.4.1744129451936; Tue, 08 Apr 2025 09:24:11 -0700 (PDT) Received: from smtpclient.apple ([131.183.188.117]) by smtp.gmail.com with ESMTPSA id 00721157ae682-703d1e81bc5sm32038937b3.55.2025.04.08.09.24.10 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Apr 2025 09:24:11 -0700 (PDT) From: JD Smith Message-Id: <1768C0DC-75A1-400D-8C0F-C4B0CCED8FE7@gmail.com> Content-Type: multipart/alternative; boundary="Apple-Mail=_25483C69-D2EF-447D-9EB8-36E56399856C" Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.400.131.1.6\)) Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' Date: Tue, 8 Apr 2025 12:24:00 -0400 In-Reply-To: To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> <87ldsb84lk.fsf@gmail.com> X-Mailer: Apple Mail (2.3826.400.131.1.6) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org, 77588-done@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" --Apple-Mail=_25483C69-D2EF-447D-9EB8-36E56399856C Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset=utf-8 > On Apr 8, 2025, at 11:42=E2=80=AFAM, Jo=C3=A3o T=C3=A1vora = wrote: >=20 > The main difficulty seems to be finding a server which supports this = mode. Clangd and basedpyright don't seem to.=20 basedpyright actually does; it was added about a month ago via pyright: https://github.com/microsoft/pyright/pull/10055=EF=BF=BC Implement support for pull diagnostics in Pyright by rchiodo =C2=B7 Pull = Request #10055 =C2=B7 microsoft/pyright github.com >> - Can we be certain that `eglot--versioned-identifier' is always an = integer? >=20 >=20 > No. It can be nil. But what it's not nil, it's an integer as specified = in the standard. Then it might be worth switching the test to `(not (eq ...' from `(/=3D = ...'. >> I don't think the LSP server is to blame here. Yes, it's sending = large messages (too often) and getting behind, but it is dutifully = providing the document version number.=20 >=20 >=20 > I beg to differ. A server that is sending useless junk down the wire, = however legal that junk is, is a server that should be fixed. As you = well know, performance problems arise often from just parsing JSON into = expensive Lisp structures. My point is that the message's version info is an explicit = acknowledgement that the information may be out of date by the time the = client processes it. I see no way around that (other than everything = working quicker). A fair critique is just how many push updates arrive. = I suspect if we raise this they'd point us to pull diagnostics anyway. = A nice feature of pull is it can respond "no changes" when there are = none.= --Apple-Mail=_25483C69-D2EF-447D-9EB8-36E56399856C Content-Type: multipart/related; type="text/html"; boundary="Apple-Mail=_65071332-12D8-4E48-9E5B-F65F2787FD9A" --Apple-Mail=_65071332-12D8-4E48-9E5B-F65F2787FD9A Content-Transfer-Encoding: quoted-printable Content-Type: text/html; charset=utf-8
On Apr 8, = 2025, at 11:42=E2=80=AFAM, Jo=C3=A3o T=C3=A1vora = <joaotavora@gmail.com> wrote:

The main difficulty seems to be finding a = server which supports this mode. Clangd and basedpyright don't seem = to. 

basedpyright = actually does; it was added about a month ago via = pyright:


- Can we be = certain that `eglot--versioned-identifier' is always an = integer?

No. It can be = nil. But what it's not nil, it's an integer as specified in the = standard.

Then it might be worth = switching the test to `(not (eq ...' from `(/=3D = ...'.

I don't think the LSP server is = to blame here.  Yes, it's sending large messages (too often) and = getting behind, but it is dutifully providing the document version = number. 

I beg to = differ. A server that is sending useless junk down the wire, however = legal that junk is, is a server that should be fixed. As you well know, = performance problems arise often from just parsing JSON into expensive = Lisp structures.

My point is that the = message's version info is an explicit acknowledgement that the = information may be out of date by the time the client processes it. =  I see no way around that (other than everything working quicker). =  A fair critique is just how many push updates arrive.  = I suspect if we raise this they'd point us to pull diagnostics anyway. =  A nice feature of pull is it can respond "no changes" when there = are none.
= --Apple-Mail=_65071332-12D8-4E48-9E5B-F65F2787FD9A Content-Transfer-Encoding: base64 Content-Disposition: inline; filename=10055.png Content-Type: image/png; x-unix-mode=0666; name="10055.png" Content-Id: <8F67821A-7E7C-4AAC-9D89-2816CEB0B129> iVBORw0KGgoAAAANSUhEUgAAAoAAAAFACAYAAAAszc0KAAAAAXNSR0IArs4c6QAAAERlWElmTU0A KgAAAAgAAYdpAAQAAAABAAAAGgAAAAAAA6ABAAMAAAABAAEAAKACAAQAAAABAAACgKADAAQAAAAB AAABQAAAAABvE1SKAAABzGlUWHRYTUw6Y29tLmFkb2JlLnhtcAAAAAAAPHg6eG1wbWV0YSB4bWxu czp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iWE1QIENvcmUgNi4wLjAiPgogICA8cmRmOlJE RiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMi PgogICAgICA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIgogICAgICAgICAgICB4bWxuczpl eGlmPSJodHRwOi8vbnMuYWRvYmUuY29tL2V4aWYvMS4wLyI+CiAgICAgICAgIDxleGlmOkNvbG9y U3BhY2U+MTwvZXhpZjpDb2xvclNwYWNlPgogICAgICAgICA8ZXhpZjpQaXhlbFhEaW1lbnNpb24+ MTAyNDwvZXhpZjpQaXhlbFhEaW1lbnNpb24+CiAgICAgICAgIDxleGlmOlBpeGVsWURpbWVuc2lv bj41MTI8L2V4aWY6UGl4ZWxZRGltZW5zaW9uPgogICAgICA8L3JkZjpEZXNjcmlwdGlvbj4KICAg PC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KMyImCQAAQABJREFUeAHsfQdgXNWV9pE0VV2yrGbJvXds bLAB0wkEQgkBEkoI6dnU3exmS7L5UzZlN9lNX0KooQVYIAkkNIdqDBiDe69yk21Zvc1IM5r5v+88 PXk0lmTZGLCkc+3RzLy57757z7vle98pNyWOJJZMAiYBk4BJwCRgEjAJmASGjARSh0xLraEmAZOA ScAkYBIwCZgETAIqAQOA1hFMAiYBk4BJwCRgEjAJDDEJGAAcYjfcmmsSMAmYBEwCJgGTgEnAAKD1 AZOAScAkYBIwCZgETAJDTAIGAIfYDbfmmgRMAiYBk4BJwCRgEjAAaH3AJGASMAmYBEwCJgGTwBCT gAHAIXbDrbkmAZOAScAkYBIwCZgEDABaHzAJmARMAiYBk4BJwCQwxCRgAHCI3XBrrknAJGASMAmY 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 +C5WTjq/C30AAAAASUVORK5CYII= --Apple-Mail=_65071332-12D8-4E48-9E5B-F65F2787FD9A-- --Apple-Mail=_25483C69-D2EF-447D-9EB8-36E56399856C-- From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 17:00:04 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 21:00:04 +0000 Received: from localhost ([127.0.0.1]:35790 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u2G39-0006Xo-CY for submit@debbugs.gnu.org; Tue, 08 Apr 2025 17:00:04 -0400 Received: from mail-wm1-x335.google.com ([2a00:1450:4864:20::335]:47388) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u2G32-0006WY-P5 for 77588@debbugs.gnu.org; Tue, 08 Apr 2025 16:59:57 -0400 Received: by mail-wm1-x335.google.com with SMTP id 5b1f17b1804b1-43cf034d4abso65126925e9.3 for <77588@debbugs.gnu.org>; Tue, 08 Apr 2025 13:59:56 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744145990; x=1744750790; darn=debbugs.gnu.org; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to; bh=OtIs82ued1BX02Iq2p+ASaYCFCjF03YMLOTJUI6GHUQ=; b=D2v1YyDUjp84Dj6ue2pBgEQB5HVOHd+EMGJrzgRhWdo2WDWWWE6NPlVzFGJefbQG1/ 5TGijIygIoBzXNVCARNzi/VSsF4bsZ2P1anHqdDPayso7pe+2uSMku3BNkC0vqOghEvQ S2GiRudWipPg466xAev5ye5ibqNCNeSQI56wWfpTAP0yQwc95jDPXnOkNII7TU7OHQhB EyawHYS/wTM0F+/mTira1o4r5uj1T+4N15m4girNXCkvQuBCnq/7cezGzQL7v07QNjst K5cAueYoSJXtzEfyz9Up5T7QE7fB1tb4wx14QZ7rZWxL03t6T6Ee3fMKjuNw1mdweEX9 RsIw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744145990; x=1744750790; h=content-transfer-encoding:mime-version:user-agent:message-id:date :references:in-reply-to:subject:cc:to:from:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to; bh=OtIs82ued1BX02Iq2p+ASaYCFCjF03YMLOTJUI6GHUQ=; b=XpnXJCo8RZI36jGiUhnW9f/iYGclEOQLhYHgI8LNflA4QqtnT+KenWOBxkrJwcGz/W S4/cUM9+kDLkhJmnOfzkYJCwbCC15ISYmxoMPRobviev9pNEujUkTcgsEC5zPNKairqH 4GxdCgw9uKkKG6yIBQneH+vGHUzmQe35cA7nR2f5jJjOvIh3R5meK8os/gnp0BUpo3iC frxQTCEeRNMAaOpwwj07WuTA/Ks9vDn5RZciyXuUcigF1la0uhK7WnzXcjsW6Zq+3zSc YtYOoyXjwmouQVuklng7QINQhjkFIqBt6nNBHKAMYqE+Qszy5WVv/KAiOGbB+elDn2VY t4ew== X-Forwarded-Encrypted: i=1; AJvYcCXaAaGy30xgiD8yKt/9eUeFPwLotqUecjmMEaeOjYuiYa5lSnCZFp1m99QQZdvCwqN/F/rFhQ==@debbugs.gnu.org X-Gm-Message-State: AOJu0YxcLOkT2i7iddwaiqWm0yleu9ACM6HhvNBQJYIoCkorGNTpnZ7e yd0vWwSsijEAOjkOpgTJu7vMAmKanextUcRpUKMdhYywbCAvSLZfT1+GXQ== X-Gm-Gg: ASbGncv7s/s2ZNreOJEYcturWtUWDXit9bYU1b8qcge+YBylxBc2jp8S3cw89pot36n ygJsRh6DL2DlQWFdS+ugXKObhLBhfiwPETGfKrQD890CTHfM+pxYXWbrJNKSsvjVbNqLHH1KslP rZXiSqOs0D1zcxzsCy0zrLodyG8xcxHl+kOEP2VXxIq85H2pyupyQERXHLzgq3MieyAQL9Sj8uf 4N1eMZMBf0v7l9hPQoFPF8j6h6mJTk1nIq3p8i536OTJZfJnXRIWL50efqrauWSW/r91+KurEWK OEMN2nRAtQ8vLg+WrJJ2g5oEc7QlSooXORs4qt2eTCyXZBE3MqxCkLy+aR/Eag== X-Google-Smtp-Source: AGHT+IGXx0YFo69zIzzHKZQnvZgEXwsad2kfQ3jbIoQX1P9tEVNKqUtDiCkIF3SlkUdB0ph5yr7UBQ== X-Received: by 2002:a05:600c:5251:b0:43c:e305:6d50 with SMTP id 5b1f17b1804b1-43f1ed4ba2cmr4102395e9.24.1744145989715; Tue, 08 Apr 2025 13:59:49 -0700 (PDT) Received: from krug (87-196-72-236.net.novis.pt. [87.196.72.236]) by smtp.gmail.com with ESMTPSA id 5b1f17b1804b1-43ec366b571sm174111315e9.40.2025.04.08.13.59.48 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 08 Apr 2025 13:59:49 -0700 (PDT) From: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= To: JD Smith Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' In-Reply-To: References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> <87ldsb84lk.fsf@gmail.com> <1768C0DC-75A1-400D-8C0F-C4B0CCED8FE7@gmail.com> Date: Tue, 08 Apr 2025 22:00:22 +0100 Message-ID: <87frii8j2x.fsf@gmail.com> User-Agent: Gnus/5.13 (Gnus v5.13) MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Spam-Score: 0.0 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -1.0 (-) [I dropped the bug report and previous recipients, adding them back and hoping they can piece together the context from the quotations] JD Smith writes: >> Btw your html mails are hard to read. > > This is hopefully better. Yes it is, thanks! >> On Apr 8, 2025, at 12:44=E2=80=AFPM, Jo=C3=A3o T=C3=A1vora wrote: >>=20 >>=20 >> On Tue, Apr 8, 2025, 17:24 JD Smith wrote >>=20 >> Then it might be worth switching the test to `(not (eq ...' from `(/=3D = ...'. >>=20 >> I don't see why. =3D Is the lisp way of comparing things we know are num= bers. > > You just mentioned one of them can be nil though... Right, but the patch I pushed checks for that before using `/=3D`. >> My point is that the message's version info is an explicit >> acknowledgement that the information may be out of date by the time >> the client processes it. I see no way around that (other than >> everything working quicker). >>=20 >> What could be the server's rationale for sending out of date >> information when it _knows_ that the information is out of date? >> Presumably we the client have informed it of the new version in >> didChange. Or am I missing something? > > Maybe I am missing something, but if the push diagnostics and > didChange cross paths, I could see how the latter could be out of > date. Indeed, but they don't cross paths, at least not on virtually all servers that I know of. Servers on a "push diagnostics" model operate by sending at most 1 publishDiagnostics notification _after_ receiiving a didChange. Which makes sense. You're notified of some changes V1, you do some calculations, and you publish your results. If you operate asynchronously and during that time you get another notification of changes V2, you probably have throw most work out (certainly don't publish it). If you supply the Eglot events log to your server session we can check what's happening. I have used basedpyright+eglot in the past though, and I never noticed any problems (doesn't mean they can't or weren't happening under the hood, but I certainly didn't experience any catastrophic slowdown). Jo=C3=A3o From debbugs-submit-bounces@debbugs.gnu.org Tue Apr 08 19:45:25 2025 Received: (at 77588) by debbugs.gnu.org; 8 Apr 2025 23:45:26 +0000 Received: from localhost ([127.0.0.1]:36070 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1u2IdB-00012v-Be for submit@debbugs.gnu.org; Tue, 08 Apr 2025 19:45:25 -0400 Received: from mail-il1-x12e.google.com ([2607:f8b0:4864:20::12e]:53369) by debbugs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.84_2) (envelope-from ) id 1u2Id8-00012f-Bf for 77588@debbugs.gnu.org; Tue, 08 Apr 2025 19:45:23 -0400 Received: by mail-il1-x12e.google.com with SMTP id e9e14a558f8ab-3d4436ba324so52586145ab.2 for <77588@debbugs.gnu.org>; Tue, 08 Apr 2025 16:45:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1744155916; x=1744760716; darn=debbugs.gnu.org; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:from:to:cc:subject:date :message-id:reply-to; bh=2I0QGckPf2gjJCad1nk4q/l6m43PyXhuFPSX4Byum7U=; b=nOiyqbGJHDrICa5PqMMzOMsva/ma8LU/wubEDNGr57bH+VHk9njNNdKOHQJJhGoWtu EgHVpnnAB1I5cqfcc3a2+4QYLZI5EcmKzmfzpMNFlUo28kR/xPQLfpCD47ckAZ92pqgq bUELjTBrlerXkJEgLgXYymlPLrVcPRBvKHyEdhmtYemhWqE0OwDzZ0YLAdvCOq35K48y ioCu4gv5Z00Lf6OVodvcc/ZHC5Jl+D/lNbIo+/UBBjMCeHOegQgOkOSpnutvML9C5jPK whF8vRly3KX7lDflDXYrP9Cy7JUyoGe4J6CJ5v6H2plAbRHWyL+e5/mz4edr50kEc6AG h/8g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1744155916; x=1744760716; h=to:references:message-id:content-transfer-encoding:cc:date :in-reply-to:from:subject:mime-version:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=2I0QGckPf2gjJCad1nk4q/l6m43PyXhuFPSX4Byum7U=; b=A26UKkP8u9sml2x5zMvtA/QJBbN0D/3Qh29MsEFGVnahbjfQJvyin+cioRO7Zm8GdK anxMxd9jsTNW8xPjsKyj2sj22os7TEiQB5F3LuurM6EMlO67F1Rah7SEeGboUSUr9Nxg Pa2ntUASVtp+vqMRq7a0MHyGEy5gk6HFt5Lxl91aIcQt5XvlVzZm3RSFxOPM03gW/A78 I0NE9MbSL9dbJejS5XQOXcuOg8lzZt7QUgRUzwVphR5ViK8xi+HzBo98CZnCwHPysyHE ScXILBFmEWFqVdykKpfMuqRLZMz0mXOT7y1oZN56/btjyfKHDU3D2xY1Biqvd++i65TV PMFQ== X-Forwarded-Encrypted: i=1; AJvYcCU7dYY3doawQx2qo+5/pnKpnnMiMGX4aCPLUDk/gcnUroV8i1p8uqm9zRfSFvsKqKahVLnzOw==@debbugs.gnu.org X-Gm-Message-State: AOJu0Ywl+EdDv3eJy7LRm4Lf+iY/Ml3F5nl3YbFy4eBtPNV0L4JEzNzP AJMSB0eRI0mu1m5OB5JtpZZNZTe63VKHil6GEQ/0WPZJzGrJ8s65 X-Gm-Gg: ASbGncvUawrOIH3Y9nYLqkAGdyoe11AdvFPLpmP3LFFehT/miAFBlbAKYJu3IM+Jma4 b+A5D91WRrjsv1sRhg2RJbK8OvJJQCK2Irfzs54J7PTBE67Efoy7VSXjdGotUyXLbZ6+ozRbOh0 cvLMvBoJbOqAIi4Ai1YKC8S+Ia7eEucVeT4tkrmyHYkFrz9q45sg+SwM/nhSD8saF8jOBE7v8Bs N3D67qrqBarCsGHv8886VaibnOnFKgrYT/VLsJTiyHT+F1dyJ5de1BBm3duKYLEOzN0amdPABFj lz4dajt/1vp2feel+FcLbdtjtytaC8oaY9ULGIvfQW71Sy7gkklCo9/JPFKCjkYNp0O3QjNV8O7 +/5GhYjBQZYBdZVdN0AgEKWbWkzk= X-Google-Smtp-Source: AGHT+IH57hAR1SGMsd1JYs3IYYWNtLuGufVld81bQwcgk//fns5xQePVViMFBZD4EYrShHRdn9j/Tw== X-Received: by 2002:a05:6e02:360a:b0:3d4:2306:a875 with SMTP id e9e14a558f8ab-3d7b460e817mr5272145ab.8.1744155916267; Tue, 08 Apr 2025 16:45:16 -0700 (PDT) Received: from smtpclient.apple (cm-24-53-185-196.buckeyecom.net. [24.53.185.196]) by smtp.gmail.com with ESMTPSA id 8926c6da1cb9f-4f4f44e10ccsm741558173.112.2025.04.08.16.45.15 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Tue, 08 Apr 2025 16:45:15 -0700 (PDT) Content-Type: text/plain; charset=utf-8 Mime-Version: 1.0 (Mac OS X Mail 16.0 \(3826.400.131.1.6\)) Subject: Re: bug#77588: Catastrophic slowdown in eglot via `flymake-diag-region' From: JD Smith In-Reply-To: <87frii8j2x.fsf@gmail.com> Date: Tue, 8 Apr 2025 19:45:05 -0400 Content-Transfer-Encoding: quoted-printable Message-Id: References: <86v7rgtdx9.fsf@gnu.org> <87wmbw7yia.fsf@gmail.com> <40A07116-EB6A-4B72-92DF-C83EBE760EDB@gmail.com> <87ldsb84lk.fsf@gmail.com> <1768C0DC-75A1-400D-8C0F-C4B0CCED8FE7@gmail.com> <87frii8j2x.fsf@gmail.com> To: =?utf-8?B?Sm/Do28gVMOhdm9yYQ==?= X-Mailer: Apple Mail (2.3826.400.131.1.6) X-Spam-Score: 0.7 (/) X-Debbugs-Envelope-To: 77588 Cc: Spencer Baugh , Eli Zaretskii , 77588@debbugs.gnu.org X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: debbugs-submit-bounces@debbugs.gnu.org Sender: "Debbugs-submit" X-Spam-Score: -0.3 (/) > On Apr 8, 2025, at 5:00=E2=80=AFPM, Jo=C3=A3o T=C3=A1vora = wrote: >=20 >>=20 >> Maybe I am missing something, but if the push diagnostics and >> didChange cross paths, I could see how the latter could be out of >> date. >=20 > Indeed, but they don't cross paths, at least not on virtually all > servers that I know of. Servers on a "push diagnostics" model operate > by sending at most 1 publishDiagnostics notification _after_ = receiiving > a didChange. Which makes sense. You're notified of some changes V1, > you do some calculations, and you publish your results. If you = operate > asynchronously and during that time you get another notification of > changes V2, you probably have throw most work out (certainly don't > publish it). >=20 > If you supply the Eglot events log to your server session we can check > what's happening. I have used basedpyright+eglot in the past though, > and I never noticed any problems (doesn't mean they can't or weren't > happening under the hood, but I certainly didn't experience any > catastrophic slowdown). This is an interesting point. Here's an event log: [1]. I modified the = old notifier to simply alert when versions didn't match. It reports: Diagnostics version mismatch 28 received, 29 current In the log, you can see the following pattern: [jsonrpc] e[19:15:32.870] --> textDocument/inlayHint[107]=20 [jsonrpc] e[19:15:32.905] <-- textDocument/inlayHint[107]=20 [jsonrpc] e[19:15:33.079] --> textDocument/didChange ; = Version 29 change sent [jsonrpc] e[19:15:33.079] --> textDocument/completion[108]=20 [jsonrpc] e[19:15:33.383] --> textDocument/inlayHint[109]=20 [jsonrpc] e[19:15:33.446] <-- textDocument/publishDiagnostics ; = Version 28 diagnostics received [jsonrpc] e[19:15:33.800] --> textDocument/signatureHelp[110]=20 [jsonrpc] e[19:15:33.801] --> textDocument/hover[111]=20 [jsonrpc] e[19:15:33.801] --> textDocument/documentHighlight[112]=20 [jsonrpc] e[19:15:33.807] <-- textDocument/completion[108]=20 [jsonrpc] e[19:15:33.809] <-- textDocument/inlayHint[109]=20 [jsonrpc] e[19:15:34.095] <-- textDocument/publishDiagnostics ; = Version 29 diagnostics received I.e. v28 diagnostics are received *after* v29 didChange is sent. Up to = 50% of the updates have this version mismatch. Is it significant that = the publishDiagnostics is "nested" inside a completion? Note that it = also happens (though less frequently) even when typing a multiple line = comment, always shortly after a newline is entered. I agree this is = strange: basepyright should drop the v28 update like a rock. Also during these pauses, I found that end-of-thing often (but not = always) errors out: 1 -> (end-of-thing symbol) 1 <- end-of-thing: !non-local\ exit! =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 -> (end-of-thing sexp) 1 <- end-of-thing: !non-local\ exit! =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 -> (end-of-thing symbol) 1 <- end-of-thing: 306546 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 -> (end-of-thing sexp) 1 <- end-of-thing: !non-local\ exit! =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 -> (end-of-thing symbol) 1 <- end-of-thing: 306546 =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D 1 -> (end-of-thing sexp) 1 <- end-of-thing: !non-local\ exit! =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D= =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D I think this explains why my slow-down isn't as bad here: end-of-thing = is now *crashing* (inside ignore-errors). Not the most useful speedup = to be sure, and not sure what changed, probably a parsing difference in = the file.=20 Repeating that command by hand shows the real error: Debugger entered--Lisp error: (error "No sexp here") signal(error ("No sexp here")) error("No %s here" sexp) #(sexp) apply(# sexp) #f(compiled-function (body &rest args) #)(# sexp) apply(#f(compiled-function (body &rest args) #) # sexp) end-of-thing(sexp) eval((end-of-thing 'sexp) t) #f(compiled-function () #)() #f(compiled-function () #)() handler-bind-1(#f(compiled-function () #) = (error) eval-expression--debug) eval-expression((end-of-thing 'sexp) nil nil 127) funcall-interactively(eval-expression (end-of-thing 'sexp) nil nil = 127) call-interactively(eval-expression nil nil) command-execute(eval-expression) [1] = https://gist.githubusercontent.com/jdtsmith/a604c1e99f98f48da4d76f0abf07ae= dc/raw/0eb71ea878c70dc4d44afe56e44731d7dd135e19/event-buffer.txt From unknown Sat Jun 21 12:25:04 2025 Received: (at fakecontrol) by fakecontrolmessage; To: internal_control@debbugs.gnu.org From: Debbugs Internal Request Subject: Internal Control Message-Id: bug archived. Date: Wed, 07 May 2025 11:24:25 +0000 User-Agent: Fakemail v42.6.9 # This is a fake control message. # # The action: # bug archived. thanks # This fakemail brought to you by your local debbugs # administrator