aboutsummaryrefslogtreecommitdiff
path: root/src/testing/testing_group.c
diff options
context:
space:
mode:
authorNathan S. Evans <evans@in.tum.de>2011-02-05 16:17:53 +0000
committerNathan S. Evans <evans@in.tum.de>2011-02-05 16:17:53 +0000
commit30eaa74c6e9a89373f255f4183d21a4599598035 (patch)
tree5fc5313837ba3c0a20949c615e7e6949e9ec86ee /src/testing/testing_group.c
parent0d53baa57a6d03f4e09082b0b835681dec6d71bd (diff)
downloadgnunet-30eaa74c6e9a89373f255f4183d21a4599598035.tar.gz
gnunet-30eaa74c6e9a89373f255f4183d21a4599598035.zip
vastly reduce cpu overhead when connecting peers
Diffstat (limited to 'src/testing/testing_group.c')
-rw-r--r--src/testing/testing_group.c101
1 files changed, 85 insertions, 16 deletions
diff --git a/src/testing/testing_group.c b/src/testing/testing_group.c
index 929cc9128..88408e871 100644
--- a/src/testing/testing_group.c
+++ b/src/testing/testing_group.c
@@ -662,6 +662,11 @@ struct GNUNET_TESTING_PeerGroup
662 unsigned int outstanding_connects; 662 unsigned int outstanding_connects;
663 663
664 /** 664 /**
665 * How many connects have already been scheduled?
666 */
667 unsigned int total_connects_scheduled;
668
669 /**
665 * Hostkeys loaded from a file. 670 * Hostkeys loaded from a file.
666 */ 671 */
667 char *hostkey_data; 672 char *hostkey_data;
@@ -685,10 +690,24 @@ struct ConnectTopologyContext
685 unsigned int remaining_connections; 690 unsigned int remaining_connections;
686 691
687 /** 692 /**
693 * How many more connections do we need to schedule?
694 */
695 unsigned int remaining_connects_to_schedule;
696
697 /**
688 * Handle to group of peers. 698 * Handle to group of peers.
689 */ 699 */
690 struct GNUNET_TESTING_PeerGroup *pg; 700 struct GNUNET_TESTING_PeerGroup *pg;
691 701
702 /**
703 * How long to try this connection before timing out.
704 */
705 struct GNUNET_TIME_Relative connect_timeout;
706
707 /**
708 * How many times to retry connecting the two peers.
709 */
710 unsigned int connect_attempts;
692 711
693 /** 712 /**
694 * Temp value set for each iteration. 713 * Temp value set for each iteration.
@@ -724,16 +743,6 @@ struct ConnectContext
724 struct ConnectTopologyContext *ct_ctx; 743 struct ConnectTopologyContext *ct_ctx;
725 744
726 /** 745 /**
727 * How long to try this connection before timing out.
728 */
729 struct GNUNET_TIME_Relative connect_timeout;
730
731 /**
732 * How many times to retry connecting the two peers.
733 */
734 unsigned int connect_attempts;
735
736 /**
737 * Whether this connection has been accounted for in the schedule_connect call. 746 * Whether this connection has been accounted for in the schedule_connect call.
738 */ 747 */
739 int counted; 748 int counted;
@@ -2815,6 +2824,41 @@ create_and_copy_blacklist_files (struct GNUNET_TESTING_PeerGroup *pg,
2815 return ret; 2824 return ret;
2816} 2825}
2817 2826
2827/* Forward Declaration */
2828static void
2829schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc);
2830
2831/**
2832 * Choose a random peer's next connection to create, and
2833 * call schedule_connect to set up the connect task.
2834 *
2835 * @param ct_ctx the overall connection context
2836 */
2837static void preschedule_connect(struct ConnectTopologyContext *ct_ctx)
2838{
2839 struct GNUNET_TESTING_PeerGroup *pg = ct_ctx->pg;
2840 struct PeerConnection *connection_iter;
2841 struct ConnectContext *connect_context;
2842 uint32_t random_peer;
2843
2844 if (ct_ctx->remaining_connects_to_schedule == 0)
2845 return;
2846 random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
2847 while (pg->peers[random_peer].connect_peers_head == NULL)
2848 random_peer = GNUNET_CRYPTO_random_u32(GNUNET_CRYPTO_QUALITY_WEAK, pg->total);
2849
2850 connection_iter = pg->peers[random_peer].connect_peers_head;
2851 GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Scheduling connection between %d and %d\n", random_peer, connection_iter->index);
2852
2853 connect_context = GNUNET_malloc (sizeof (struct ConnectContext));
2854 connect_context->first = pg->peers[random_peer].daemon;
2855 connect_context->second = pg->peers[connection_iter->index].daemon;
2856 connect_context->ct_ctx = ct_ctx;
2857 GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
2858 GNUNET_CONTAINER_DLL_remove(pg->peers[random_peer].connect_peers_head, pg->peers[random_peer].connect_peers_tail, connection_iter);
2859 ct_ctx->remaining_connects_to_schedule--;
2860}
2861
2818 2862
2819/** 2863/**
2820 * Internal notification of a connection, kept so that we can ensure some connections 2864 * Internal notification of a connection, kept so that we can ensure some connections
@@ -2841,6 +2885,8 @@ internal_connect_notify (void *cls,
2841 ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL); 2885 ct_ctx->notify_connections_done (ct_ctx->notify_cls, NULL);
2842 GNUNET_free (ct_ctx); 2886 GNUNET_free (ct_ctx);
2843 } 2887 }
2888 else
2889 preschedule_connect(ct_ctx);
2844 2890
2845 if (pg->notify_connection != NULL) 2891 if (pg->notify_connection != NULL)
2846 pg->notify_connection (pg->notify_connection_cls, first, second, distance, 2892 pg->notify_connection (pg->notify_connection_cls, first, second, distance,
@@ -2884,10 +2930,11 @@ schedule_connect (void *cls, const struct GNUNET_SCHEDULER_TaskContext *tc)
2884 outstanding_connects); 2930 outstanding_connects);
2885#endif 2931#endif
2886 pg->outstanding_connects++; 2932 pg->outstanding_connects++;
2933 pg->total_connects_scheduled++;
2887 GNUNET_TESTING_daemons_connect (connect_context->first, 2934 GNUNET_TESTING_daemons_connect (connect_context->first,
2888 connect_context->second, 2935 connect_context->second,
2889 connect_context->connect_timeout, 2936 connect_context->ct_ctx->connect_timeout,
2890 connect_context->connect_attempts, 2937 connect_context->ct_ctx->connect_attempts,
2891 &internal_connect_notify, 2938 &internal_connect_notify,
2892 connect_context->ct_ctx); 2939 connect_context->ct_ctx);
2893 GNUNET_free (connect_context); 2940 GNUNET_free (connect_context);
@@ -3017,8 +3064,8 @@ connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
3017 struct ConnectTopologyContext *ct_ctx; 3064 struct ConnectTopologyContext *ct_ctx;
3018#if OLD 3065#if OLD
3019 struct PeerConnection *connection_iter; 3066 struct PeerConnection *connection_iter;
3020 struct ConnectContext *connect_context;
3021#else 3067#else
3068 struct ConnectContext *connect_context;
3022 int ret; 3069 int ret;
3023#endif 3070#endif
3024 3071
@@ -3048,9 +3095,32 @@ connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
3048 GNUNET_free (ct_ctx); 3095 GNUNET_free (ct_ctx);
3049 return total; 3096 return total;
3050 } 3097 }
3098 ct_ctx->connect_timeout = connect_timeout;
3099 ct_ctx->connect_attempts = connect_attempts;
3051 ct_ctx->remaining_connections = total; 3100 ct_ctx->remaining_connections = total;
3052 total = 0; 3101 ct_ctx->remaining_connects_to_schedule = total;
3102
3053 3103
3104 /**
3105 * FIXME: iterating over peer lists in this way means that a single peer will have
3106 * all of its connections scheduled basically at once. This means a single peer
3107 * will have a lot of work to do, and may slow down the connection process. If
3108 * we could choose a connection *randomly* that would work much better.
3109 *
3110 * Even using the hashmap method we still choose all of a single peers connections.
3111 *
3112 * Will we incur a serious performance penalty iterating over the lists a bunch of
3113 * times? Probably not compared to the delays in connecting peers. Can't hurt
3114 * to try anyhow...
3115 */
3116 for (pg_iter = 0; pg_iter < pg->max_outstanding_connections; pg_iter++)
3117 {
3118 preschedule_connect(ct_ctx);
3119 }
3120 return total;
3121
3122#if SLOW
3123 total = 0;
3054 for (pg_iter = 0; pg_iter < pg->total; pg_iter++) 3124 for (pg_iter = 0; pg_iter < pg->total; pg_iter++)
3055 { 3125 {
3056#if OLD 3126#if OLD
@@ -3062,8 +3132,6 @@ connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
3062 connect_context->first = pg->peers[pg_iter].daemon; 3132 connect_context->first = pg->peers[pg_iter].daemon;
3063 connect_context->second = pg->peers[connection_iter->index].daemon; 3133 connect_context->second = pg->peers[connection_iter->index].daemon;
3064 connect_context->ct_ctx = ct_ctx; 3134 connect_context->ct_ctx = ct_ctx;
3065 connect_context->connect_timeout = connect_timeout;
3066 connect_context->connect_attempts = connect_attempts;
3067 GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context); 3135 GNUNET_SCHEDULER_add_now (&schedule_connect, connect_context);
3068 connection_iter = connection_iter->next; 3136 connection_iter = connection_iter->next;
3069 total++; 3137 total++;
@@ -3078,6 +3146,7 @@ connect_topology (struct GNUNET_TESTING_PeerGroup *pg,
3078#endif 3146#endif
3079 } 3147 }
3080 return total; 3148 return total;
3149#endif
3081} 3150}
3082 3151
3083 3152