emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2 00/16] Speeding up DEFVAR_PER_BUFFER


From: Spencer Baugh
Subject: Re: [PATCH v2 00/16] Speeding up DEFVAR_PER_BUFFER
Date: Sun, 22 Nov 2020 11:28:27 -0500

Eli Zaretskii <eliz@gnu.org> writes:
> Thanks, but could you perhaps provide a more detailed overview of the
> general idea of the changeset?  It is not easy to glean that from 16
> patches, each one describing only the details of its narrow goal.
> Please include in the more detailed overview indications what parts of
> the series are really needed to speed up buffer-local variables and
> which are cleanups in the areas of the changes not directly related to
> speeding things up.

Patch 1 and 2 are tests; patch 15 is the speed-up change. Patches 3
through 14 all change the existing abstractions so that patch 15 can be
small, and should have no impact. Patch 16 is a followup further cleanup
enabled by 15. Only 15 should have any meaningful performance impact.

>> I have an idea which would allow avoiding the mass change, if that's
>> desired, which also has some additional benefits.  We could define
>> getter functions (marked as inline) for each Lisp_Object field, and
>> have BVAR call those field-specific getter functions by forming the
>> name of the getter through token pasting.  The boilerplate of the
>> getters would be kept under control by using an X macro to define both
>> the fields in struct buffer and the getters. Something like:
>> 
>> #define FIELD_LIST \
>>   C_FIELD(name) \
>>   C_FIELD(filename) \
>>   ...
>>   LISP_FIELD(mode_line_format) \
>>   ...
>> 
>> And then "instantiating" FIELD_LIST twice in two different contexts to
>> define the Lisp_Object fields and the getters.
>
> I don't think I have a clear idea of what will this mean in practice.
> Can you show an example of its usage?

There is a decent example on https://en.wikipedia.org/wiki/X_Macro

In our case, it would be something like
struct buffer {
#define C_FIELD(field) Lisp_Object field;
#define LISP_FIELD(field) Lisp_Object field;
       FIELD_LIST
#undef C_FIELD
#undef LISP_FIELD
}

#define C_FIELD(field) Lisp_Object bget_ ## (struct buffer *b) \
{ return b->field ## _; }
#define LISP_FIELD(field) Lisp_Object bget_ ## (struct buffer *b) \
{ return bvar_get(b, offsetof(struct buffer, field)); }
       FIELD_LIST
#undef C_FIELD
#undef LISP_FIELD

#define BVAR(b, field) bget_ ## field (b)

>> Regardless of what approach we take, at least some level of
>> benchmarking will be necessary.  Is there an established benchmark
>> suite for these kinds of changes?
>
> Is benchmark-run what you are after?  Or are you asking what use cases
> of buffer-local bindings to use inside the benchmark?  If the latter,
> then I guess some simple example with binding case-fold-search
> followed by some regexp search would do, if you do that with various
> numbers of live buffers in the session.

Ah, no, I mean benchmarking the rest of Emacs to see the impact.  I've
already benchmarked these changes on the case they're intended to fix.
Old results, but no change in this iteration:

(benchmark-run 500000 (let ((case-fold-search nil)) (string-match "" "")))
; unpatched emacs: (0.6872330339999999 0 0.0)
; patched emacs: (0.608068564 0 0.0)
(setq my-buffer-list nil)
(dotimes (idx 1000) (push (get-buffer-create (format "test-buffer:%s" idx)) 
my-buffer-list))

(benchmark-run 500000 (let ((case-fold-search nil)) (string-match "" "")))
; unpatched emacs: (18.591189848 0 0.0)
; patched emacs: (0.5885462539999999 0 0.0)
        



reply via email to

[Prev in Thread] Current Thread [Next in Thread]