39 Door_call(doorfd, &arg); /* запуск */
40 Start_time();
41 for (i = 0; i < nloop; i++)
42 Door_call(doorfd, &arg);
43 printf("latency: %.3f usec\n", Stop_time() / nloop);
44 Kill(childpid, SIGTERM);
45 unlink(argv[1]);
46 exit(0);
47 }
Программа измерения времени задержки Sun RPC
Для измерения времени задержки Sun RPC мы напишем две программы: клиент и сервер, аналогично измерению полосы пропускания. Мы используем старый файл спецификации RPC, но на этот раз клиент вызывает нулевую процедуру сервера. Вспомните упражнение 16.11: эта процедура не принимает никаких аргументов и ничего не возвращает. Это именно то, что нам нужно, чтобы определить задержку. В листинге А.18 приведен текст клиента. Как и в решении упражнения 16.11, нам нужно воспользоваться clnt_call для вызова нулевой процедуры; в заглушке клиента отсутствует необходимая заглушка для этой процедуры.
//bench/lat_sunrpc_client.с
1 #include "unpipc.h"
2 #include "lat_sunrpc.h"
3 int
4 main(int argc, char **argv)
5 {
6 int i, nloop;
7 CLIENT *cl;
8 struct timeval tv;
9 if (argc != 4)
10 err_quit("usage: lat_sunrpc_client
11 nloop = atoi(argv[2]);
12 cl = Clnt_create(argv[1], BW_SUNRPC_PROG, BW_SUNRPC_VERS, argv[3]);
13 tv.tv_sec = 10;
14 tv.tv_usec = 0;
15 Start_time();
16 for (i = 0; i < nloop; i++) {
17 if (clnt_call(cl, NULLPROC, xdr_void, NULL,
18 xdr_void, NULL, tv) != RPC_SUCCESS)
19 err_quit("%s", clnt_sperror(cl, argv[1]));
20 }
21 printf("latency: %.3f usec\n", Stop_time() / nloop);
22 exit(0);
23 }
Мы компилируем сервер с функцией, приведенной в листинге А.13, но она все равно не вызывается. Поскольку мы используем rpcgen для построения клиента и сервера, нам нужно определить хотя бы одну процедуру сервера, но мы не обязаны ее вызывать. Причина, по которой мы используем rpcgen, заключается в том, что она автоматически создает функцию main сервера с нулевой процедурой, которая нам нужна.
А.5. Синхронизация потоков: программы
Для измерения времени, уходящего на синхронизацию при использовании различных средств, мы создаем некоторое количество потоков (от одного до пяти, согласно табл. А.4 и А.5), каждый из которых увеличивает счетчик в разделяемой памяти большое количество раз, используя различные формы синхронизации для получения доступа к счетчику.
Взаимные исключения Posix
В листинге А.19 приведены глобальные переменные и функция main пpoгрaммы, измеряющей быстродействие взаимных исключений Posix.
//bench/incr_pxmutex1.с
1 #include "unpipc.h"
2 #define MAXNTHREADS 100
3 int nloop;
4 struct {
5 pthread_mutex_t mutex;
6 long counter;
7 } shared = {
8 PTHREAD_MUTEX_INITIALIZER
9 };
10 void *incr(void *);
11 int
12 main(int argc, char **argv)
13 {
14 int i, nthreads;
15 pthread_t tid[MAXNTHREADS];
16 if (argc != 3)
17 err_quit("usage: incr_pxmutex1 <#loops> <#threads>");
18 nloop = atoi(argv[1]);
19 nthreads = min(atoi(argv[2]), MAXNTHREADS);
20 /* блокировка взаимного исключения */
21 Pthread_mutex_lock(&shared.mutex);
22 /* создание потоков */
23 Set_concurrency(nthreads);
24 for (i = 0; i < nthreads; i++) {
25 Pthread_create(&tid[i], NULL, incr, NULL);
26 }