Added SILC Thread Queue API
[silc.git] / lib / silcutil / tests / test_silcmutex.c
1 /* Locking performance tests.  Gives locsk&unlocks/second. */
2 /* Version 1.0 */
3
4 #include "silc.h"
5
6 typedef struct {
7   SilcThread thread;
8   SilcInt64 time;
9 } Context;
10
11 #define MAX_ROUND 8
12 #define MAX_MUL 4
13 #define MAX_THREADS 4
14 #define MAX_LOCKS 471234567
15
16 SilcMutex mutex;
17 SilcUInt64 cpu_freq = 0;
18 int max_locks, max_locks2;
19 SilcTimerStruct timer;
20
21 #define rdtsc() silc_timer_tick(&timer, FALSE)
22
23 void *mutex_thread(void *context)
24 {
25   Context *c = context;
26   SilcInt64 s;
27   register int i;
28
29   s = rdtsc();
30   for (i = 0; i < max_locks; i++) {
31     silc_mutex_lock(mutex);
32     silc_mutex_unlock(mutex);
33   }
34   c->time = rdtsc() - s;
35   c->time /= cpu_freq;
36
37   return NULL;
38 }
39
40 SilcUInt64 hval;
41 SilcUInt64 hval2;
42 SilcUInt64 hval3;
43
44 void *mutex_thread_hold(void *context)
45 {
46   Context *c = context;
47   SilcInt64 s;
48   register int i;
49
50   s = rdtsc();
51   for (i = 0; i < max_locks / 4; i++) {
52     silc_mutex_lock(mutex);
53     hval2 = i;
54     hval3 = 0;
55     hval++;
56     hval3 = hval2 + i;
57     hval += hval2;
58     hval3 += hval;
59     if (silc_unlikely(hval3 != hval2 + i + hval)) {
60       fprintf(stderr, "MUTEX CORRUPT 1\n");
61       exit(1);
62     }
63     if (silc_unlikely(hval2 != i)) {
64       fprintf(stderr, "MUTEX CORRUPT 2 (%llu != %d)\n", hval2, i);
65       exit(1);
66     }
67     silc_mutex_unlock(mutex);
68   }
69   c->time = rdtsc() - s;
70   c->time /= cpu_freq;
71
72   return NULL;
73 }
74
75 int main(int argc, char **argv)
76 {
77   Context c[MAX_THREADS * MAX_MUL];
78   SilcInt64 val;
79   int k, i, j, o = 0;
80   SilcBool success;
81
82   silc_timer_synchronize(&timer);
83   val = rdtsc();
84   sleep(1);
85   val = rdtsc() - val;
86   val /= 1000;                  /* Gives us milliseconds */
87   fprintf(stderr, "CPU frequency: %llu\n", val);
88
89   max_locks = MAX_LOCKS;
90
91   fprintf(stderr, "lock/unlock per second\n");
92
93   for (j = 0; j < MAX_ROUND; j++) {
94     for (i = 0; i < 1; i++)
95       c[i].thread = silc_thread_create(mutex_thread, &c[i], TRUE);
96
97     val = 0;
98     for (i = 0; i < 1; i++) {
99       silc_thread_wait(c[i].thread, NULL);
100       val += c[i].time;
101     }
102     fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
103                       (1000LL * max_locks * 1) / val, 1);
104
105     if (o == 0) {
106       /* If MAX_LOCKS is too large for this CPU, optimize.  We don't want to
107          wait a whole day for this test. */
108       if ((SilcInt64)(max_locks / 10) >
109           (SilcInt64)((1000LL * max_locks) / val))
110         max_locks /= 10;
111       o = 1;
112     }
113   }
114   puts("");
115
116   max_locks2 = max_locks;
117   for (k = 0; k < MAX_MUL; k++) {
118     sleep(16);
119     max_locks = max_locks2 / (k + 1);
120     for (j = 0; j < MAX_ROUND; j++) {
121       for (i = 0; i < MAX_THREADS * (k + 1); i++)
122         c[i].thread = silc_thread_create(mutex_thread, &c[i], TRUE);
123
124       val = 0;
125       for (i = 0; i < MAX_THREADS * (k + 1); i++) {
126         silc_thread_wait(c[i].thread, NULL);
127         val += c[i].time;
128       }
129       fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
130                       (1000LL * max_locks * (MAX_THREADS * (k + 1))) / val,
131                       MAX_THREADS * (k + 1));
132     }
133     puts("");
134   }
135   max_locks = max_locks2;
136
137   fprintf(stderr, "Spinning/holding lock, lock/unlock per second\n");
138
139   max_locks /= 2;
140   sleep(5);
141   for (j = 0; j < MAX_ROUND / 2; j++) {
142     for (i = 0; i < 1; i++)
143       c[i].thread = silc_thread_create(mutex_thread_hold, &c[i], TRUE);
144
145     val = 0;
146     for (i = 0; i < 1; i++) {
147       silc_thread_wait(c[i].thread, NULL);
148       val += c[i].time;
149     }
150     fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
151                       (1000LL * (max_locks / 4) * 1) / val, 1);
152   }
153   puts("");
154
155   max_locks2 = max_locks;
156   max_locks2 /= 2;
157   for (k = 0; k < MAX_MUL; k++) {
158     sleep(2);
159     max_locks = max_locks2 / (k + 1);
160     for (j = 0; j < MAX_ROUND / 2; j++) {
161       hval = hval2 = 1;
162       for (i = 0; i < MAX_THREADS * (k + 1); i++)
163         c[i].thread = silc_thread_create(mutex_thread_hold, &c[i], TRUE);
164
165       val = 0;
166       for (i = 0; i < MAX_THREADS * (k + 1); i++) {
167         silc_thread_wait(c[i].thread, NULL);
168         val += c[i].time;
169       }
170       fprintf(stderr, "%llu mutex lock/unlock per second (%d threads)\n",
171                       (1000LL * (max_locks / 4) *
172                        (MAX_THREADS * (k + 1))) / val,
173                       MAX_THREADS * (k + 1));
174     }
175     puts("");
176   }
177
178   success = TRUE;
179
180   fprintf(stderr, "Testing was %s\n", success ? "SUCCESS" : "FAILURE");
181
182   return success;
183 }