From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Philip Kaludercic Newsgroups: gmane.emacs.bugs Subject: bug#58950: [PATCH] * lisp/subr.el (buffer-match-p): Optimise performance Date: Tue, 01 Nov 2022 19:11:03 +0000 Message-ID: <875yfyebi0.fsf@posteo.net> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=-=-=" Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="17938"; mail-complaints-to="usenet@ciao.gmane.io" To: 58950@debbugs.gnu.org Original-X-From: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Tue Nov 01 20:12:22 2022 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 1opwgP-0004TG-I7 for geb-bug-gnu-emacs@m.gmane-mx.org; Tue, 01 Nov 2022 20:12:21 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1opwg8-00061s-Pk; Tue, 01 Nov 2022 15:12:04 -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 1opwg7-00061f-AS for bug-gnu-emacs@gnu.org; Tue, 01 Nov 2022 15:12:03 -0400 Original-Received: from debbugs.gnu.org ([209.51.188.43]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1opwg7-0000KL-3R for bug-gnu-emacs@gnu.org; Tue, 01 Nov 2022 15:12:03 -0400 Original-Received: from Debian-debbugs by debbugs.gnu.org with local (Exim 4.84_2) (envelope-from ) id 1opwg6-00075b-Cq for bug-gnu-emacs@gnu.org; Tue, 01 Nov 2022 15:12:02 -0400 X-Loop: help-debbugs@gnu.org Resent-From: Philip Kaludercic Original-Sender: "Debbugs-submit" Resent-CC: bug-gnu-emacs@gnu.org Resent-Date: Tue, 01 Nov 2022 19:12:02 +0000 Resent-Message-ID: Resent-Sender: help-debbugs@gnu.org X-GNU-PR-Message: report 58950 X-GNU-PR-Package: emacs X-GNU-PR-Keywords: patch X-Debbugs-Original-To: bug-gnu-emacs@gnu.org Original-Received: via spool by submit@debbugs.gnu.org id=B.166732987727196 (code B ref -1); Tue, 01 Nov 2022 19:12:02 +0000 Original-Received: (at submit) by debbugs.gnu.org; 1 Nov 2022 19:11:17 +0000 Original-Received: from localhost ([127.0.0.1]:44250 helo=debbugs.gnu.org) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1opwfI-00074W-V9 for submit@debbugs.gnu.org; Tue, 01 Nov 2022 15:11:17 -0400 Original-Received: from lists.gnu.org ([209.51.188.17]:59336) by debbugs.gnu.org with esmtp (Exim 4.84_2) (envelope-from ) id 1opwfG-00074O-RO for submit@debbugs.gnu.org; Tue, 01 Nov 2022 15:11:11 -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 1opwfG-0005il-Jy for bug-gnu-emacs@gnu.org; Tue, 01 Nov 2022 15:11:10 -0400 Original-Received: from mout02.posteo.de ([185.67.36.66]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1opwfD-0000AZ-8s for bug-gnu-emacs@gnu.org; Tue, 01 Nov 2022 15:11:10 -0400 Original-Received: from submission (posteo.de [185.67.36.169]) by mout02.posteo.de (Postfix) with ESMTPS id D189A240103 for ; Tue, 1 Nov 2022 20:11:04 +0100 (CET) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=posteo.net; s=2017; t=1667329864; bh=X3hp3DOimqNA/sHJyFisRQo6gxIdDOOkG9TsQbnfutY=; h=From:To:Subject:Autocrypt:Date:From; b=QxhFbslYDteLXfV1DEw7k/qzVNyckFS9JRKAA4zRQ1lemsvdzPNsCXBXreaQivC1b bHkDrgh4qvTjW1hIsGDV/ia4OmriMP9ytfDtxqvic95668G5PkQoBv2nf7S7gqRCLb +oMH3Qv5bOV8Pkb4BBk6oOJaYrnp0qDEQr3ZBoyDXHyyg99pRbTaBaywVTxSheblTJ l5fpkBAtWbstp1gynXpnE7KIGPFWtjRFlVnp3uqQmsvxi70y891laqRCfMYq+hSsGs vVUODiCfwLRoXaGsxxha2e7zrryWLpZ7YzNEt6YaBJZEsU79c5FNBKLjHfKMDTHkkZ gCzDsIyufKVMw== Original-Received: from customer (localhost [127.0.0.1]) by submission (posteo.de) with ESMTPSA id 4N203r1jXYz6tmL for ; Tue, 1 Nov 2022 20:11:03 +0100 (CET) Autocrypt: addr=philipk@posteo.net; prefer-encrypt=nopreference; keydata= mDMEYHHqUhYJKwYBBAHaRw8BAQdAp3GdmYJ6tm5McweY6dEvIYIiry+Oz9rU4MH6NHWK0Ee0QlBo aWxpcCBLYWx1ZGVyY2ljIChnZW5lcmF0ZWQgYnkgYXV0b2NyeXB0LmVsKSA8cGhpbGlwa0Bwb3N0 ZW8ubmV0PoiQBBMWCAA4FiEEDM2H44ZoPt9Ms0eHtVrAHPRh1FwFAmBx6lICGwMFCwkIBwIGFQoJ CAsCBBYCAwECHgECF4AACgkQtVrAHPRh1FyTkgEAjlbGPxFchvMbxzAES3r8QLuZgCxeAXunM9gh io0ePtUBALVhh9G6wIoZhl0gUCbQpoN/UJHI08Gm1qDob5zDxnIHuDgEYHHqUhIKKwYBBAGXVQEF AQEHQNcRB+MUimTMqoxxMMUERpOR+Q4b1KgncDZkhrO2ql1tAwEIB4h4BBgWCAAgFiEEDM2H44Zo Pt9Ms0eHtVrAHPRh1FwFAmBx6lICGwwACgkQtVrAHPRh1Fw1JwD/Qo7kvtib8jy7puyWrSv0MeTS g8qIxgoRWJE/KKdkCLEA/jb9b9/g8nnX+UcwHf/4VfKsjExlnND3FrBviXUW6NcB Received-SPF: pass client-ip=185.67.36.66; envelope-from=philipk@posteo.net; helo=mout02.posteo.de 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, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action 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: , Original-Sender: "bug-gnu-emacs" Errors-To: bug-gnu-emacs-bounces+geb-bug-gnu-emacs=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.bugs:246803 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Tags: patch The below patch is based on a tangent discussion in bug#58839, the below patch was written in collaboration with Jo=C3=A3o T=C3=A1vora. It involves= an optimisation to `buffer-match-p' that dramatically speeds the execution of the function. This is important for the very least as `buffer-match-p' is used for displaying buffer. Running (benchmark-run 1000 (match-buffers "\\*.+\\*")) I previously got (22.822269875 178 15.524474267999977), and with the patch applied (0.27100275 2 0.1730835160000197). There are a few points that can be discussed: 1. Style. I wrap the defun in a let (or rather letrec) block to avoid littering the global namespace. It isn't necessary, and one could argue it makes debugging more difficult. 2. Caching policy. Caching is critical to this optimisation. Just using byte-compilation would cause the above test to slow down to (76.323692627 656 57.088315405). The question is if the hash map will collect too much garbage over time, and if there is a better approach that could be taken? In GNU Emacs 29.0.50 (build 3, x86_64-pc-linux-gnu, GTK+ Version 3.24.30, cairo version 1.16.0) of 2022-10-31 built on heron Repository revision: 462a66e79edcc34ecbeef7cc1604765adfdc038e Repository branch: feature/package+vc System Description: Guix System Configured using: 'configure --with-pgtk --with-imagemagick PKG_CONFIG_PATH=3D/gnu/store/ssg343s6ldqdwh30136pnawhbgd0cb6i-profile/lib/= pkgconfig:/gnu/store/ssg343s6ldqdwh30136pnawhbgd0cb6i-profile/share/pkgconf= ig' --=-=-= Content-Type: text/patch Content-Disposition: attachment; filename=0002-lisp-subr.el-buffer-match-p-Accelerate-using-byte-co.patch >From 0a9ddbcc6958fa7ed94456722a3eee65582a56b2 Mon Sep 17 00:00:00 2001 From: Philip Kaludercic Date: Tue, 1 Nov 2022 19:57:49 +0100 Subject: [PATCH] * lisp/subr.el (buffer-match-p): Optimise performance --- lisp/subr.el | 75 +++++++++++++++++++++++++++------------------------- 1 file changed, 39 insertions(+), 36 deletions(-) diff --git a/lisp/subr.el b/lisp/subr.el index 83e2e75c41..0dd7a814d9 100644 --- a/lisp/subr.el +++ b/lisp/subr.el @@ -7002,8 +7002,38 @@ string-lines (setq start (length string))))) (nreverse lines)))) -(defun buffer-match-p (condition buffer-or-name &optional arg) - "Return non-nil if BUFFER-OR-NAME matches CONDITION. +(letrec ((buffer-sym (make-symbol "buffer")) + (arg-sym (make-symbol "arg")) + (translate + (lambda (condition) + "Compile a CONDITION into a predicate function." + (pcase-exhaustive condition + ((or 't 'nil) + condition) + ((pred stringp) + `(string-match-p ,condition (buffer-name ,buffer-sym))) + ((pred functionp) + (if (eq 1 (cdr (func-arity condition))) + `(condition ,buffer-sym) + `(condition + ,buffer-sym + ,arg-sym))) + (`(major-mode . ,mode) + `(eq (buffer-local-value 'major-mode ,buffer-sym) + ',mode)) + (`(derived-mode . ,mode) + `(provided-mode-derived-p + (buffer-local-value 'major-mode ,buffer-sym) + ',mode)) + (`(not . ,cond) + `(not ,(funcall translate cond))) + (`(or . ,conds) + `(or ,@(mapcar translate conds))) + (`(and . ,conds) + `(and ,@(mapcar translate conds)))))) + (cond-cache (make-hash-table :test 'eq))) + (defun buffer-match-p (condition buffer-or-name &optional arg) + "Return non-nil if BUFFER-OR-NAME matches CONDITION. CONDITION is either: - the symbol t, to always match, - the symbol nil, which never matches, @@ -7022,40 +7052,13 @@ buffer-match-p to be met. * `or': the cdr is a list of recursive condition, of which at least one has to be met." - (letrec - ((buffer (get-buffer buffer-or-name)) - (match - (lambda (conditions) - (catch 'match - (dolist (condition conditions) - (when (pcase condition - ('t t) - ((pred stringp) - (string-match-p condition (buffer-name buffer))) - ((pred functionp) - (if (eq 1 (cdr (func-arity condition))) - (funcall condition buffer) - (funcall condition buffer arg))) - (`(major-mode . ,mode) - (eq - (buffer-local-value 'major-mode buffer) - mode)) - (`(derived-mode . ,mode) - (provided-mode-derived-p - (buffer-local-value 'major-mode buffer) - mode)) - (`(not . ,cond) - (not (funcall match cond))) - (`(or . ,args) - (funcall match args)) - (`(and . ,args) - (catch 'fail - (dolist (c args) - (unless (funcall match (list c)) - (throw 'fail nil))) - t))) - (throw 'match t))))))) - (funcall match (list condition)))) + (funcall (or (gethash condition cond-cache) + (puthash condition + (byte-compile + `(lambda (,buffer-sym ,arg-sym) + ,(funcall translate condition))) + cond-cache)) + (get-buffer buffer-or-name) arg))) (defun match-buffers (condition &optional buffers arg) "Return a list of buffers that match CONDITION. -- 2.38.0 --=-=-=--