summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Brown <mcb30@ipxe.org>2021-06-17 15:29:22 +0100
committerMichael Brown <mcb30@ipxe.org>2021-06-17 15:29:22 +0100
commit85af9c856105d01e3de01a9fb767a916b7eb8d5b (patch)
treede652eaba02e346fb311573a209fdbb7993152d4
parent51c88a4a62116d77a854b55100c6955d6f1eb6dc (diff)
downloadqemu-ipxe-peerdisc_recent.tar.gz
[peerdist] Assume that most recently discovered peer can be reusedpeerdisc_recent
The peer discovery time has a significant impact on the overall PeerDist download speed, since each block requires an individual discovery attempt. In most cases, a peer that responds for block N will turn out to also respond for block N+1. Assume that the most recently discovered peer (for any block) probably has a copy of the next block to be discovered, thereby allowing the peer download attempt to begin immediately. In the case that this assumption is incorrect, the existing error recovery path will allow for fallback to newly discovered peers (or to the origin server). Suggested-by: Andreas Hammarskjöld <junior@2PintSoftware.com> Signed-off-by: Michael Brown <mcb30@ipxe.org>
-rw-r--r--src/net/peerdisc.c23
1 files changed, 23 insertions, 0 deletions
diff --git a/src/net/peerdisc.c b/src/net/peerdisc.c
index 55e3f7fa..d7e0d298 100644
--- a/src/net/peerdisc.c
+++ b/src/net/peerdisc.c
@@ -73,6 +73,9 @@ static LIST_HEAD ( peerdisc_segments );
*/
unsigned int peerdisc_timeout_secs = PEERDISC_DEFAULT_TIMEOUT_SECS;
+/** Most recently discovered peer (for any block) */
+static char *peerdisc_recent;
+
/** Hosted cache server */
static char *peerhost;
@@ -383,6 +386,7 @@ static int peerdisc_discovered ( struct peerdisc_segment *segment,
struct peerdisc_peer *peer;
struct peerdisc_client *peerdisc;
struct peerdisc_client *tmp;
+ char *recent;
/* Ignore duplicate peers */
list_for_each_entry ( peer, &segment->peers, list ) {
@@ -403,6 +407,15 @@ static int peerdisc_discovered ( struct peerdisc_segment *segment,
/* Add to end of list of peers */
list_add_tail ( &peer->list, &segment->peers );
+ /* Record as most recently discovered peer */
+ if ( location != peerdisc_recent ) {
+ recent = strdup ( location );
+ if ( recent ) {
+ free ( peerdisc_recent );
+ peerdisc_recent = recent;
+ }
+ }
+
/* Notify all clients */
list_for_each_entry_safe ( peerdisc, tmp, &segment->clients, list )
peerdisc->op->discovered ( peerdisc );
@@ -484,6 +497,16 @@ static struct peerdisc_segment * peerdisc_create ( const char *id ) {
} else {
+ /* Add most recently discovered peer to list of peers
+ *
+ * This is a performance optimisation: we assume that
+ * the most recently discovered peer for any block has
+ * a high probability of also having a copy of the
+ * next block that we attempt to discover.
+ */
+ if ( peerdisc_recent )
+ peerdisc_discovered ( segment, peerdisc_recent );
+
/* Start discovery timer */
start_timer_nodelay ( &segment->timer );
DBGC2 ( segment, "PEERDISC %p discovering %s\n",