combine short periodic timeout functions for windows.
authorRobin Gareus <robin@gareus.org>
Sat, 25 Oct 2014 17:21:15 +0000 (19:21 +0200)
committerRobin Gareus <robin@gareus.org>
Sat, 25 Oct 2014 17:21:15 +0000 (19:21 +0200)
Fixes excessive CPU usage (spinlock instead of sleep/WaitForSingleObject)

MS Windows has a scheduler time-slice of 15ms.
Ardour has two fast timeout functions: The FPS timeout (20-60Hz, clock
video-monitor) and a fast-screen-update (25Hz, meters etc).
They are loosely coupled (async) and scheduled from the main application
thread (gtk main).

Since they're async, gtk schedules them as needed. Even though the actual
period of the separate timeouts is larger. The effective period between
all timeout callbacks is <15ms and the main application thread never idles.

gtk2_ardour/ardour_ui.cc
gtk2_ardour/ardour_ui_dialogs.cc

index 133e991a06cb29a23aac14968a4a74ccaf60781c..aeac8a1637b0a0b92436aab7bd3ab6bfcdc4ebb2 100644 (file)
@@ -1006,7 +1006,9 @@ If you still wish to quit, please use the\n\n\
 
                second_connection.disconnect ();
                point_one_second_connection.disconnect ();
+#ifndef PLATFORM_WINDOWS
                point_zero_something_second_connection.disconnect();
+#endif
                fps_connection.disconnect();
        }
 
@@ -1159,6 +1161,9 @@ gint
 ARDOUR_UI::every_fps ()
 {
        FPSUpdate(); /* EMIT_SIGNAL */
+#ifdef PLATFORM_WINDOWS
+       every_point_zero_something_seconds();
+#endif
        return TRUE;
 }
 
@@ -1178,7 +1183,17 @@ ARDOUR_UI::set_fps_timeout_connection ()
                                * _session->frame_rate() / _session->nominal_frame_rate()
                                / _session->timecode_frames_per_second()
                                );
+#ifdef PLATFORM_WINDOWS
+               // the smallest windows scheduler time-slice is ~15ms.
+               // periodic GUI timeouts shorter than that will cause
+               // WaitForSingleObject to spinlock (100% of one CPU Core)
+               // and gtk never enters idle mode.
+               // also changing timeBeginPeriod(1) does not affect that in
+               // any beneficial way, so we just limit the max rate for now.
+               interval = std::max(30u, interval); // at most ~33Hz.
+#else
                interval = std::max(8u, interval); // at most 120Hz.
+#endif
        }
        fps_connection.disconnect();
        fps_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_fps), interval);
index 8cd65ef378979017444160735b59df48f909b45f..654525358264ca2551b71ad641a62ddaf64b8eee 100644 (file)
@@ -184,7 +184,9 @@ ARDOUR_UI::set_session (Session *s)
 
        second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_second), 1000);
        point_one_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_one_seconds), 100);
+#ifndef PLATFORM_WINDOWS
        point_zero_something_second_connection = Glib::signal_timeout().connect (sigc::mem_fun(*this, &ARDOUR_UI::every_point_zero_something_seconds), 40);
+#endif
        set_fps_timeout_connection();
 
        update_format ();
@@ -286,7 +288,9 @@ ARDOUR_UI::unload_session (bool hide_stuff)
 
        second_connection.disconnect ();
        point_one_second_connection.disconnect ();
+#ifndef PLATFORM_WINDOWS
        point_zero_something_second_connection.disconnect();
+#endif
        fps_connection.disconnect();
 
        if (editor_meter) {