From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: =?utf-8?Q?Gerd_M=C3=B6llmann?= Newsgroups: gmane.emacs.devel Subject: Re: Gap buffer problem? Date: Wed, 11 Dec 2024 14:22:47 +0100 Message-ID: References: <8634iwex8q.fsf@gnu.org> <86wmg7bso1.fsf@gnu.org> <87cyhzmzbp.fsf@telefonica.net> <87bjximwnj.fsf@protonmail.com> <87ttbal9qx.fsf@protonmail.com> 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="8140"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Cc: "Pip Cet via \"Emacs development discussions.\"" , =?utf-8?Q?=C3=93scar?= Fuentes To: Pip Cet Original-X-From: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Wed Dec 11 14:23:45 2024 Return-path: Envelope-to: ged-emacs-devel@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 1tLMgr-0001uu-0F for ged-emacs-devel@m.gmane-mx.org; Wed, 11 Dec 2024 14:23:45 +0100 Original-Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1tLMg4-00035O-Jn; Wed, 11 Dec 2024 08:22:56 -0500 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 1tLMg2-00035G-Nx for emacs-devel@gnu.org; Wed, 11 Dec 2024 08:22:54 -0500 Original-Received: from mail-wr1-x42b.google.com ([2a00:1450:4864:20::42b]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1tLMfz-0006KS-F9 for emacs-devel@gnu.org; Wed, 11 Dec 2024 08:22:54 -0500 Original-Received: by mail-wr1-x42b.google.com with SMTP id ffacd0b85a97d-385e3621518so4280685f8f.1 for ; Wed, 11 Dec 2024 05:22:50 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20230601; t=1733923370; x=1734528170; darn=gnu.org; h=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=Zz0QsLeGzUlZHymoAgeAflE9mbKKVX8dkwEiFaDNMAA=; b=e7wRrpUXp+B/pdhNP9Qu8+MlAbiUHBRpFLF5ww2y2eiNkehsvZc3VstmUjMS6tGPFr rWYUqIkCvq7zEaQBwt9SFR12E/oUR8uGDD8HPek9JXp+6dD+7vvzgVTqLfAc/+abQ0Zs 2uCayVdI8Wmpkw97G50dTDZ8a7MDcjM5D8rqG+LGOCpX/sQxQomEai+trLQapLZAaQQr o6AhPhAlboWTHHVCANYUsL0YqTnHvaPyDrBFn4A3+eHiUyKBwxBFk4pfKE3hFuRdIWI7 yFM2LkM7pR90DKWnqC0NoagL6yOPUlxTzWDcfyWATNpwxTpHavpITOvuSij13i5LHd9D ccFQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1733923370; x=1734528170; h=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=Zz0QsLeGzUlZHymoAgeAflE9mbKKVX8dkwEiFaDNMAA=; b=kaU544smUtWUlO/26Gtro3je6j/7AXw7eWH5+nR0b49pcmNxvESlE6PK1wgfhctSwJ mZ+KeRVQCPvyaZ+H7MUC9SPKmH3RK1te3/O2Kh2Eb3CHCUSiJH1QTm3XsU9NKuKqUfxQ xyeLnjXK1FSeCHmjppWxXDEMOefXteM63gFte5BxH8AP6SqUCX8s3p6raZro21wMDbxT vYbSX+RqayyJb3AylvCQ9ceKn6Ce9n/O8UJZefZ+tOxRNxbCkuWt3PQR4TJb2ccTZ1Qm ZIF1fuqtQBxV8dfNEGRiduylxSeR1Ok22ULwyFr/5N4L5z3m78uD+XHx3ec8zCigpxpL PfKg== X-Gm-Message-State: AOJu0YyMQjg+cE5ReYfcFB/NrINwThPo3WArfNBB6eE1qkY81zx3Bbjx sQWw7nZLXexMi7SwALeLaYK3exLm8zh5Z9cfuFzc6s25PqyiIh4+qY1Q5A== X-Gm-Gg: ASbGnctxrcjtv32at04lEEldjYtVDlm9M1ngNJGij+pGBwTxc9Zh7Zc4kkItlKbSSZU qA4wUd1cOE8XRySkxdI/1E10vacfbltDYx1f46uk95gPc9WiBObEZ7eEQJzqjOWsktFEIBBsRDf RAzZbuXtSlGw5XNdtlBZZj8U+eLg99iFGhmLd7G9KL9SLyL+QBE+/4GkyQknNLeTN8l5dt7ym7K otkIAGDktu54fgM99BPCxoW0FmiP1LrhPopp+fpmzykHuJDO7g35d6xWeETH311aNWLyw8vg5AV WcU/j9XzXMzZQfiiFMISZyMMhC7DL0DdDDHGIEI6DhPzDNonPFTkazajEqjsqao= X-Google-Smtp-Source: AGHT+IFMZKXhaqm2TfOj5mrQQP71PWCjFvoCJjbr+yuCcE9UnFRkWSCoVk+oQCsjQi9w+ybM/Lh9rw== X-Received: by 2002:a5d:47a1:0:b0:385:f8bd:6e80 with SMTP id ffacd0b85a97d-3864ceab394mr2270746f8f.56.1733923368972; Wed, 11 Dec 2024 05:22:48 -0800 (PST) Original-Received: from pro2 (p200300e0b709ba00c5d5596d9959c8a7.dip0.t-ipconnect.de. [2003:e0:b709:ba00:c5d5:596d:9959:c8a7]) by smtp.gmail.com with ESMTPSA id ffacd0b85a97d-3878248e61dsm1284307f8f.21.2024.12.11.05.22.47 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 11 Dec 2024 05:22:48 -0800 (PST) In-Reply-To: <87ttbal9qx.fsf@protonmail.com> (Pip Cet's message of "Wed, 11 Dec 2024 11:50:46 +0000") Received-SPF: pass client-ip=2a00:1450:4864:20::42b; envelope-from=gerd.moellmann@gmail.com; helo=mail-wr1-x42b.google.com X-Spam_score_int: 0 X-Spam_score: -0.1 X-Spam_bar: / X-Spam_report: (-0.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, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URI_DOTEDU=1.999 autolearn=no autolearn_force=no X-Spam_action: no action X-BeenThere: emacs-devel@gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: "Emacs development discussions." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Original-Sender: emacs-devel-bounces+ged-emacs-devel=m.gmane-mx.org@gnu.org Xref: news.gmane.io gmane.emacs.devel:326352 Archived-At: --=-=-= Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable Pip Cet writes: > Gerd M=C3=B6llmann writes: > >> Pip Cet writes: >>> if we ever replace the gap buffer code, we should make sure its >>> replacement actually handles buffer text and text properties/intervals >>> in an integrated manner, rather than storing just buffer text). >>> >>> Pip >> >> And if I may add a wish to the future author: Make whatever you use >> persistent data structures, so that one could think of letting redisplay >> run concurrently. Really! :-) > > You won't be surprised to hear I've been playing with some code,=20 Indeed, I was just thinking to myself "I knew it" :-). Two thumbs up! > so could I ask you to expand on this point? What precisely does > redisplay require? Full snapshotting or would it be sufficient to have > fine-grained locking? Maybe it's helpful when I tell something about the background. Some time last year I asked myself if I could make Emacs more than one of my plenty of CPU cores without solving the multi-threaded Elisp problem. And the idea was that I could do that, possibly, by letting redisplay happen in another thread. I later realized while thinking about the details, that this undertaking is an order of magnitude too large for me. Everything taking more than a few months is. And, in addition, I wouldn't want to do data structures in C anyway. So it's history. Won't happen. But, there is an incomplete, terse, terrible Org file from those times that I kept. I talked a bit about this with Stefan Monnier and Eli at the time, just FYI.=20 --=-=-= Content-Type: text/x-org Content-Disposition: attachment; filename=20230926161343-concurrent_redisplay.org Content-Description: Concurrent redisplay :PROPERTIES: :ID: E5E87FA1-48D1-4753-AAAE-E86FB36F5742 :END: #+title: Concurrent Redisplay # -*- mode: org; eval: (auto-fill-mode 1) -*- #+STARTUP: content #+AUTHOR: gerd@gnu.org * Concurrent Redisplay Redisplay is currently performed sequentially as part of Emacs' command loop. The command loop calls =redisplay= to make sure that changes in buffers are made visible on the screen. Concurrent redisplay means to change Emacs' architecture, so that redisplay can be done concurrently with the command loop and running Elisp. In this document, I'm trying to get an impression if a parallel redisplay is achievable, from a very high-level perspective at least. To make thinking about this possible, I make a number of assumptions and simplications, which are described in the following. ** Multi-threaded Lisp This document is no way concerned with making Elisp multi-threaded, if that's possible, if so how, and what else. Due to demand from others, I'm also considering the case that a concurrent redisplay can call Lisp. How this is made possible, I'm not considering. ** Possible Gains - Distribute work on more than one CPU core - Makes it possible to implement advanced display features in the future that would be too costly to perform in a sequential redisplay. ** Concurrency Architecture As a simple to reason about architecture, I assume that Emacs will consist of two modules: - The =main= module consists of command loop and Lisp, and runs in one thread. - The =redisplay= module runs in another thread. Both modules are isolated from each other, and may not access data owned by the other module. Communication between modules only happens by exchanging non-blocking messages. I could imagine a GUI/TUI backend model in this picture, for good measure, but won't consider that further. Random links: The Problem with Threads https://www2.eecs.berkeley.edu/Pubs/TechRpts/2006/EECS-2006-1.pdf Plain Threads are the Goto of Modern Computing https://isocpp.org/blog/2014/12/plain-threads-are-the-goto-of-todays-computing ** Display Model Concurrent redisplay in the architecture described must work on a model that it owns. It is assumed for now, that this model represents a buffer's text plus a number of properties/variables relevant to redisplay, like faces that apply to regions of text. See [[*Redisplay Model]]. ** Triggering Redisplay Concurrentl redisplay could choose to display at its own whim, or triggered by receiving a message from the main module. It could, for example, decide to redisplay based on available hardware frame rates. How this is done is not considered here. ** Display Update Roughly speaking, current redisplay can be divided into two parts: - Produce desired glyphs, which describe what the display should look like. - Update the display by comparing current and desired glyphs and calling the GUI/TUI backend(s). Then set the current glyphs to the desired glyphs for the next round. The update part is not considered in the following. There are several conceivable ways to implement an update: - Update in the =redisplay= module * Call GUI backend directly * Post messages to the =main= module, which calls GUI backend * Post messages to a possible GUI module - Update in the =main= module + =Redisplay= posts message containing desired glyphs This looks like a solvable problem to me. So, for simplicity, I don't consider it here. In the following, "redisplay" mainly refers to producing desired glyphs. ** One Window/Buffer For simplicity, I only consider one window displaying one buffer. An interesting, maybe even natural, idea might be to run more than one redisplay in parallel, one for each window, but that is also not in scope here. ** Frame-based Redisplay Also not considered here is the update phase of TTY frames, which currently requires a view of all windows on a frame at once, which is commonly called frame-based redisplay. * Aspects to Consider The following is a list of things to consider when thinking of making redisplax concurrent. ** jit-lock Current redisplay calls run =fontification-functions= to ensure that properties are up to date for the text being displayed. This will not be possible in a concurrent redisplay, unless one assumes that Lisp can be called from multiple threads. Stefan (and Eli?) thinks we will eventually need to be able to call some Lisp-ish code from a concurrent redisplay before it can fully replace the existing synchronous redisplay. I myself would accept a display that is not always 100% accorate, for exmaple because parts of the text have not been fontified yet, or compositions determined. Instead of calling Lisp from redisplay, one use background fontification in the main module together with guesstimates which regions of text will actually be displayed to make sure that fontification results are visible as soon as possible. The redisplay module could also post messages to guide this guessing, for example at the end of redisplay. ** Hooks and functions In general, the idea is that =redisplay= posts messages to the =main= module that certain things have happened. Hooks/functions run by current redisplay are: - window-scroll-functions - activate-menubar-hook (redisplay_internal -> prepare_menu_bar -> update_menu_bar) - update-menubar-hook (update_menu_bar) - fontification-functions (jit-lock, and maybe others) - ? Open: what are the expectations of these hook function about variables, buffers? ** Caches Redisplay needs access to face, font and image caches which are stored on frames (owned by main module). I propose as an idea to remove the caches from frames and give ownership of these to concurrent redisplay. Could be a table frame -> caches. Some communication is necessary from the main module to redisplay for frame changes, clearing caches from Lisp, .... - does face/font/image code called during redisplay call Lisp? - can face etc. code be run from another thread? ** Glyph matrices Glyph matrices are a form of cache, so they should be treated likewise. Depends on which module does the update phase of redisplay. ** Point and mark Needed for region highlighting. Create new model version when changing these. This requires that creating new model versions is reasonably fast. ** window-start computation Redisplay posts message back to main module containing information about what is on the display. Window start/end could be part of that. ** move_it functions This concerns Lisp functions like vertical-motion. Rely (relied?) partly on current glyph matricx, and otherwise on redisplay functions that are used without producing glyphs. - do expect results based on current text, even if not displayed yet. Open. No solution in mind that isn't ugly (locking, maybe). - need display model to operate on. - Pixel positions in text? ** Mouse highlight Open. No idea how that is done nowadays. It used to use the current matrices, only. ** TTYs The update phase of redisplay on ttys needs a view of the whole frame's current and desired glyph matrices for optimization. This is done by giving tty frames matrices, and sub-allocating window matrices from these. The descriptions above are not affected by this, but it has to be kept in mind, for the update phase, which is not yet taken into account. ** minibuffer, reading from Seems to be all the same as other windows, but open. ** Echo area Open (-> window geometry?) ** Bidi Eli says: #+begin_quote I think this can be removed from the list of issues. Basically (with a few caveats, see below, which I don't think change anything in principle), bidi.c is just a subroutine of set_iterator_to_next, which implements the non-linear scanning of buffer text needed for bidi reordering. It effectively causes set_iterator_to_next to move to the next character in _visual_ order, not in buffer position order (the latter would require just incrementing the buffer position). To do this, bidi.c needs access to buffer text, and little else. The caveats I mentioned are: . sometimes we need to figure out the base paragraph direction, either L2R or R2L (the latter will be displayed with characters starting at the right edge of the window instead of the left), in this case bidi.c looks back using regexps for the beginning of the paragraph, because the Unicode Bidirectional Algorithm mandates that the paragraph direction is determined by the first strong directional character of the paragraph . when the buffer includes display properties, bidi.c treats all the characters "covered" by the property as a single neutral character, since this is how images and other such stuff needs to be handled for display reordering purposes -- this requires partial processing of display properties for the single purpose of determining whether they are "replacing" or "non-replacing" properties, and in the former case to determine at which buffer position the display property ends I don't think these caveats change anything, since again they only need to access buffer text. The bidi reordering code maintains a state (struct bidi_it), but it is a sub-structure of struct it, and lives only as long as the iterator object lives. #+end_quote ** Narrowing Don't remember how that is done. ** Selective display Open. Should at long last die. ** Window geometry changes Open. ** Others? * Redisplay Model What is being displayed and how it is displayed depends on - buffer text - Properties of the text (overlays, text properties) - Values of display-relevant variables (=truncate-lines=, ...) Concurrent redisplay mustown such a model, so that no synchronization is necessary between =main= and =redisplay= module. ** Buffer Text *** Copying One could think of making copies of all what is needed for redisplay and let concurrent redisplay work on such a model. I believe this is out of question, for performance reasons. Such a copy would have to be made by the main module, and that could easily cost more than what what we do now in sequential redisplay, especially if we don't exactly know what data redisplay will need (range of text, for example). *** Another "Copying" Possibility Stefan Monnier had another interesting idea that I quote here #+begin_quote Note that you can also use the current text representation with a concurrent redisplay: simply keep a whole copy of the buffer over in the redisplay side. Updating that whole copy should usually be quite efficient thanks to BEG/END_UNCHANGED. #+end_quote *** Persistence To avoid copying, let buffer text be represented as a persistent data structure. Conceptually, this persistent data structure contains an ordered set of buffer-text versions. When the =main= module modifies buffer text, new versions are created. When =redisplay= starts, it picks the youngest version available as buffer zexz. because it is known that any modification in =main= will lead to a new version, and not modify an existing version. The "piece table" is an interesting representation for such a persistent buffer text data structure. Some later descriptions assume that buffer text uses a persistent piece table. Some links: An interesting paper about text representations in general: https://www.cs.unm.edu/~crowley/papers/sds.pdf Piece tables: https://www.averylaird.com/programming/the%20text%20editor/2017/09/30/the-piece-table An implementation of a persistent piece table: https://github.com/cdacamar/fredbuf A blog post about VSCode using piece tables: https://code.visualstudio.com/blogs/2018/03/23/text-buffer-reimplementation An implementation of a persistent tree: https://cglab.ca/~dana/pbst/#:~:text=A%20persistent%20binary%20search%20tree,into%2Fdeletion%20from%20the%20tree. ** Properties (Overlays + Text Properties) Properties that are relevant for redisplay are: - =face= - =invisible= - =display= - =composition= Redisplay needs the following information about properties: - start + end position - property value Property values can contain constructs that eval Lisp. Examples: - display (=:when=, =(:height FN)=, ...) - =mode-line-format= may also contain =:eval= If concurrent redisplay cannot call Lisp: The parts of the property values that require evaluating Lisp must be part of the display model in evaluated form. Such a model could contain a map =Lisp_Object= -> =value= (at the time the model version was current), where - the key =Lisp_Object= is the part of the original property value containing =:eval=, for instance. It could be the =cons= cell of an =(:eval ...)= - =value= is the evaluated value Changing properties must create new model versions. - adding/removing/changing props -> new model version - each piece in a piece table could have a list of applicable props for the whole piece. - mass changes could be done without producing lots of new model versions + requires that concurrent redisplay doesn't work on a model that is mass-updated, which could require synchronization, which is ugly. Possible optimizations: - discard/coalesce old model versions in the background, to reduce memory footprint? The main module creates new versions, only. Redisplay uses only the latest version. ** Variables The display model must also contain a snapshot of the values of all relevant variables at the time of the model version. Relevant values are: - truncate-lines - scroll-conservatively - window, frame, buffer, global values (window-start, ...) - ? - todo. make a list * Persistent Data Structures Wikipedia: https://en.wikipedia.org/wiki/Persistent_data_structure ** Terminology Short summary of the terminology: - persistent + general term encompassing veriations below + always preserves versions of itself when modified. + immutable in the sense that they are not changed in-place. - partially persistent + all versions can be read + only newest version can be modified. - fully persistent + all versions can be read + every version can be modified. - confluently persistent + fully persistent + versions can be merged (melded). ** Links Kind of a brief overview: https://academic-accelerator.com/encyclopedia/persistent-data-structure Irmin: Mergeable ropes https://inria.hal.science/hal-01099136v1/document Intersting article: https://blog.acolyer.org/2015/01/14/mergeable-persistent-data-structures/ Partially and fully persistent DS in C (no merges) https://github.com/vineeths96/Persistent-Data-Structures Confluently persistent DS paper https://arxiv.org/pdf/1301.3388.pdf https://www.cs.utexas.edu/~ecprice/papers/confluent_swat.pdf Data visualization with persistent DS https://www.researchgate.net/publication/258713092_Efficient_Dynamic_Data_Visualization_with_Persistent_Data_Structures * Redisplay calling Lisp This is a hypotheical scenario, but Eli and Stefan seem to assume that it is important to have to make concurrent redisplay acceptable to users. - Redisplay calls Lisp to fontify etc. + just assuming that is possible in the future + as a substitute for storing a snapshot in display model. + how calling Lisp from redisplay works on the Lisp side, is not yet specified My conclusions from this: - Properties must be persistent data structures + because no props snapshot in display model + because redisplay needs props corresponding to its buffer-text version - Properties must be confluently persistent data structures + need to be able to modify prop versions in Lisp + need to merge back changes into current versions - buffer modifications from Lisp either + should be prevented (how?) + or buffer-text must be confluently persistent - merge or discard any buffer-text changes (delete version, if it was created). Probably discard. - what about if Lisp changes display-relevant variables? - unclear - Other modifications? ** Merging properties Imagine =fontification-functions= adding properties for font-lock. These modifications should not be lost once concurrent redisplay has finished. That means the properties added to an old version of the buffer text etc must be merged into newer versions. - Confluently persistent props require + way to merge changes to newer versions + consider only merge version n-1 to n - single prop = (beg end value) + position translation - know what changed in buffer-texts from n-1 to n + wanting translation pos_{n-1} to pos_n + piece added in n in front of pos_{n-1} => add length + piece delete in from of pos_{n-1} => subtract + details depend on buffer-text DS - buffer-text DS must take into account that translations must be possible - looks doable + value merging + assume interval [beg end] in the following (including beg and end) + added property - [beg_n end_n] may intersect with 0+ props in version n. - say first intersection is in [a b], a >= beg, b <= end with value val - [beg a-1] -> new value - [a b] -> value-dependent handling of old/new value (merge/discard..., must be defined) - [b+1 end] -> either new value or merge with next intersecing prop from n + changed values - treat as remove + add + removed props - no direct representation in version of props in version n-1 - assume scan whole version n for prop of the same kind - could record min/max pos of changes in n-1 - let [a b val] be "interesting" prop in n (face, ...) - if there is no intersecting prop in [a b] in n-1, what does that mean? - it has been newly added in n compared to n-1 - it was in n-2 and been removed in n-1 - must find out to resolve + can we in all cases? Assuming everything still open can be resolved, this looks doable, but it is certainly non-trivial. * Performance/Memory Considerations The use of persistent data structures will have an impoact on both performance and memory consumption. How large this impact will be I find impossible to tell, especially on older hardware. But keep in mind, that at the time this might be implemented, current hardware will be old. * Personal Conclusions I'm stopping here, despite open questions, because I think I have reached a sufficient level of gut feeling about the subject. I'd summarize my thoughts as: - Concurrent redisplay is feasible, both with and without being able to call Lisp from redisplay. - Changing buffer-text representation using a piece table is a big enough bite that it is only worth it only if a concurrent redisplay comes at some point. - If performance on old hardware will be acceptable, for some value of acceptable, I find unpredictable. - Concurrent redisplay with the ability to call Lisp from redisplay is considerably more complex than without being able to call Lisp. I'd say at least 2 times. - Concurrent redisplay will not happen unless at least 2 or 3 people with enought time decide to work on it. * Random Grab Bag - make pieces for long lines (max length of piece) - concurrency -> dump complicated redisplay optimizations? - pieces provide more detailed information about what text has changed (compared to BEG_UNCHANGED and END_UNCHANGED). Zed editor, rasterization on GPU https://zed.dev/blog/videogame # end. --=-=-= Content-Type: text/plain It's probably not very helpful, but at least I get the idea of a concurrent redisplay planted into brains, where it can do it's evil work :-). > > (However, before anyone gets their hopes and/or fears up, my code > depends on disabling most of the regexp code, and the additional number > of garbage-collected objects is so great that I concluded I'd wait for > MPS to land before resuming work on it. One of the few distinct > advantages of the current gap buffer approach is that it doesn't affect > GC...) > > I know virtually nothing about redisplay. > > Pip What I've written is pretty high-level, nothing to worry about. --=-=-=--