Bug #2186
openGTK4 Client consumme 100% CPU (at least on debian with GTK 4.18)
0%
Description
I found that among other issues, the GTK4 client was eating 100% of the CPU.
Digging around with GDB pinpoint to a cascade of events. I solve it by blocking/unblocking them in plrdlg.c (from code version 3.2.5) :
866 void real_players_dialog_update(void *unused)
867 {
868 GtkTreeModel *model;
869 GtkTreeIter iter;
870 int selected;
871
872 if (NULL == players_dialog_shell) {
873 return;
874 }
875
876 /* Save the selection. */
877 if (gtk_tree_selection_get_selected(players_selection, &model, &iter)) {
878 gtk_tree_model_get(model, &iter, PLR_DLG_COL_ID, &selected, -1);
879 } else {
880 selected = -1;
881 }
882
883 g_signal_handlers_block_by_func(players_selection, G_CALLBACK(selection_callback), NULL);
884 gtk_list_store_clear(players_dialog_store);
885 players_iterate(pplayer) {
886 if (!player_should_be_shown(pplayer)) {
887 continue;
888 }
889 gtk_list_store_append(players_dialog_store, &iter);
890 fill_row(players_dialog_store, &iter, pplayer);
891 if (player_number(pplayer) == selected) {
892 /* Restore the selection. */
893 gtk_tree_selection_select_iter(players_selection, &iter);
894 }
895 } players_iterate_end;
896
897 update_views();
898 g_signal_handlers_unblock_by_func(players_selection, G_CALLBACK(selection_callback), NULL);
899 }
running the new version so CPU back to normal ...
As I am not an expert in GUI, I let you decide if this is the right fix or not :).
Best regards.
Updated by Caeies Caeies about 5 hours ago
Looks Like I was a little bit optimistic ... While this fix drastically lower the number of spawn threads, it doesn't solve all the issues ...
I had to do more fixes:
replace the add_idle_callback function which looks like infinite loop for GTK4 code by animation_tick_cb function like (remove in pages.c and edit gui_main.c):
227 static gboolean animation_tick_cb(GtkWidget *widget, GdkFrameClock *frame_clock, gpointer user_data);
...
1519 gtk_widget_add_tick_callback(map_canvas, animation_tick_cb, NULL, NULL);
...
2447 static gboolean animation_tick_cb(GtkWidget *widget,
2448 GdkFrameClock *frame_clock,
2449 gpointer user_data)
2450 {
2451 if (get_current_client_page() == PAGE_GAME) {
2452 update_animation();
2453 }
2454 return G_SOURCE_CONTINUE;
2455 }
and for the add_idle_callback(main_message_area_resize, NULL); one (in pages.c):
3605 //add_idle_callback(main_message_area_resize, NULL);
3606 main_message_area_resize(NULL);
and in gui_main.c:
362 void main_message_area_resize(void *data)
363 {
364 if (get_current_client_page() == PAGE_GAME) {
365 static int old_width = 0, old_height = 0;
366 int width = gtk_widget_get_width(GTK_WIDGET(main_message_area));
367 int height = gtk_widget_get_height(GTK_WIDGET(main_message_area));
368
369 if (width != old_width
370 || height != old_height) {
371 chatline_scroll_to_bottom(TRUE);
372 old_width = width;
373 old_height = height;
374 }
375
376 // add_idle_callback(main_message_area_resize, NULL);
377 }
378 }
...
2076 /* Assumes client_state is set */
2077 timer_id = g_timeout_add(TIMER_INTERVAL, timer_callback, NULL);
2078
2079 g_signal_connect_swapped(main_message_area, "notify::default-width",
2080 G_CALLBACK(main_message_area_resize), NULL);
2081 g_signal_connect_swapped(main_message_area, "notify::default-height",
2082 G_CALLBACK(main_message_area_resize), NULL);
2083 }
...
With these changes, the GUI is much more reactive and consume only a very low CPU. NOTE: I guess that the same kind of adaptation should be done for the network ping case, but that's for later :).
Hope this is clear.
Updated by Caeies Caeies about 5 hours ago
Oups, forget to add this amend my initial correction by (in plrdlg.c):
866 void real_players_dialog_update(void *unused)
867 {
868 GtkTreeModel *model;
869 GtkTreeIter iter;
870 int selected;
871
872 if (NULL == players_dialog_shell) {
873 return;
874 }
875
876 /* Save the selection. */
877 if (gtk_tree_selection_get_selected(players_selection, &model, &iter)) {
878 gtk_tree_model_get(model, &iter, PLR_DLG_COL_ID, &selected, -1);
879 } else {
880 selected = -1;
881 }
882
883 g_object_freeze_notify(G_OBJECT(players_dialog_store));
884 g_signal_handlers_block_by_func(players_selection, G_CALLBACK(selection_callback), NULL);
885 gtk_list_store_clear(players_dialog_store);
886 players_iterate(pplayer) {
887 if (!player_should_be_shown(pplayer)) {
888 continue;
889 }
890 gtk_list_store_append(players_dialog_store, &iter);
891 fill_row(players_dialog_store, &iter, pplayer);
892 if (player_number(pplayer) == selected) {
893 /* Restore the selection. */
894 gtk_tree_selection_select_iter(players_selection, &iter);
895 }
896 } players_iterate_end;
897
898 update_views();
899 g_signal_handlers_unblock_by_func(players_selection, G_CALLBACK(selection_callback), NULL);
900 g_object_thaw_notify(G_OBJECT(players_dialog_store));
901 }
Would be better to generate a patch I guess. Let me know.