aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2019-08-12 22:58:21 +0100
committerMichael Brown <mcb30@ipxe.org>2019-08-12 23:05:58 +0100
commitc9e393e727debc150a7aa5806e0d740f53b1b8d5 (patch)
tree12547538508204e1de141cd85e615b20c6e77623
parentc63ef427a2b18d318b313a4adf6267bb4dfa0c1c (diff)
downloadipxe-peerdist.zip
ipxe-peerdist.tar.gz
ipxe-peerdist.tar.bz2
[peerdist] Reduce number of concurrent requests to origin serverpeerdist
Origin server requests are likely to be significantly more expensive than local peer requests: they consume sparse uplink bandwidth and, if using HTTPS, substantial local resources. Start with a low number of concurrent block downloads and adjust this number in response to the availability of local peers, in order to avoid hammering the origin server with the full concurrency limit. Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/include/ipxe/peermux.h7
-rw-r--r--src/net/peermux.c32
2 files changed, 30 insertions, 9 deletions
diff --git a/src/include/ipxe/peermux.h b/src/include/ipxe/peermux.h
index 54acbfe..8970759 100644
--- a/src/include/ipxe/peermux.h
+++ b/src/include/ipxe/peermux.h
@@ -18,6 +18,9 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
#include <ipxe/xferbuf.h>
#include <ipxe/pccrc.h>
+/** Minimum number of concurrent block downloads */
+#define PEERMUX_MIN_BLOCKS 2
+
/** Maximum number of concurrent block downloads */
#define PEERMUX_MAX_BLOCKS 32
@@ -69,6 +72,10 @@ struct peerdist_multiplexer {
/** Block download initiation process */
struct process process;
+ /** Number of concurrent block downloads */
+ unsigned int count;
+ /** Maximum number of concurrent block downloads */
+ unsigned int limit;
/** List of busy block downloads */
struct list_head busy;
/** List of idle block downloads */
diff --git a/src/net/peermux.c b/src/net/peermux.c
index a391ed3..c354f21 100644
--- a/src/net/peermux.c
+++ b/src/net/peermux.c
@@ -92,7 +92,8 @@ static int peermux_progress ( struct peerdist_multiplexer *peermux,
if ( stats->total ) {
percentage = ( ( 100 * stats->local ) / stats->total );
snprintf ( progress->message, sizeof ( progress->message ),
- "%3d%% from %d peers", percentage, stats->peers );
+ "%3d%% from %d peers (x%d)", percentage,
+ stats->peers, peermux->limit );
}
return 0;
@@ -184,14 +185,17 @@ static void peermux_step ( struct peerdist_multiplexer *peermux ) {
unsigned int next_block;
int rc;
- /* Stop initiation process if all block downloads are busy */
- peermblk = list_first_entry ( &peermux->idle,
- struct peerdist_multiplexed_block, list );
- if ( ! peermblk ) {
+ /* Stop initiation process if we have reached the concurrency limit */
+ if ( peermux->count >= peermux->limit ) {
process_del ( &peermux->process );
return;
}
+ /* Get next available idle block download */
+ peermblk = list_first_entry ( &peermux->idle,
+ struct peerdist_multiplexed_block, list );
+ assert ( peermblk != NULL );
+
/* Increment block index */
next_block = ( block->index + 1 );
@@ -251,6 +255,7 @@ static void peermux_step ( struct peerdist_multiplexer *peermux ) {
/* Move to list of busy block downloads */
list_del ( &peermblk->list );
list_add_tail ( &peermblk->list, &peermux->busy );
+ peermux->count++;
return;
@@ -319,12 +324,19 @@ static void peermux_block_stat ( struct peerdist_multiplexed_block *peermblk,
if ( count > stats->peers )
stats->peers = count;
- /* Update block counts */
- if ( peer )
+ /* Update block counts and concurrency limit */
+ if ( peer ) {
stats->local++;
+ if ( peermux->limit < PEERMUX_MAX_BLOCKS )
+ peermux->limit++;
+ } else {
+ if ( peermux->limit > PEERMUX_MIN_BLOCKS )
+ peermux->limit--;
+ }
stats->total++;
- DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers\n",
- peermux, stats->local, stats->total, stats->peers );
+ DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers (x%d)\n",
+ peermux, stats->local, stats->total, stats->peers,
+ peermux->limit );
}
/**
@@ -340,6 +352,7 @@ static void peermux_block_close ( struct peerdist_multiplexed_block *peermblk,
/* Move to list of idle downloads */
list_del ( &peermblk->list );
list_add_tail ( &peermblk->list, &peermux->idle );
+ peermux->count--;
/* If any error occurred, terminate the whole multiplexer */
if ( rc != 0 ) {
@@ -426,6 +439,7 @@ int peermux_filter ( struct interface *xfer, struct interface *info,
&peermux->cache.info.raw.data );
process_init_stopped ( &peermux->process, &peermux_process_desc,
&peermux->refcnt );
+ peermux->limit = PEERMUX_MIN_BLOCKS;
INIT_LIST_HEAD ( &peermux->busy );
INIT_LIST_HEAD ( &peermux->idle );
for ( i = 0 ; i < PEERMUX_MAX_BLOCKS ; i++ ) {