From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Ihor Radchenko Newsgroups: gmane.emacs.bugs Subject: bug#66117: 30.0.50; `find-buffer-visiting' is slow when opening large number of buffers Date: Thu, 05 Oct 2023 14:25:54 +0000 Message-ID: <87bkddi1sd.fsf@localhost> References: <878r919qfh.fsf@localhost> <72c93fb0-bf3e-3dad-69c0-2147cfa40f57@gutov.dev> <875y42xyex.fsf@localhost> <87zg1ewfc2.fsf@localhost> <834jjm749q.fsf@gnu.org> <87cyyawd1a.fsf@localhost> <83pm2a5k85.fsf@gnu.org> <87wmwh2tae.fsf@localhost> <83zg1d468w.fsf@gnu.org> <87bkdr2651.fsf@localhost> <87pm2584oz.fsf@localhost> <87zg17b3du.fsf@web.de> Mime-Version: 1.0 Content-Type: text/plain Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="4555"; mail-complaints-to="usenet@ciao.gmane.io" Cc: dmitry@gutov.dev, Eli Zaretskii , 66117@debbugs.gnu.org To: Michael Heerdegen Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Thu Oct 05 16:25:07 2023 Return-path: Envelope-to: geb-bug-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1qoPHn-0000tv-FU for geb-bug-gnu-emacs@m.gmane-mx.org; Thu, 05 Oct 2023 16:25:07 +0200 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1qoPHV-0005qz-Qs; Thu, 05 Oct 2023 10:24:50 -0400 Original-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 1qoPHQ-0005nr-3S for bug-gnu-emacs@gnu.org; Thu, 05 Oct 2023 10:24:44 -0400 Original-Received: from debbugs.gnu.org ([2001:470:142:5::43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1qoPHP-0002fd-GX for bug-gnu-emacs@gnu.org; Thu, 05 Oct 2023 10:24:43 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1qoPHh-0008Dg-MI for bug-gnu-emacs@gnu.org; Thu, 05 Oct 2023 10:25:01 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Ihor Radchenko Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Thu, 05 Oct 2023 14:25:01 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: followup 66117 X-GNU-PR-Package: emacs Original-Received: via spool by 66117-submit@debbugs.gnu.org id=B66117.169651588931572 (code B ref 66117); Thu, 05 Oct 2023 14:25:01 +0000 Original-Received: (at 66117) by debbugs.gnu.org; 5 Oct 2023 14:24:49 +0000 Original-Received: from localhost ([127.0.0.1]:48052 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qoPHV-0008D9-2c for submit@debbugs.gnu.org; Thu, 05 Oct 2023 10:24:49 -0400 Original-Received: from mout02.posteo.de ([185.67.36.66]:57281) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1qoPHR-0008Cv-6F for 66117@debbugs.gnu.org; Thu, 05 Oct 2023 10:24:48 -0400 Original-Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id C10C5240107 for <66117@debbugs.gnu.org>; Thu, 5 Oct 2023 16:24:20 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1696515860; bh=J6DksJtD8gmvosjq6x98OSrdnjts51sZM7uOnfglffQ=; h=From:To:Cc:Subject:Date:Message-ID:MIME-Version:From; b=hOJ3+RxOAGNjKtkf7SeqLo2OmffswouaoaDSWWNv160eWLRxJBMLuw1sra5aBP4Aj 84pDe4zIvx842/Dd8QY6K1hS9QzRAnaSgUxexV5iL+gV2BRm4fyOyojIugs6L83e2W kGYJVefflkIXxxNyhYDlSUeXrWiu8L7hoMjI3dFkeSVgDzF4p2BG6UUmhFlkeLTs9M ZKunFlmB0Suzltj9FMir9ui1Aq8tY0Vo4gcorJg8JI4EemC0YeFJRFasWqpC9u23/V 1zPRjf4Rh4ncQdDw+2MFXAPPdilnn7vzxzqZzppzLJOUU8xuAivoplE4OogOTB1tRa bqcJC0QT5er9g== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4S1Yhz428hz6tyM; Thu, 5 Oct 2023 16:24:19 +0200 (CEST) In-Reply-To: <87zg17b3du.fsf@web.de> X-BeenThere: debbugs-submit@debbugs.gnu.org X-Mailman-Version: 2.1.18 Precedence: list X-BeenThere: bug-gnu-emacs@gnu.org List-Id: "Bug reports for GNU Emacs, the Swiss army knife of text editors" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:271877 Archived-At: Michael Heerdegen writes: > Ihor Radchenko writes: > >> So, using `with-current-buffer' when looping over all the buffers is >> certainly not optimal (maybe in other places as well). >> >> However, even `buffer-local-value' is still costly - it adds up over 50% >> run time. > > OTOH - I tried to reproduce your experiments here locally - > `find-buffer-visiting' only takes 12% of the total run time here when > using the `buffer-local-value' tuned definition of `find-buffer-visiting'. > When we additionally merge the two loops in `find-buffer-visiting' into > one loop and avoid the duplicated calls of `buffer-local-value', don't we > reach a region where maintaining a separate cache doesn't make sense for > the additional gain? > And I wonder which part(s) of `buffer-local-value' is/are that costly, > and why. I looked closer, and it is not `buffer-local-value' being costly, but rather the rest of the `find-buffer-visiting'. In particular, regexp matching in `abbreviate-file-name' and `file-truename'. I used the following: (defun find-buffer-visiting (filename &optional predicate) "Return the buffer visiting file FILENAME (a string). This is like `get-file-buffer', except that it checks for any buffer visiting the same file, possibly under a different name. If PREDICATE is non-nil, only buffers satisfying it are eligible, and others are ignored. PREDICATE is called with the buffer as the only argument, but not with the buffer as the current buffer. If there is no such live buffer, return nil." (let ((predicate (or predicate #'identity)) (truename (abbreviate-file-name (file-truename filename)))) (or (let ((buf (get-file-buffer filename))) (when (and buf (funcall predicate buf)) buf)) (let ((list (buffer-list)) found) (while (and (not found) list) (if (and (buffer-local-value 'buffer-file-name (car list)) (string= (buffer-local-value 'buffer-file-truename (car list)) truename) (funcall predicate (car list))) (setq found (car list))) (setq list (cdr list))) found) (let* ((attributes (file-attributes truename)) (number (file-attribute-file-identifier attributes)) (list (buffer-list)) found local-filename) (and buffer-file-numbers-unique (car-safe number) ;Make sure the inode is not just nil. (while (and (not found) list) (setq local-filename (buffer-local-value 'buffer-file-name (car list))) (if (and local-filename (equal (buffer-local-value 'buffer-file-number (car list)) number) ;; Verify this buffer's file number ;; still belongs to its file. (file-exists-p local-filename) (equal (file-attributes (buffer-local-value 'buffer-file-truename (car list))) attributes) (funcall predicate (car list))) (setq found (car list))) (setq list (cdr list)))) found)))) (native-compile #'find-buffer-visiting) Native compilation at the end is important - it reduced runtime significantly. > Storing the same information twice - once in a buffer local variable, > and then again in a cache that needs to be updated separately doesn't > sound very reasonable. But see Dmitry's reproducer where even `get-file-buffer' is demonstrated to be slow in certain scenarios. So, caching (although less rigorous) might be still necessary. -- Ihor Radchenko // yantar92, Org mode contributor, Learn more about Org mode at . Support Org development at , or support my work at