Merge pull request #1157 from goneng/fix_high_cpu

GUI: Reduce CPU usage by adding sleep intervals to UI wait loops
This commit is contained in:
Mykola Grymalyuk
2025-04-04 06:58:43 -06:00
committed by GitHub
13 changed files with 55 additions and 55 deletions

View File

@@ -1,5 +1,8 @@
# OpenCore Legacy Patcher changelog
## 2.4.0
- Reduce CPU usage on main UI thread
## 2.3.2
- Resolve erroring in Passwords app and Safari Autofill on T1 Macs running 15.4 or later
- Increment binaries:

View File

@@ -130,7 +130,7 @@ class OpenCoreLegacyPatcher:
if not any(x in sys.argv for x in ignore_args):
while self.constants.unpack_thread.is_alive():
time.sleep(0.1)
time.sleep(self.constants.thread_sleep_interval)
arguments.arguments(self.constants)

View File

@@ -155,6 +155,8 @@ class Constants:
self.unpack_thread = None # Determine if unpack thread finished (threading.Thread)
self.update_stage: int = 0 # Determine update stage (see gui_support.py)
self.log_filepath: Path = None # Path to log file
self.thread_sleep_interval: float = 0.1 # Sleep interval between UI updates (seconds) - reduce refresh-rate to reduce CPU-usage
self.thread_nap_interval: float = 0.01 # Short Sleep interval between UI updates (seconds) - for faster UI updates of the progress bar
self.commit_info: tuple = (None, None, None) # Commit info (Branch, Commit Date, Commit URL)

View File

@@ -6,6 +6,7 @@ import wx
import logging
import threading
import traceback
import time
from .. import constants
@@ -101,12 +102,12 @@ class BuildFrame(wx.Frame):
"""
while gui_support.PayloadMount(self.constants, self).is_unpack_finished() is False:
wx.Yield()
time.sleep(self.constants.thread_sleep_interval)
thread = threading.Thread(target=self._build)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
self.return_button.Enable()

View File

@@ -76,13 +76,11 @@ class OSUpdateFrame(wx.Frame):
if results[HardwarePatchsetSettings.KERNEL_DEBUG_KIT_REQUIRED] is True:
kdk_thread = threading.Thread(target=_kdk_thread_spawn)
kdk_thread.start()
while kdk_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(kdk_thread)
if results[HardwarePatchsetSettings.METALLIB_SUPPORT_PKG_REQUIRED] is True:
metallib_thread = threading.Thread(target=_metallib_thread_spawn)
metallib_thread.start()
while metallib_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(metallib_thread)
download_objects = {
@@ -149,8 +147,7 @@ class OSUpdateFrame(wx.Frame):
kdk_checksum_thread = threading.Thread(target=_validate_kdk_checksum_thread)
kdk_checksum_thread.start()
while kdk_checksum_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(kdk_checksum_thread)
if self.kdk_checksum_result is False:
logging.error("KDK checksum validation failed")
@@ -172,8 +169,7 @@ class OSUpdateFrame(wx.Frame):
kdk_install_thread = threading.Thread(target=_install_kdk_thread)
kdk_install_thread.start()
while kdk_install_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(kdk_install_thread)
if self.kdk_install_result is False:
logging.info("Failed to install KDK")
@@ -194,8 +190,7 @@ class OSUpdateFrame(wx.Frame):
metallib_install_thread = threading.Thread(target=_install_metallib_thread)
metallib_install_thread.start()
while metallib_install_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(metallib_install_thread)
if self.metallib_install_result is False:
logging.info("Failed to install Metallib")

View File

@@ -4,6 +4,7 @@ gui_download.py: Generate UI for downloading files
import wx
import logging
import time
from .. import constants
@@ -86,6 +87,7 @@ class DownloadFrame(wx.Frame):
label_amount.Centre(wx.HORIZONTAL)
wx.Yield()
time.sleep(self.constants.thread_sleep_interval)
if self.download_obj.download_complete is False and self.user_cancelled is False:
wx.MessageBox(f"Download failed: \n{self.download_obj.error_msg}", "Error", wx.OK | wx.ICON_ERROR)

View File

@@ -103,9 +103,7 @@ class InstallOCFrame(wx.Frame):
thread = threading.Thread(target=self._fetch_disks)
thread.start()
while thread.is_alive():
wx.Yield()
continue
gui_support.wait_for_thread(thread)
self.progress_bar_animation.stop_pulse()
self.progress_bar.Hide()
@@ -281,8 +279,7 @@ class InstallOCFrame(wx.Frame):
thread = threading.Thread(target=self._install_oc, args=(partition,))
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
if self.result is True:
if self.constants.update_stage != gui_support.AutoUpdateStages.INACTIVE and self.constants.detected_os >= os_data.os_data.big_sur:

View File

@@ -149,8 +149,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
thread = threading.Thread(target=_fetch_installers)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
progress_bar_animation.stop_pulse()
progress_bar.Hide()
@@ -412,8 +411,7 @@ class macOSInstallerDownloadFrame(wx.Frame):
self.Show()
# Wait for thread to finish
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
progress_bar_animation.stop_pulse()
progress_bar.Hide()

View File

@@ -88,8 +88,7 @@ class macOSInstallerFlashFrame(wx.Frame):
thread = threading.Thread(target=fetch_installers)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
frame_modal = wx.Dialog(self, title=self.title, size=(350, 200))
@@ -180,8 +179,7 @@ class macOSInstallerFlashFrame(wx.Frame):
thread = threading.Thread(target=_fetch_disks)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
self.frame_modal = wx.Dialog(self, title=self.title, size=(350, 200))
@@ -317,7 +315,9 @@ class macOSInstallerFlashFrame(wx.Frame):
except:
bytes_written = 0
wx.CallAfter(progress_bar.SetValue, bytes_written)
wx.Yield()
time.sleep(self.constants.thread_sleep_interval)
if self.result is False:
logging.error("Failed to flash installer, cannot continue.")
@@ -370,8 +370,7 @@ class macOSInstallerFlashFrame(wx.Frame):
thread = threading.Thread(target=prepare_script, args=(self, installer_path, disk, self.constants))
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
return self.prepare_result
@@ -399,10 +398,11 @@ class macOSInstallerFlashFrame(wx.Frame):
return False
logging.info("Successfully created macOS installer")
while thread.is_alive():
# wait for download_thread to finish
# though highly unlikely this thread is still alive (flashing an Installer will take a while)
time.sleep(0.1)
# wait for download_thread to finish
# though highly unlikely this thread is still alive (flashing an Installer will take a while)
gui_support.wait_for_thread(thread)
logging.info("Installing Root Patcher to drive")
self._install_installer_pkg(disk)
@@ -617,8 +617,7 @@ class macOSInstallerFlashFrame(wx.Frame):
thread = threading.Thread(target=_integrity_check)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
if error_message == "":
logging.info("Installer pkg validated")

View File

@@ -263,6 +263,19 @@ class ThreadHandler(logging.Handler):
wx.CallAfter(self.text_box.AppendText, self.format(record) + '\n')
def wait_for_thread(thread: threading.Thread, sleep_interval=None):
"""
Waits for a thread to finish while processing UI events at regular intervals
to prevent UI freezing and excessive CPU usage.
"""
# Use the passed sleep_interval, or get from global_constants
interval = sleep_interval if sleep_interval is not None else constants.Constants().thread_sleep_interval
while thread.is_alive():
wx.Yield()
time.sleep(interval)
class RestartHost:
"""
Restarts the host machine

View File

@@ -93,9 +93,7 @@ class SysPatchDisplayFrame(wx.Frame):
frame.ShowWindowModal()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
frame.Close()

View File

@@ -88,8 +88,7 @@ class SysPatchStartFrame(wx.Frame):
kdk_thread = threading.Thread(target=_kdk_thread_spawn)
kdk_thread.start()
while kdk_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(kdk_thread)
if self.kdk_obj.success is False:
progress_bar_animation.stop_pulse()
@@ -170,8 +169,7 @@ class SysPatchStartFrame(wx.Frame):
metallib_thread = threading.Thread(target=_metallib_thread_spawn)
metallib_thread.start()
while metallib_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(metallib_thread)
if self.metallib_obj.success is False:
progress_bar_animation.stop_pulse()
@@ -209,8 +207,7 @@ class SysPatchStartFrame(wx.Frame):
install_thread = threading.Thread(target=_install_metallib)
install_thread.start()
while install_thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(install_thread)
if self.result is False:
progress_bar_animation.stop_pulse()
@@ -314,6 +311,7 @@ class SysPatchStartFrame(wx.Frame):
while gui_support.PayloadMount(self.constants, self).is_unpack_finished() is False:
wx.Yield()
time.sleep(self.constants.thread_sleep_interval)
if self.patches[HardwarePatchsetSettings.KERNEL_DEBUG_KIT_REQUIRED] is True:
if self._kdk_download(self) is False:
@@ -329,8 +327,7 @@ class SysPatchStartFrame(wx.Frame):
thread = threading.Thread(target=self._start_root_patching, args=(self.patches,))
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
self._post_patch()
self.return_button.Enable()
@@ -356,8 +353,7 @@ class SysPatchStartFrame(wx.Frame):
thread = threading.Thread(target=self._revert_root_patching, args=(self.patches,))
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
self._post_patch()
self.return_button.Enable()

View File

@@ -102,8 +102,7 @@ class UpdateFrame(wx.Frame):
thread = threading.Thread(target=_fetch_update)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
gui_download.DownloadFrame(
self.frame,
@@ -128,8 +127,7 @@ class UpdateFrame(wx.Frame):
thread = threading.Thread(target=self._extract_update)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
# Title: Installing update
title_label.SetLabel("Installing update...")
@@ -138,8 +136,7 @@ class UpdateFrame(wx.Frame):
thread = threading.Thread(target=self._install_update)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
# Title: Update complete
title_label.SetLabel("Update complete!")
@@ -170,8 +167,7 @@ class UpdateFrame(wx.Frame):
thread = threading.Thread(target=self._launch_update)
thread.start()
while thread.is_alive():
wx.Yield()
gui_support.wait_for_thread(thread)
timer = 5
while True: