ArthurSonzogni / FTXUI

:computer: C++ Functional Terminal User Interface. :heart:
MIT License
6.64k stars 399 forks source link

Performance issue with paragraphs #778

Open Epixu opened 9 months ago

Epixu commented 9 months ago

Hey there, I'm experimenting with FTXUI for the first time, I'm planning on using it to design an ASCII game engine interface. I'm still in the experimentation phase, and I'm encountering a plethora of issues, some of them are already posted, and I'll refer to them.

However, the most pressing issue at the moment, is performance. Here's what my demo looks like: frtxuiscre

Here I have my working experimentation code (which I recommend you extract and use inside standalone app, if you want to test it, since testing my module would involve downloading the entire engine atm)

I'm currently experiencing a substantial input lag all the time. From a bit of introspection into the library, I found out that in order to fit the paragraph, it is broken apart into words, each word becomes a text node, and all these nodes go inside a flexbox, which is then dynamically analyzed on render. (correct me if I'm wrong)

This results in a huge amount of overhead, a dynamic allocation per word, etc. Which is troublesome, since I'm attempting at rerouting console output through FTXUI. Is there a better way to do this? Is there, like a nested console output renderer, that relays messages? I didn't see one in the examples.

Alternatively, it would probably be possible to split text only line-by-line, and inserting those as text, instead of word-by-word? As a last measure, I will attempt to "fake it", by simply drawing the currently relevant lines, and offset these when I scroll (since scrolling doesn't work too, see #519)

Additionally, it seems the the split variable doesn't affect paragraphs when I resize the terminal. It happens only when I drag the separator.

ArthurSonzogni commented 9 months ago

Hello @Epixu,

Here I have my working experimentation code (which I recommend you extract and use inside standalone app, if you want to test it, since testing my module would involve downloading the entire engine atm) Would you have some build instructions for me to test? The CMake provided in the project was not standing alone. I guess it depends being included in some bigger project.

I'm currently experiencing a substantial input lag all the time. From a bit of introspection into the library, I found out that in order to fit the paragraph, it is broken apart into words, each word becomes a text node, and all these nodes go inside a flexbox, which is then dynamically analyzed on render. (correct me if I'm wrong)

Yes, correct. paragraph is built on top of flexbox, because it was an easy gain. Depending on the particularities of what you would like to do, it should be possible to get 10x-100x gains. It means more work on your plate: implementing yourself some logic (e.g. implementing a ftxui::Node).

Is there, like a nested console output renderer, that relays messages? I didn't see one in the examples.

There are no supported ways to import console output as input into FTXUI. Maybe one day.

Alternatively, it would probably be possible to split text only line-by-line

The text is split by word, so that we can wrap on words.

If you know in advance the size of the line, you probably can split the text to fit the line and return a vbox({...lines}). No more flexbox.

(since scrolling doesn't work too, see https://github.com/ArthurSonzogni/FTXUI/issues/519)

Scrolling is not really a concept in FTXUI. What we have are frame to render into an element something from a larger area, and the decorator select and focus to focus an element at the center of the view of the frame. I guess you aren't using select/focus. Do you?

Additionally, it seems the the split variable doesn't affect paragraphs when I resize the terminal. It happens only when I drag the separator.

I did not understood this sentence.

Epixu commented 9 months ago

Thanks for the quick response! I might have been a bit cryptic in my intents, here's a bit of clarification on a bunch of points:

The text is split by word, so that we can wrap on words.

If you know in advance the size of the line, you probably can split the text to fit the line and return a vbox({...lines}). No more flexbox.

I believe that it can still be possible to wrap on words, without actually do an allocation for each word. I might attempt at making a Node for that purpose. In that particular case, I do know the size of text (its the mSplit variable, see at end of comment), and using that I can approximate where the relevant words are, and scan only around them, to make the appropriate carry-over of words around that point.

Scrolling is not really a concept in FTXUI. What we have are frame to render into an element something from a larger area, and the decorator select and focus to focus an element at the center of the view of the frame. I guess you aren't using select/focus. Do you?

I will try those, thank you. On a side note, I probably can intercept mouse scroll wheel events and update elements according to it?

Additionally, it seems the the split variable doesn't affect paragraphs when I resize the terminal. It happens only when I drag the separator.

I did not understood this sentence.

What I refer to is in my testing code:

auto split = ResizableSplitRight(right, left, &mSplit);

That mSplit variable seems to not affect the paragraph, when I resize the console window - all elements update, except the paragraph. And I'm forced to do something like:

   if (mSplit != mSplitPrev) {
      // Need to refresh paragraphs                                     
      mSplitPrev = mSplit;
      mLog.clear();

      for (unsigned i = 0; i < 100; ++i)
         mLog.push_back(paragraph(p) | size(WIDTH, EQUAL, mScreen.dimx() - mSplit - 3));
   }

... on each frame, in order to recreate the paragraphs. Also, worthy of note, is that if I don't do | size(WIDTH, EQUAL, mScreen.dimx() - mSplit - 3) manually, I don't get anything in the text area, even if I drag the border. Seems like paragraph doesn't respond well to splits.

Really appreciate your help