From c75d81f4c4e347c00410dd2680859aabbc094118 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sat, 27 Aug 2016 00:44:10 -0700 Subject: [PATCH] client: prioritize network (including GUI RPC) over async file ops This is an effort to make the Manager responsive even when lots of VM jobs are starting up. --- client/app_start.cpp | 2 +- client/async_file.cpp | 6 ++---- client/async_file.h | 5 ++++- client/client_state.cpp | 45 +++++++++++++++++++++-------------------- 4 files changed, 30 insertions(+), 28 deletions(-) diff --git a/client/app_start.cpp b/client/app_start.cpp index cc3bae52c4..b0529d9ffd 100644 --- a/client/app_start.cpp +++ b/client/app_start.cpp @@ -1363,7 +1363,7 @@ void run_test_app() { exit(1); } while (1) { - do_async_file_ops(); + do_async_file_op(); if (at.async_copy == NULL) { break; } diff --git a/client/async_file.cpp b/client/async_file.cpp index 7a71f128ec..e433466cb1 100644 --- a/client/async_file.cpp +++ b/client/async_file.cpp @@ -325,21 +325,19 @@ void remove_async_verify(ASYNC_VERIFY* avp) { // Note: if there are lots of pending operations, // it's better to finish the oldest one before starting the rest // -bool do_async_file_ops() { +void do_async_file_op() { if (async_copies.size()) { ASYNC_COPY* acp = async_copies[0]; if (acp->copy_chunk()) { async_copies.erase(async_copies.begin()); delete acp; } - return true; + return; } if (async_verifies.size()) { if (async_verifies[0]->verify_chunk()) { async_verifies.erase(async_verifies.begin()); } - return true; } - return false; } diff --git a/client/async_file.h b/client/async_file.h index a86be550c3..355f2fcf30 100644 --- a/client/async_file.h +++ b/client/async_file.h @@ -91,6 +91,9 @@ extern std::vector async_copies; extern void remove_async_copy(ASYNC_COPY*); extern void remove_async_verify(ASYNC_VERIFY*); -extern bool do_async_file_ops(); +inline bool have_async_file_op() { + return (async_verifies.size() || async_copies.size()); +} +extern void do_async_file_op(); #endif diff --git a/client/client_state.cpp b/client/client_state.cpp index 97c8697a9a..152dc99da0 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -809,22 +809,27 @@ FDSET_GROUP all_fds; // Spend x seconds either doing I/O (if possible) or sleeping. // -void CLIENT_STATE::do_io_or_sleep(double x) { +void CLIENT_STATE::do_io_or_sleep(double max_time) { int n; struct timeval tv; set_now(); - double end_time = now + x; - //int loops = 0; + double end_time = now + max_time; + double time_remaining = max_time; while (1) { - bool action = do_async_file_ops(); - curl_fds.zero(); gui_rpc_fds.zero(); http_ops->get_fdset(curl_fds); all_fds = curl_fds; gui_rpcs.get_fdset(gui_rpc_fds, all_fds); - double_to_timeval(action?0:x, tv); + + bool have_async = have_async_file_op(); + + // prioritize network (including GUI RPC) over async file ops. + // if there's a pending asynch file op, do the select with zero timeout; + // otherwise do it for the remaining amount of time. + + double_to_timeval(have_async?0:time_remaining, tv); #ifdef NEW_CPU_THROTTLE client_mutex.unlock(); #endif @@ -843,28 +848,24 @@ void CLIENT_STATE::do_io_or_sleep(double x) { // called pretty often, even if no descriptors are enabled. // So do the "if (n==0) break" AFTER the got_selects(). - http_ops->got_select(all_fds, x); + http_ops->got_select(all_fds, time_remaining); gui_rpcs.got_select(all_fds); - if (!action && n==0) break; - -#if 0 - // Limit number of times thru this loop. - // Can get stuck in while loop, if network isn't available, - // DNS lookups tend to eat CPU cycles. - // - if (loops++ > 99) { - boinc_sleep(.01); -#ifdef __EMX__ - DosSleep(0); -#endif - break; + if (have_async) { + // do the async file op only if no network activity + // + if (n == 0) { + do_async_file_op(); + } + } else { + if (n == 0) { + break; + } } -#endif set_now(); if (now > end_time) break; - x = end_time - now; + time_remaining = end_time - now; } }