Skip to content
This repository has been archived by the owner on Mar 3, 2023. It is now read-only.

Render lines via tiles #6733

Merged
merged 68 commits into from
Jun 2, 2015
Merged

Render lines via tiles #6733

merged 68 commits into from
Jun 2, 2015

Conversation

as-cii
Copy link
Contributor

@as-cii as-cii commented May 11, 2015

This PR introduces a change in how we render lines. It does so by organizing them into tiles, which we then move up and down through a compositing transformation. The main advantage is that paint times dramatically reduce, because now we simply need to paint a small tile, instead of all the lines. This is especially noticeable during scrolling which, as a result, will be the subject of the benchmarks I am going to show later on.

Please, note that:

  • Specs are broken. The solution you can see here was achieved by spiking a bunch of ideas, and therefore I didn't pay attention to change specs/code gradually. As a result, I plan to adapt previous specs and write some new ones as soon as possible.
  • There's some evident structural duplication in code. However, I'd like to start refactoring that stuff as soon as I have unit tests to prevent naive errors.
  • Naming-wise I am not entirely happy with TilesPresenter and LinesPresenter and they're probably going to change. Any suggestion or improvement is very welcome here.
  • I have intentionally left out line numbers from using this new approach. I'd like to keep this PR focused and work on that right after 🚢ping this one.

🐎 And now some benchmarks! 🐎

Benchmarks

Tests conducted using:

  • A 1920x1080 window

  • editor.scrollSensitivity = 130

  • A custom code (associated to a keyboard key) to simulate mouseWheel events

    document.querySelector("html /deep/ .editor-contents--private").dispatchEvent(new WheelEvent("mousewheel", wheelDeltaY: -250))
  • Keyboard Key Repeat: Fast (Mac OS X setting)

  • Delay Until Repeat: Short (Mac OS X setting)

I needed a (more or less) repeatable way to benchmark scrolling. To try this out, you can simply scroll up and down as you would normally do.

master

master

as-tiled-rendering

as-tiled-rendering

Why this matters?

As you can notice, paint times are dramatically reduced. This may not be noticeable with your 👀, but it's nevertheless important 'cause it leaves some room for additional operations (such as a more expensive character measurement computation). As said earlier, things are going to speed up further once we introduce tiling for line numbers as well.

It would be great if you could try this out, reporting any eventual regression or glitch that I may have overlooked while implementing the tiling strategy. Moreover, any code review or additional 👀 are always welcome.

Thank you!

/cc: @atom/feedback @nathansobo

@@ -0,0 +1,41 @@
module.exports =
class LinesPresenter
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should really be TilePresenter.

@maxbrunsfeld
Copy link
Contributor

✨ Really exciting work.

@@ -963,7 +963,7 @@ class TextEditorPresenter
hasPixelPositionRequirements: ->
@lineHeight? and @baseCharacterWidth?

pixelPositionForScreenPosition: (screenPosition, clip=true) ->
pixelPositionForScreenPosition: (screenPosition, clip=true, {absolute}={}) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Talk to me a little about this absolute flag... seems like you should always just choose the position relative to the viewport now since the lines layer is no longer moving. Either way, I think we should avoid allocating the options object on this hot path. I'm paranoid about garbage objects these days.

@nathansobo
Copy link
Contributor

I've been talking about wanting to do tiles for a year now. Thanks so much for pushing this forward!

@benogle
Copy link
Contributor

benogle commented May 11, 2015

Wow, looks like a huge speedup

@Zireael07
Copy link

Always good to see speedups!

as-cii added 5 commits May 13, 2015 09:04
This commit makes the method return a `top` value which is relative to the
viewport. However, we still need to return an absolute value for `left` because
lines are moved horizontally through a single transform on their parent node.

I would prefer being consistent (i.e. make everything relative), but moving
every single tile to simulate scrolling, on the other hand, seems overkill and
it's not really intuitive given that we are not tiling horizontally.

/cc: @nathansobo
@v3ss0n
Copy link

v3ss0n commented Jun 3, 2015

@nathansobo @as-cii i am testing on linux 64bit.
I opened up a compiled js file , with long lines and 1.2MB.
Selection is smooth, editing is a bit laggy
Scrolling is fine until it goes to bottom.

When scrolled to bottom part , it freeze up , taking 100% CPU and seems to be generating tiles, for 20-40 secs?
That bottom part is 1.1 mil chars , within 2 lines only.
It happens everytime when scroll back to top and bottom part again

Is it possible to move tiles generation to a worker process? I have tested with 205 and it rendered fast and fine.

@as-cii
Copy link
Contributor Author

as-cii commented Jun 3, 2015

Hi @v3ss0n, thank you for your feedback!

Could you please attach somewhere the file you're talking about? If it's private and you don't want to share it with everyone, it'd be awesome if you could share it via e-mail (you can find my address on my profile, https://github.com/as-cii).

Thanks a lot!

@v3ss0n
Copy link

v3ss0n commented Jun 3, 2015

@as-cii thanks a lot for fast response. I restarted atom and reopened, first it stop responding while atom start , and loading the file , so i start from scratch (previously auto reload have a lot of tabs and split panes opened ). Now it rendering fine . I tested without --safe.

So only problem remain is when previous session restored , and large files are opened previously atom stop responding and has to force close (can reproduce with --safe )

Rendering is smooth and fine , i copy / paste that file 10 times , making 11mb , and it dosen't slow down scrolling at all!

Thanks a lot for hard work , i will upload the file i testing to gist in a bit.

@v3ss0n
Copy link

v3ss0n commented Jun 3, 2015

Here are things i've tested so far:

###Works

  • 11 MB file
  • More than 100k char per line
  • Compiled Javascript file (with a lot of tokens )
  • Just characters
  • Select word , Select Line , Select Multiple line , Select all

##Fails

  • Reopen session with many tabs and one huge file.

@alexandernst
Copy link

This looks very interesting nodejs/node#1159
I wonder if Atom could use it for heavy tasks? @nathansobo

@nathansobo
Copy link
Contributor

@alexandernst That looks super interesting. Thanks for the heads up.

@ilanbiala
Copy link

@nathansobo does Atom already use io.js or is it still on Node?

@mnquintana
Copy link
Contributor

@ilanbiala Atom uses io.js – Electron uses it.

@nathansobo
Copy link
Contributor

@ilanbiala Yep. It could take a while for this feature to get to us however since it's not even merged to master in iojs. Then it has to be released in an official iojs release, integrated into Electron, and finally Atom has to upgrade to that version of Electron. But definitely worth keeping an eye on. It's something we could definitely make lots use of once it's available.

@v3ss0n
Copy link

v3ss0n commented Jun 10, 2015

This may be a bit offtopic but curious.
@mnquintana atom is built using node 0.12 on my machine , is that already using IO.js ?
Atom current version is not using electron , yet right?

@mehcode
Copy link
Contributor

mehcode commented Jun 10, 2015

@v3ss0n From what I understand atom has a packaged version. The version you have is only used to bootstrap the process.

@YurySolovyov
Copy link

@v3ss0n it is currently io v1.6.3 and being updated to io v2.2.1

@v3ss0n
Copy link

v3ss0n commented Jun 10, 2015

ah i got it , it have packaged own IO.js separated from OS version ?

@v3ss0n
Copy link

v3ss0n commented Jun 11, 2015

We have a problem with tile rendering , effecting themes with background transparency : https://github.com/v3ss0n/steam-pirate-ui
It renders tiles in more darkened color than my theme's color , i had compared it against atom version without tiled rendering. See attached. The text area part of the editor is darkened vs the bottom part (the actual theme's color)

tile_rendering_theme

from styling side , should i theme .lines or .tile

@olmokramer
Copy link

Hey, awesome work on the tile rendering! I've got one problem with it, however, as it breaks my block-cursor package.

To have a block-cursor, I used to add a (opaque) background color to the cursor element, and set its z-index to -1. That way, the cursor would render behind the text, and text would still be legible.

Now, with the new tile rendering, all the lines are inside a new element with an opaque background, so I can't render the cursor behind the lines anymore (or it would also be behind the tile, and thus invisible anyway)...

There's the option to set a very low alpha value on the cursor color, and render it in front of the text, but that way the cursor changes the text color, and it's tricky to find a value that produces a nice color and keeps text legible.

@v3ss0n
Copy link

v3ss0n commented Jun 21, 2015

it seems we have no choice but to embrace it ? The benefits outweighs a few styling inflexibility , but i miss my beautiful theme tho .

@olmokramer
Copy link

Hmmm, I just thought that highlights might suffer from the same issue, but then I found that a highlights container is added to each tile. I wonder if this is also possible for the cursors, or would it be too much of a performance issue? Or just too much work for too little gain?

@v3ss0n
Copy link

v3ss0n commented Jun 21, 2015

Highlights? the Highlight selected package ? or Editor's highlight? I am gonna give a try. I was too busy these days and haven't hack atom much last 2-3 weeks.

@as-cii
Copy link
Contributor Author

as-cii commented Jun 22, 2015

Hmmm, I just thought that highlights might suffer from the same issue, but then I found that a highlights container is added to each tile. I wonder if this is also possible for the cursors, or would it be too much of a performance issue? Or just too much work for too little gain?

Given that tiles have an opaque background, I am afraid this is the only possible solution. Moreover, that would be consistent with how we handle highlights, as you’re pointing out. I kinda overlooked it because Atom’s default cursor works just fine as it stands in front of the tiles; the implementation will definitely bring some complexity but, ultimately, I think it’s the right way of doing it and, after all, it won’t mess things up that much.

@olmokramer: that said, what do you think about opening a brand new issue where we can keep track of this? I plan to work on it, but I’ll be traveling over the next days and I think I’ll be able to tackle it starting from the next month.

Highlights? the Highlight selected package ? or Editor's highlight? I am gonna give a try. I was too busy these days and haven't hack atom much last 2-3 weeks.

@v3ss0n: highlights are an abstraction useful to decorate markers; you can have a look at the related blog post for all the nitty-gritty details.

@v3ss0n
Copy link

v3ss0n commented Jun 22, 2015

Thanks , interesting , i will look into it.

@olmokramer
Copy link

@as-cii Thanks! That's truly awesome :) I'll submit a new issue in the evening.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.