back

by raphlinus·9y ago·view on hn ↗
Hi Jon! Great to see you here. Much of what I wrote is speculative, especially paren matching based on monoids. What actually went into xi editor is much more conservative. I didn't actually intend this to be posted to HN, but am not too surprised it did.

As to being a young person, I don't know if you remember, but I was already of drinking age when you and me and Adam Sah hung out a bit and talked about the "rush" language.

I admit to being excited, but because I think "modern" editors really are too bloated and slow and it causes a thousand paper cuts throughout the day, and I think that can be fixed.

1 comments
Oh you're that Raph! Hi.

Sorry for presuming age + experience level, it's how this came across to me. Actually I think Rush is a prime example of "excited about general ideas that turn out not to be right or relevant to much". But we were students, and I guess that is what students often do.

I agree modern editors are too slow and bloated. I would write one if I didn't have way too many other things happening. But I don't think they are slow and bloated due to a lack of computer science concepts. I think they are slow because most of the world, over the last 25 years, has lost the art of writing software that is remotely efficient.

If I were to write an editor, it would store text as arrays of lines (since lines are what you care about) with maybe one level of hierarchy, such that each 10k lines of the file are in one array. I think that would be fine and if it ran into problems with very large files, relatively minor modifications would take it the rest of the way. (Of course this is untested but I feel pretty confident about it). Rather than calling malloc all the time, a specialized allocator would be in play.

I do think it's a good idea to make a better editor so I wish you good luck with that (dude I am so sick of emacs).

I used an array of lines in gzilla[0]. It's not bad, but it _is_ exporting details of the representation up to clients, which gets worse once you add some hierarchy. To me, the nice thing about ropes is that they appear to the client as just a string, with some fancy added methods such as creating a cursor that can advance to the next or previous line efficiently. Of course, to make this work, you need a good programming language; an implementation of ropes in C would be painful.

As I said elsewhere on the thread, the good thing about ropes is their worst case performance. Super-long line? Rope still efficient. 10 million line file? Rope still efficient. Massive sequence of edits relative to the pristine file? Rope still efficient. It's pretty easy to write code which works well in the common cases but then degrades when things get interesting. I'm not going to apologize for caring about that.

[0] http://www.levien.com/free/gzilla-tour.html

But ... in a text editor you care about lines most of the time.

This is what I object to about the rope representation -- it intentionally destroys this information that you actually want available most of the time. I don't think that's nice at all.

It's possible you could make the rope work better in this sense by annotating each piece... I dunno, haven't thought about it.

As for the worst-case performance thing ... I think my scheme would do fine with super-long lines or 10 million line files. But dude, I don't even have an editor today that works okay on 10k-line files, and I don't think it's the internal data representation that's the problem, I think it's because of all the other decisions that get made (or lack thereof).

I have no idea what you mean about "intentionally destroying" line info. The info is right there, and there's a perfectly nice interface (Cursor) for getting at it; no real difference between calling next() on a Cursor object and doing line_index++.

Besides, what's a "line"? Is it a source line, or a visual line after wrapping? In an editor, you care deeply about both, depending on what exactly you're doing. With an array of lines, you pick one for the representation, and when you want the other one, it's quite painful. With ropes, no problem at all, just two different Cursor objects into the same rope.

I agree, other decisions besides buffer representation are important, and I'm doing my best to get those right too.

>> and when you want the other one, it's quite painful.

It's really not that painful. A logical line of text may span multiple visual lines because of word wrapping. A visual line will never span more than one logical line. So you always have a 1-to-N relationship between logical and visual lines, and everyone knows you have to go to M-to-N before things get objectively painful.

Here's the thing about text editors: they are extremely well known problems. It's really hard to say anything about writing a text editor is "difficult" when we have hundreds of examples of free, open source software that we can sit with and analyze for requirements. There really aren't many new lessons to learn, certainly not in the memory representation for the file.

It's really nice to talk about parallelizing your text editor operations, but here in the year twenty thousand and seventeen, Vi is still single-threaded and not at all hardware accelerated and it still runs essentially infinitely faster than most other text editors. The only time Vi's single-threadedness becomes a problem is when plugin authors can't be arsed to not load up Python.

What data structure does Vi use? An array of lines.

What other than computer science concepts can save us from slow software? Computer science concepts (Amdahl and Moore, maybe Dennard, maybe-maybe Landauer) have proven that hardware improvements cannot. Is there some aspect of the software performance that can only be understood through another domain of human endeavor?
I am not trying to be anti-intellectual, but software currently has the opposite problem, where people decide some idea will Make Everything Better and it turns out that this idea does nothing of the kind. In fact some of these ideas have set software engineering back by decades (example: Object-Oriented Programming).

There are, of course, computer science concepts that are very smart. But we don't need these to save us from slow software, because today's slow software problem is just the result of people doing bad things in layer upon layer. We have to stop doing all the bad stuff and dig us out of the hole we're in, just to get back to neutral. Once we are back at neutral, then we can try thinking about some computer science smarty stuff to take us forward.

See? Now you're sounding like an old fart :-)

You give an example of Object-Oriented Programming as an idea that has software engineering idea back by decades but really isn't it the misapplication of that tool that does the damage? Consider that time and again software engineers have developed a code base of functions which all need a bit a shared state, and technique of calling all those functions while including a reference to the 'context', was more simply expressed as calling a function "from" the context itself?

The tools help with the cognitive burden of understanding the entire system. And tools that allow one to make durable assumptions about part of the system allow the engineer to 'free up' space in their brain for other parts of the system. That desire to add abstraction in order to 'move up' the conceptual tree and get a wider view of the overall system has been part of how humans think since they first started collecting into tribes[1].

Certainly "over abstracting" is a huge issue. There was a great story about the Xerox Star system (first word processor that was multi-lingual and multi-fonted) that Dave Curbow used to tell about how the 'call stack' to get a character on the screen had reached insane levels (and that made things very slow). All due to abstraction. And yet there are good examples too where at Sun the adding of support for the 3b2 file system was accomplished quickly, and everything still worked, due to the Virtual File System (VFS) abstraction.

My point is that it isn't the tools that set computer science back, it is the misapplication of them that does that. And what I liked about Raph's discussions on Xi is the exploring and testing whether or not a tool he had available was applicable to writing text editors.

[1] Can you imagine the challenge of having to talk to someone in the tribe for 10 minutes to determine what their role was and capabilities? So much easier to say "You're a hunter right?" and when they say yes just assume various hunter capabilities are available.

This just points to a problem that computer science concepts need to address: the conflation of subroutines (reusable components of programs) and runtime calls/returns. Or, stated more directly, programmer control over inlining and other costs, on the way to enabling more zero-cost abstractions.

One big problem is that one can't deploy the existing methods of zero-cost abstraction (templates/monomorphized generics) across process boundaries or the kernel/userspace boundary. Let's work on this, not act as if abstractions themselves are the problem.

(As an aside: I think the "implementation inheritance" aspect of OOP is at least as harmful as jblow suggests. "Associate related pieces of data with the code that operates on them as a unit" is a pretty reasonable idea on its own.)

> In fact some of these ideas have set software engineering back by decades (example: Object-Oriented Programming)

I don't want to sound like I want to oppose you here, but I would be genuinely interested about on your write up about OOP setting engineering back by decades. Could you elaborate, please?

is just the result of people doing bad things in layer upon layer.

You can make a decent argument that's the only realistic way extremely large systems like the web can possibly come about. It's not pretty but the track record of the alternatives is worse.

The context of this discussion is about "a high quality text editor".

Of course in the name of not using the same golden hammer for all problems, extremely large systems like the web and text editors should each be considered in their own rights for the best solution for each of those.

I know. But you can also substitute 'long-lived' for 'extremely large', etc. 'People have lost track of the importance of efficiency/performance' is a recurring point of jblow's. There's something to it, no doubt, but I think it also merits some pushback.
I don't think "long-lived" is a good substitute for "extremely large". The longer something lives, the better it should be, for multiple reasons -- more time to work on the code, more design iterations, more-thorough understanding of the problem gained over time. If the code is just getting more messy and decayed and hard-to-deal-with over time, then we are doing something wrong. (And we almost always are).

I'm not just saying that people have lost track of the importance of efficiency. I am saying they've lost track of how to actually do it. I think at least 95% of the programmers working in Silicon Valley have no practical idea of how to make code run fast. Of the remaining 5%, a very small number are actually good at making code run fast. It's a certain thing that you either get or don't. (I didn't really get it when I started in games, even though I thought I did ... it took a while to really learn.)