dnkl/foot
41
2.0k
Fork
You've already forked foot
243

Investigate if we can add 8 bits to the cell struct without affecting performance #593

Open
opened 2021年06月15日 13:09:53 +02:00 by dnkl · 4 comments
Owner
Copy link

The cell struct currently consists of two fields: attrs and wc, where wc is the character it contains, and attrs its attributes (i.e. bold, italic, underline, colors etc).

Most of the attributes are related to ANSI attributes, and are first set in the vt struct's attrs member, and then copied to the cell when a character is printed.

That is, all cell attributes are overwritten when a character is printed.

This becomes a problem for the few attributes that are not related to the ANSI state: currently url and selected.

The selected bits informs the renderer that the cell is selected (by the user) and should be highlighted as such. Thus, if the user has selected a region of text, and cells within that region is updated, those cells "lose" their selected state. We are currently working around this by walking all selected cells and updating their selected bits just before rendering.

Things would become much simpler if we could separate the ANSI state from cell persistent state. For performance reasons, we cannot just split the attributes struct, as that would require more instructions when copying the attributes when printing a character.

But perhaps we can add an uint8_t to the cell struct? This new bitfield would contain state that needs to be persistent across cell writes. It would of course increase foot's memory usage, with ~8% (13 vs. 12 bytes). It may also affect our cache usage in a negative way.

The `cell` struct currently consists of two fields: `attrs` and `wc`, where `wc` is the character it contains, and `attrs` its attributes (i.e. **bold**, _italic_, underline, colors etc). Most of the attributes are related to ANSI attributes, and are first set in the `vt` struct's `attrs` member, and then **copied** to the cell when a character is printed. That is, **all** cell attributes are **overwritten** when a character is printed. This becomes a problem for the few attributes that are **not** related to the ANSI state: currently `url` and `selected`. The `selected` bits informs the renderer that the cell is selected (by the user) and should be highlighted as such. Thus, if the user has selected a region of text, and cells within that region is updated, those cells "lose" their selected state. We are currently working around this by walking all selected cells and updating their `selected` bits just before rendering. Things would become much simpler if we could separate the ANSI state from cell persistent state. For performance reasons, we cannot just split the attributes struct, as that would require **more** instructions when copying the attributes when printing a character. But perhaps we can add an `uint8_t` to the cell struct? This new bitfield would contain state that needs to be persistent across cell writes. It would of course increase foot's memory usage, with ~8% (13 vs. 12 bytes). It may also affect our cache usage in a negative way.
Collaborator
Copy link

But perhaps we can add an uint8_t to the cell struct?
...
It would of course increase foot's memory usage, with ~8% (13 vs. 12 bytes)

I think adding a uint8_t member would increase sizeof(struct cell) from 12 to 16 bytes. _Alignof(struct cell) is 4, so the compiler would have to add 3 bytes of padding.

> But perhaps we can add an `uint8_t` to the cell struct? > ... > It would of course increase foot's memory usage, with ~8% (13 vs. 12 bytes) I think adding a `uint8_t` member would increase `sizeof(struct cell)` from 12 to 16 bytes. `_Alignof(struct cell)` is 4, so the compiler would have to add 3 bytes of padding.
Author
Owner
Copy link

Ah, right, of course. We could always pack it.

But, and I didn't mention this in the description above, a 13-byte struct means we'll be doing unaligned memory accesses. Not sure how much impact that will have. Slower, for sure, but by how much? I guess that's part of the investigation :)

We get by pretty ok with the current state bits. But #592 is hard to do without persistent cell state.

Ah, right, of course. We could always pack it. But, and I didn't mention this in the description above, a 13-byte struct means we'll be doing unaligned memory accesses. Not sure how much impact that will have. Slower, for sure, but by how much? I guess that's part of the investigation :) We get by pretty ok with the current state bits. But https://codeberg.org/dnkl/foot/pulls/592 is hard to do without persistent cell state.

13-byte struct means we'll be doing unaligned memory accesses.

Depending on what you're doing, you can maybe get away with a "pool" instead.

struct cell_pool {
 struct cell cells[5]; // 60 bytes
 uint32_t flags; // 4 bytes - each cell gets to have 6 bits.
};

This will fit cozily into 64 bytes without needing to do any forced packing.

Disclaimer: I'm not really familiar with foot's codebase, so feel free to ignore if what I said doesn't apply.

> 13-byte struct means we'll be doing unaligned memory accesses. Depending on what you're doing, you can maybe get away with a "pool" instead. ```c struct cell_pool { struct cell cells[5]; // 60 bytes uint32_t flags; // 4 bytes - each cell gets to have 6 bits. }; ``` This will fit cozily into 64 bytes without needing to do any forced packing. **Disclaimer**: I'm not really familiar with foot's codebase, so feel free to ignore if what I said doesn't apply.

The selected bits informs the renderer that the cell is selected (by the user) and should be highlighted as such. Thus, if the user has selected a region of text, and cells within that region is updated, those cells "lose" their selected state. We are currently working around this by walking all selected cells and updating their selected bits just before rendering.

Others terminals (gnome-terminal) removes any selection if the text within the selection is updated. I believe this could be a legitimate behaviour because then you don't know what text you copied. The problem arise when there is a constant changing text and you want to copy some of it.

> The selected bits informs the renderer that the cell is selected (by the user) and should be highlighted as such. Thus, if the user has selected a region of text, and cells within that region is updated, those cells "lose" their selected state. We are currently working around this by walking all selected cells and updating their selected bits just before rendering. Others terminals (gnome-terminal) removes any selection if the text within the selection is updated. I believe this could be a legitimate behaviour because then you don't know what text you copied. The problem arise when there is a constant changing text and you want to copy some of it.
Sign in to join this conversation.
No Branch/Tag specified
master
osc-5522
sixel-heap-buffer-overflow
releases/1.27
releases/1.26
releases/1.25
releases/1.24
multi-cursor
releases/1.23
pixman-16f-2
releases/1.22
releases/1.21
releases/1.20
releases/1.19
releases/1.18
releases/1.17
releases/1.16
releases/1.15
releases/1.14
releases/1.13
releases/1.12
releases/1.11
releases/1.10
releases/1.9
releases/1.8
releases/1.7
releases/1.6
releases/1.5
releases/1.4
releases/1.3
releases/1.2
releases/1.1
releases/1.0
1.27.0
1.26.1
1.26.0
1.25.0
1.24.0
1.23.1
1.23.0
1.22.3
1.22.2
1.22.1
1.22.0
1.21.0
1.20.2
1.20.1
1.20.0
1.19.0
1.18.1
1.18.0
1.17.2
1.17.1
1.17.0
1.16.2
1.16.1
1.16.0
1.15.3
1.15.2
1.15.1
1.15.0
1.14.0
1.13.1
1.13.0
1.12.1
1.12.0
1.11.0
1.10.3
1.10.2
1.10.1
1.10.0
1.9.2
1.9.1
1.9.0
1.8.2
1.8.1
1.8.0
1.7.2
1.7.1
1.7.0
1.6.4
1.6.3
1.6.2
1.6.1
1.6.0
1.5.4
1.5.3
1.5.2
1.5.1
1.5.0
1.4.4
1.4.3
1.4.2
1.4.1
1.4.0
1.3.0
1.2.3
1.2.2
1.2.1
1.2.0
1.1.0
1.0.0
0.9.0
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
4 participants
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
dnkl/foot#593
Reference in a new issue
dnkl/foot
No description provided.
Delete branch "%!s()"

Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?