Skip to content

Trigger the event loop semaphore at the right time#6

Merged
a7ul merged 3 commits into
nodegui:v16.4.0-qodefrom
sedwards2009:windows_fix
Jul 1, 2022
Merged

Trigger the event loop semaphore at the right time#6
a7ul merged 3 commits into
nodegui:v16.4.0-qodefrom
sedwards2009:windows_fix

Conversation

@sedwards2009

@sedwards2009 sedwards2009 commented Jun 22, 2022

Copy link
Copy Markdown
Collaborator

This should prevent the hidden window on Windows from getting spammed,
and also prevent qode from entering this weird "slow down" state.

issue #4

It also contains some improvements to drastically increase the I/O throughput on Windows. Basically, triggering the main thread to go process nodejs events is expensive. The change is to call uv_run() multiple times instead of just once whenever we need to process nodejs events. When I/O is busy, calling multiple times will process more I/O events with less of the overhead and latency incurred by the two threads communicating with each other.

I have a little test program which times writing out the numbers 1 to 1000000 to a file one line at a time. Afterwards, it reads the file back in using 1KB chunks. The result are below are for Windows and Linux. They include plain nodejs, Qode without the extra event processing, and also Qode with different amounts of extra uv_run() calls.

Note: The amount of time processing a batch of events is capped at 8ms to prevent high I/O conditions from starving off the Qt event loop.

Windows

Write (ms) Read (ms)
NodeJS only I/O 16,008 108
Qode original 56,154 386
Qode + 64 extra uv_run() calls 15,057 104
Qode + 32 extra uv_run() calls 16,980 117
Qode + 16 extra uv_run() calls 17,236 120
Qode + 8 extra uv_run() calls 26,556 182

Linux

Write MS Read MS
NodeJS only I/O 13,672 77
Qode original 25,832 133
Qode + 64 extra uv_run() calls 13,435 75
Qode + 32 extra uv_run() calls 15,048 74
Qode + 16 extra uv_run() calls 17,673 70
Qode + 8 extra uv_run() calls 21,237 84

Note: Different machines are used between Windows and Linux.

Around about 16 extra calls in a batch seems to be a good trade off for Windows and Linux. I assume that this also holds for macOS.

This should prevent the hidden window on Windows from getting spammed,
and also prevent qode from entering this weird "slow down" state.
@sedwards2009

Copy link
Copy Markdown
Collaborator Author

The next task is to see if this affects Linux and to continue dog food testing this PR.

@sedwards2009

Copy link
Copy Markdown
Collaborator Author

Someone over at NodeGui also did some testing of the event loop performance: nodegui/nodegui#884

They were on an M1 mac which would have been running NodeGui via emulation.

@sedwards2009
sedwards2009 marked this pull request as ready for review June 29, 2022 19:52
@sedwards2009

Copy link
Copy Markdown
Collaborator Author

@a7ul 👇

Comment on lines -66 to -68

// Tell the worker thread to continue polling.
uv_sem_post(&embed_sem_);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Is this change intentional? 🤔

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Yes, it has moved down to WakeupMainThread().

This is the most important part of the bug fix which affected Windows. UvRunOnce() gets called from two different places/cases. In one case, you want the semaphore to be touched (Qt event loop is running), and in the other case you don't (no Qt event loop). Hitting the semaphore without the Qt event loop was screwing its counter up.

Comment on lines +127 to 130

// Wait for the main loop to deal with events.
uv_sem_wait(&self->embed_sem_);
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

If we skip the batch processing and only do this change where we wait for main loop to deal with events after main thread has woken up does it achive similar results?
If not lets go with batch processing.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

There are two mostly separate things in this PR:

  • The moving of the semaphore is the most important part here as it fixes Windows.
  • Processing multiple UV events each time (batch).

The batch is optional, but the impact on performance is quite great if you are doing I/O. I remember someone complaining in an issue somewhere that NodeGui's I/O is much much slower than plain nodejs.

(Yes, I probably should've made 2 PRs. my bad)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Nice! that make sense.

@sedwards2009

Copy link
Copy Markdown
Collaborator Author

@a7ul I'm going to need you to hit the Merge button. I don't have the rights.

@a7ul

a7ul commented Jul 1, 2022

Copy link
Copy Markdown

I had invited you to the entire org actually. I ll merge this one though

@a7ul
a7ul merged commit b72356b into nodegui:v16.4.0-qode Jul 1, 2022
@a7ul

a7ul commented Jul 1, 2022

Copy link
Copy Markdown

This is released now

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants