Skip to content

Commit 5339287

Browse files
jeffhostetlergitster
authored andcommitted
t/helper/fsmonitor-client: create stress test
Create a stress test to hammer on the fsmonitor daemon. Create a client-side thread pool of n threads and have each of them make m requests as fast as they can. We do not currently inspect the contents of the response. We're only interested in placing a heavy request load on the daemon. This test is useful for interactive testing and various experimentation. For example, to place additional load on the daemon while another test is running. We currently do not have a test script that actually uses this helper. We might add such a test in the future. Signed-off-by: Jeff Hostetler <jeffhost@microsoft.com> Signed-off-by: Junio C Hamano <gitster@pobox.com>
1 parent a1931de commit 5339287

File tree

1 file changed

+106
-0
lines changed

1 file changed

+106
-0
lines changed

t/helper/test-fsmonitor-client.c

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
#include "cache.h"
88
#include "parse-options.h"
99
#include "fsmonitor-ipc.h"
10+
#include "thread-utils.h"
11+
#include "trace2.h"
1012

1113
#ifndef HAVE_FSMONITOR_DAEMON_BACKEND
1214
int cmd__fsmonitor_client(int argc, const char **argv)
@@ -79,20 +81,121 @@ static int do_send_flush(void)
7981
return 0;
8082
}
8183

84+
struct hammer_thread_data
85+
{
86+
pthread_t pthread_id;
87+
int thread_nr;
88+
89+
int nr_requests;
90+
const char *token;
91+
92+
int sum_successful;
93+
int sum_errors;
94+
};
95+
96+
static void *hammer_thread_proc(void *_hammer_thread_data)
97+
{
98+
struct hammer_thread_data *data = _hammer_thread_data;
99+
struct strbuf answer = STRBUF_INIT;
100+
int k;
101+
int ret;
102+
103+
trace2_thread_start("hammer");
104+
105+
for (k = 0; k < data->nr_requests; k++) {
106+
strbuf_reset(&answer);
107+
108+
ret = fsmonitor_ipc__send_query(data->token, &answer);
109+
if (ret < 0)
110+
data->sum_errors++;
111+
else
112+
data->sum_successful++;
113+
}
114+
115+
strbuf_release(&answer);
116+
trace2_thread_exit();
117+
return NULL;
118+
}
119+
120+
/*
121+
* Start a pool of client threads that will each send a series of
122+
* commands to the daemon.
123+
*
124+
* The goal is to overload the daemon with a sustained series of
125+
* concurrent requests.
126+
*/
127+
static int do_hammer(const char *token, int nr_threads, int nr_requests)
128+
{
129+
struct hammer_thread_data *data = NULL;
130+
int k;
131+
int sum_join_errors = 0;
132+
int sum_commands = 0;
133+
int sum_errors = 0;
134+
135+
if (!token || !*token)
136+
token = get_token_from_index();
137+
if (nr_threads < 1)
138+
nr_threads = 1;
139+
if (nr_requests < 1)
140+
nr_requests = 1;
141+
142+
CALLOC_ARRAY(data, nr_threads);
143+
144+
for (k = 0; k < nr_threads; k++) {
145+
struct hammer_thread_data *p = &data[k];
146+
p->thread_nr = k;
147+
p->nr_requests = nr_requests;
148+
p->token = token;
149+
150+
if (pthread_create(&p->pthread_id, NULL, hammer_thread_proc, p)) {
151+
warning("failed to create thread[%d] skipping remainder", k);
152+
nr_threads = k;
153+
break;
154+
}
155+
}
156+
157+
for (k = 0; k < nr_threads; k++) {
158+
struct hammer_thread_data *p = &data[k];
159+
160+
if (pthread_join(p->pthread_id, NULL))
161+
sum_join_errors++;
162+
sum_commands += p->sum_successful;
163+
sum_errors += p->sum_errors;
164+
}
165+
166+
fprintf(stderr, "HAMMER: [threads %d][requests %d] [ok %d][err %d][join %d]\n",
167+
nr_threads, nr_requests, sum_commands, sum_errors, sum_join_errors);
168+
169+
free(data);
170+
171+
/*
172+
* Return an error if any of the _send_query requests failed.
173+
* We don't care about thread create/join errors.
174+
*/
175+
return sum_errors > 0;
176+
}
177+
82178
int cmd__fsmonitor_client(int argc, const char **argv)
83179
{
84180
const char *subcmd;
85181
const char *token = NULL;
182+
int nr_threads = 1;
183+
int nr_requests = 1;
86184

87185
const char * const fsmonitor_client_usage[] = {
88186
"test-tool fsmonitor-client query [<token>]",
89187
"test-tool fsmonitor-client flush",
188+
"test-tool fsmonitor-client hammer [<token>] [<threads>] [<requests>]",
90189
NULL,
91190
};
92191

93192
struct option options[] = {
94193
OPT_STRING(0, "token", &token, "token",
95194
"command token to send to the server"),
195+
196+
OPT_INTEGER(0, "threads", &nr_threads, "number of client threads"),
197+
OPT_INTEGER(0, "requests", &nr_requests, "number of requests per thread"),
198+
96199
OPT_END()
97200
};
98201

@@ -111,6 +214,9 @@ int cmd__fsmonitor_client(int argc, const char **argv)
111214
if (!strcmp(subcmd, "flush"))
112215
return !!do_send_flush();
113216

217+
if (!strcmp(subcmd, "hammer"))
218+
return !!do_hammer(token, nr_threads, nr_requests);
219+
114220
die("Unhandled subcommand: '%s'", subcmd);
115221
}
116222
#endif

0 commit comments

Comments
 (0)