Skip to content

Conversation

@sedwards2009
Copy link
Collaborator

@sedwards2009sedwards2009 commented Jun 22, 2022

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/O16,008108
Qode original56,154386
Qode + 64 extra uv_run() calls15,057104
Qode + 32 extra uv_run() calls16,980117
Qode + 16 extra uv_run() calls17,236120
Qode + 8 extra uv_run() calls26,556182

Linux

Write MSRead MS
NodeJS only I/O13,67277
Qode original25,832133
Qode + 64 extra uv_run() calls13,43575
Qode + 32 extra uv_run() calls15,04874
Qode + 16 extra uv_run() calls17,67370
Qode + 8 extra uv_run() calls21,23784

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
CollaboratorAuthor

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

@sedwards2009
Copy link
CollaboratorAuthor

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.

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

@a7ul 👇

Comment on lines -66 to -68

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

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
CollaboratorAuthor

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

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
CollaboratorAuthor

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

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
CollaboratorAuthor

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

@a7ul
Copy link

a7ul commented Jul 1, 2022

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

@a7ula7ul merged commit b72356b into nodegui:v16.4.0-qodeJul 1, 2022
@a7ul
Copy link

a7ul commented Jul 1, 2022

This is released now

Sign up for freeto 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

@sedwards2009@a7ul