Browse Source

[peerdist] Gather and report peer statistics during download

Record and report the number of peers (calculated as the maximum
number of peers discovered for a block's segment at the time that the
block download is complete), and the percentage of blocks retrieved
from peers rather than from the origin server.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 7 years ago
parent
commit
7e673a6b67
5 changed files with 114 additions and 0 deletions
  1. 6
    0
      src/include/ipxe/peerdisc.h
  2. 13
    0
      src/include/ipxe/peermux.h
  3. 8
    0
      src/net/peerblk.c
  4. 30
    0
      src/net/peerdisc.c
  5. 57
    0
      src/net/peermux.c

+ 6
- 0
src/include/ipxe/peerdisc.h View File

109
 
109
 
110
 extern unsigned int peerdisc_timeout_secs;
110
 extern unsigned int peerdisc_timeout_secs;
111
 
111
 
112
+extern void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
113
+			    struct list_head *peers );
114
+#define peerdisc_stat_TYPE( object_type )				\
115
+	typeof ( void ( object_type, struct peerdisc_peer *peer,	\
116
+			struct list_head *peers ) )
117
+
112
 extern int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
118
 extern int peerdisc_open ( struct peerdisc_client *peerdisc, const void *id,
113
 			   size_t len );
119
 			   size_t len );
114
 extern void peerdisc_close ( struct peerdisc_client *peerdisc );
120
 extern void peerdisc_close ( struct peerdisc_client *peerdisc );

+ 13
- 0
src/include/ipxe/peermux.h View File

41
 	struct interface xfer;
41
 	struct interface xfer;
42
 };
42
 };
43
 
43
 
44
+/** PeerDist statistics */
45
+struct peerdist_statistics {
46
+	/** Maximum observed number of peers */
47
+	unsigned int peers;
48
+	/** Number of blocks downloaded in total */
49
+	unsigned int total;
50
+	/** Number of blocks downloaded from peers */
51
+	unsigned int local;
52
+};
53
+
44
 /** A PeerDist download multiplexer */
54
 /** A PeerDist download multiplexer */
45
 struct peerdist_multiplexer {
55
 struct peerdist_multiplexer {
46
 	/** Reference count */
56
 	/** Reference count */
65
 	struct list_head idle;
75
 	struct list_head idle;
66
 	/** Block downloads */
76
 	/** Block downloads */
67
 	struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
77
 	struct peerdist_multiplexed_block block[PEERMUX_MAX_BLOCKS];
78
+
79
+	/** Statistics */
80
+	struct peerdist_statistics stats;
68
 };
81
 };
69
 
82
 
70
 extern int peermux_filter ( struct interface *xfer, struct interface *info,
83
 extern int peermux_filter ( struct interface *xfer, struct interface *info,

+ 8
- 0
src/net/peerblk.c View File

270
  */
270
  */
271
 static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
271
 static void peerblk_done ( struct peerdist_block *peerblk, int rc ) {
272
 	struct digest_algorithm *digest = peerblk->digest;
272
 	struct digest_algorithm *digest = peerblk->digest;
273
+	struct peerdisc_segment *segment = peerblk->discovery.segment;
274
+	struct peerdisc_peer *head;
275
+	struct peerdisc_peer *peer;
273
 	uint8_t hash[digest->digestsize];
276
 	uint8_t hash[digest->digestsize];
274
 	unsigned long now = peerblk_timestamp();
277
 	unsigned long now = peerblk_timestamp();
275
 
278
 
296
 	profile_custom ( &peerblk_attempt_success_profiler,
299
 	profile_custom ( &peerblk_attempt_success_profiler,
297
 			 ( now - peerblk->attempted ) );
300
 			 ( now - peerblk->attempted ) );
298
 
301
 
302
+	/* Report peer statistics */
303
+	head = list_entry ( &segment->peers, struct peerdisc_peer, list );
304
+	peer = ( ( peerblk->peer == head ) ? NULL : peerblk->peer );
305
+	peerdisc_stat ( &peerblk->xfer, peer, &segment->peers );
306
+
299
 	/* Close download */
307
 	/* Close download */
300
 	peerblk_close ( peerblk, 0 );
308
 	peerblk_close ( peerblk, 0 );
301
 	return;
309
 	return;

+ 30
- 0
src/net/peerdisc.c View File

76
 static int peerdisc_discovered ( struct peerdisc_segment *segment,
76
 static int peerdisc_discovered ( struct peerdisc_segment *segment,
77
 				 const char *location );
77
 				 const char *location );
78
 
78
 
79
+/******************************************************************************
80
+ *
81
+ * Statistics reporting
82
+ *
83
+ ******************************************************************************
84
+ */
85
+
86
+/**
87
+ * Report peer discovery statistics
88
+ *
89
+ * @v intf		Interface
90
+ * @v peer		Selected peer (or NULL)
91
+ * @v peers		List of available peers
92
+ */
93
+void peerdisc_stat ( struct interface *intf, struct peerdisc_peer *peer,
94
+		     struct list_head *peers ) {
95
+	struct interface *dest;
96
+	peerdisc_stat_TYPE ( void * ) *op =
97
+		intf_get_dest_op ( intf, peerdisc_stat, &dest );
98
+	void *object = intf_object ( dest );
99
+
100
+	if ( op ) {
101
+		op ( object, peer, peers );
102
+	} else {
103
+		/* Default is to do nothing */
104
+	}
105
+
106
+	intf_put ( dest );
107
+}
108
+
79
 /******************************************************************************
109
 /******************************************************************************
80
  *
110
  *
81
  * Discovery sockets
111
  * Discovery sockets

+ 57
- 0
src/net/peermux.c View File

24
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
24
 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25
 
25
 
26
 #include <stdlib.h>
26
 #include <stdlib.h>
27
+#include <stdio.h>
27
 #include <errno.h>
28
 #include <errno.h>
28
 #include <ipxe/uri.h>
29
 #include <ipxe/uri.h>
29
 #include <ipxe/xferbuf.h>
30
 #include <ipxe/xferbuf.h>
31
+#include <ipxe/job.h>
30
 #include <ipxe/peerblk.h>
32
 #include <ipxe/peerblk.h>
31
 #include <ipxe/peermux.h>
33
 #include <ipxe/peermux.h>
32
 
34
 
74
 	intf_shutdown ( &peermux->info, rc );
76
 	intf_shutdown ( &peermux->info, rc );
75
 }
77
 }
76
 
78
 
79
+/**
80
+ * Report progress of PeerDist download
81
+ *
82
+ * @v peermux		PeerDist download multiplexer
83
+ * @v progress		Progress report to fill in
84
+ * @ret ongoing_rc	Ongoing job status code (if known)
85
+ */
86
+static int peermux_progress ( struct peerdist_multiplexer *peermux,
87
+			      struct job_progress *progress ) {
88
+	struct peerdist_statistics *stats = &peermux->stats;
89
+	unsigned int percentage;
90
+
91
+	/* Construct PeerDist status message */
92
+	if ( stats->total ) {
93
+		percentage = ( ( 100 * stats->local ) / stats->total );
94
+		snprintf ( progress->message, sizeof ( progress->message ),
95
+			   "%3d%% from %d peers", percentage, stats->peers );
96
+	}
97
+
98
+	return 0;
99
+}
100
+
77
 /**
101
 /**
78
  * Receive content information
102
  * Receive content information
79
  *
103
  *
274
 	return xfer_buffer ( &peermux->xfer );
298
 	return xfer_buffer ( &peermux->xfer );
275
 }
299
 }
276
 
300
 
301
+/**
302
+ * Record peer discovery statistics
303
+ *
304
+ * @v peermblk		PeerDist multiplexed block download
305
+ * @v peer		Selected peer (or NULL)
306
+ * @v peers		List of available peers
307
+ */
308
+static void peermux_block_stat ( struct peerdist_multiplexed_block *peermblk,
309
+				 struct peerdisc_peer *peer,
310
+				 struct list_head *peers ) {
311
+	struct peerdist_multiplexer *peermux = peermblk->peermux;
312
+	struct peerdist_statistics *stats = &peermux->stats;
313
+	struct peerdisc_peer *tmp;
314
+	unsigned int count = 0;
315
+
316
+	/* Record maximum number of available peers */
317
+	list_for_each_entry ( tmp, peers, list )
318
+		count++;
319
+	if ( count > stats->peers )
320
+		stats->peers = count;
321
+
322
+	/* Update block counts */
323
+	if ( peer )
324
+		stats->local++;
325
+	stats->total++;
326
+	DBGC2 ( peermux, "PEERMUX %p downloaded %d/%d from %d peers\n",
327
+		peermux, stats->local, stats->total, stats->peers );
328
+}
329
+
277
 /**
330
 /**
278
  * Close multiplexed block download
331
  * Close multiplexed block download
279
  *
332
  *
303
 
356
 
304
 /** Data transfer interface operations */
357
 /** Data transfer interface operations */
305
 static struct interface_operation peermux_xfer_operations[] = {
358
 static struct interface_operation peermux_xfer_operations[] = {
359
+	INTF_OP ( job_progress, struct peerdist_multiplexer *,
360
+		  peermux_progress ),
306
 	INTF_OP ( intf_close, struct peerdist_multiplexer *, peermux_close ),
361
 	INTF_OP ( intf_close, struct peerdist_multiplexer *, peermux_close ),
307
 };
362
 };
308
 
363
 
330
 		  peermux_block_deliver ),
385
 		  peermux_block_deliver ),
331
 	INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
386
 	INTF_OP ( xfer_buffer, struct peerdist_multiplexed_block *,
332
 		  peermux_block_buffer ),
387
 		  peermux_block_buffer ),
388
+	INTF_OP ( peerdisc_stat, struct peerdist_multiplexed_block *,
389
+		  peermux_block_stat ),
333
 	INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
390
 	INTF_OP ( intf_close, struct peerdist_multiplexed_block *,
334
 		  peermux_block_close ),
391
 		  peermux_block_close ),
335
 };
392
 };

Loading…
Cancel
Save