Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

0

Share

Download to read offline

Евгений Обрезков "Behind the terminal"

Download to read offline

Я расскажу о том, как можно использовать терминал не по назначению.
Какие подводные камни мне встречались, когда я разрабатывал canvas для терминала. Какие алгоритмы я использовал, чтобы оптимизировать скорость отрисовки элементов.
И конечно же покажу все на реальных примерах и отвечу на вопросы.

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to like this

Евгений Обрезков "Behind the terminal"

  1. 1. Behind the terminal How to waste half a year of your time on something nobody cares about or
  2. 2. Who am I? • Developer Advocate at Onix-Systems (open-source, community and so on); • NodeJS developer with 4+ years of experience; • Active contributor to Sails ecosystem (in the past); • Currently working with microcontrollers;
  3. 3. What will I talk about? • Controlling the cursor in terminal; • Rendering using our controlled cursor; • Oops, we need to optimize it; • Demos;
  4. 4. Controlling the cursor • Move cursor: <ESC>[<ROW>;<COLUMN>f • Change display mode: <ESC>[<MODE>m • Change foreground: <ESC>[38;2;<R>;<G>;<B>m • Change background: <ESC>[48;2;<R>;<G>;<B>m • Clear the screen: <ESC>[2J • etc…
  5. 5. How can it be used for implementing canvas? • cursor.moveTo(x, y) ->
 process.stdout.write(`e[${y};${x}f`); • cursor.background(r, g, b) ->
 process.stdout.write(`e[48;2;${r};${g};${b}m`); • cursor.write(text) ->
 process.stdout.write(text); • and so on…
  6. 6. We have implemented mapping API calls to control sequences, great!
  7. 7. Simple render engine Move to (10, 10) -> change foreground color to red -> write “Hello, World” -> move to (0, 0). cursor
 .moveTo(10, 10) // <ESC>[10;10f
 .foreground(255, 0, 0) // <ESC>[38;2;255;0;0m
 .write(‘Hello, World’) // Hello, World
 .moveTo(0, 0); // <ESC>[0;0f
  8. 8. It works great for static rendering, when you show the frame only once
  9. 9. But, we want to render 253060120 times a second…
  10. 10. Oops, we have a problem <ESC>[10;10f<ESC>[38;2;255;0;0mHello, World<ESC>[0;0f<ESC>[2J<ESC>[10;10f<ESC>[38; 2;255;0;0mHello,World<ESC>[0;0f<ESC>[2J<ESC>[1 0;10f<ESC>[38;2;255;0;0mHello,World<ESC>[0;0f<E SC>[2J<ESC>[10;10f<ESC>[38;2;255;0;0mHello,Worl d<ESC>[0;0f<ESC>[2J<ESC>[10;10f<ESC>[38;2;25 5;0;0mHello,World<ESC>[0;0f<ESC>[2J<ESC>[10;10 f<ESC>[38;2;255;0;0mHello,World<ESC>[0;0f<ESC>[ 2J…
  11. 11. If frame is rich enough, you will get spamming a lot of text 25 times per second - that’s not good
  12. 12. Let’s optimize it
  13. 13. Our assumptions • It’s logical to assume, that we need to track which “pixels” are changed and which not; • Our current structure is not applicable to building difference map - we have only one big line of control sequences and we know nothing about current state of cursor, “pixels”, etc; • Solution can be to wrap each cell of the terminal in independent control sequence, so we can control them independently from others;
  14. 14. Wrapping the cells Each cell must know how to render itself independently. Let’s wrap the cell in all the required sequences for that: • Position; • BackgroundForeground; • Display modes; • Character to write in this cell; • Reset all settings to default (so it doesn’t collide with other styles);
  15. 15. Wrapped cell <ESC>[<Y>;<X>f # Position
 <ESC>[48;2;<R>;<G>;<B>m # Background
 <ESC>[38;2;<R>;<G>;<B>m # Foreground
 <ESC>[<DISPLAY_MODE>m # Bold, dim, whatever
 <CHAR_IN_CELL> # A single character to print
 <ESC>[0m # Reset all display settings
  16. 16. We got independent cells, think of them as “pixels”
  17. 17. Introducing the “markers”
  18. 18. Cell markers We have 2 states of the cell: modified and unmodified. Let’s say, we change background for some cell: cell[y * <TERMINAL_WIDTH> + x].setBackground(); It changes the cell state to modified and set new background color for our cell, which will rebuild the control sequence for that cell on the next flushing.
  19. 19. Markers allow to not build the difference between cells - we already know that it was not modified
  20. 20. What if we change background to the same color?
  21. 21. That’s when difference comes into play
  22. 22. If control sequence in a modified cell is the same as the old control sequence - ignore flushing - we already flushed it before
  23. 23. Checklist • We have a kind of “virtual terminal” in our render engine which is represented as an array of wrappers around real cells; • We removed the control sequence which resets the terminal state. We can clear it via writing cell with whitespace and no styling; • We have hybrid system with markers and differences between frames; • Finally, we have 120 FPS in the terminal - amazing!
  24. 24. It’s written entirely in JavaScript
  25. 25. Everybody loves demos!
  26. 26. Thanks ghaiklor ghaiklor ghaiklor

Я расскажу о том, как можно использовать терминал не по назначению. Какие подводные камни мне встречались, когда я разрабатывал canvas для терминала. Какие алгоритмы я использовал, чтобы оптимизировать скорость отрисовки элементов. И конечно же покажу все на реальных примерах и отвечу на вопросы.

Views

Total views

353

On Slideshare

0

From embeds

0

Number of embeds

86

Actions

Downloads

2

Shares

0

Comments

0

Likes

0

×