pthreads/{array_thrsafe_rwlock → array_thrsafe_perf}/main.c RENAMED
@@ -1,68 +1,171 @@
1
  #include <pthread.h>
2
  #include <stdio.h>
3
  #include <stdlib.h>
 
4
  #include <time.h>
5
 
6
- #include "array.h"
 
7
 
8
- void print_array(const char* name, array_t* array);
9
- void test_arrays(array_t* array1, array_t* array2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  void* test_array(void* data);
11
 
12
- int main()
13
- {
14
- array_t* array1 = array_create(100);
15
- array_t* array2 = array_create(100);
16
 
17
- test_arrays(array1, array2);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
18
 
19
- print_array("array1", array1);
20
- print_array("array2", array2);
21
 
22
- array_destroy(array1);
23
- array_destroy(array2);
 
 
 
24
 
25
- return 0;
 
 
26
  }
27
-
28
- void print_array(const char* name, array_t* array)
29
  {
30
- printf("%s: %zu elements\n", name, array_get_count(array));
31
- fflush(stdout);
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  }
33
 
34
- void test_arrays(array_t* array1, array_t* array2)
35
  {
 
36
  srand( (unsigned)((unsigned)time(NULL) + (unsigned)clock()) );
37
 
38
- size_t thread_count = 10 + rand() % 20;
39
- pthread_t* threads = (pthread_t*) malloc( thread_count * sizeof(pthread_t) );
 
40
 
41
- for ( size_t current = 0; current < thread_count; ++current )
42
- pthread_create( threads + current, NULL, test_array, current % 2 ? array2 : array1 );
 
 
 
 
 
43
 
44
- for ( size_t current = 0; current < thread_count; ++current )
 
45
  pthread_join( threads[current], NULL );
46
 
 
 
47
  free(threads);
 
 
 
 
 
48
  }
49
 
50
  void* test_array(void* data)
51
  {
52
- array_t* array = (array_t*)data;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
53
 
54
- for ( size_t index = 0, count = 1000 + rand() % 10000; index < count; ++index )
 
55
  {
56
- size_t num = rand() % 100;
57
- if ( num >= 10 )
58
- array_append( array, (void*)(num) );
 
 
 
 
 
 
 
 
 
59
  else
60
  {
61
- num += rand() % 90;
62
- if ( array_find_first(array, (void*)num, 0) != array_not_found )
63
- array_remove_first(array, (void*)num, 0);
 
64
  }
65
  }
66
 
67
  return NULL;
68
  }
 
 
 
 
 
 
1
  #include <pthread.h>
2
  #include <stdio.h>
3
  #include <stdlib.h>
4
+ #include <string.h>
5
  #include <time.h>
6
 
7
+ #include "array_mutex.h"
8
+ #include "array_rwlock.h"
9
 
10
+ typedef struct
11
+ {
12
+ size_t initial_element_count;
13
+ size_t operation_count;
14
+ double insertion_percent;
15
+ double deletion_percent;
16
+ double searching_percent;
17
+ size_t worker_count;
18
+ size_t tested_array;
19
+ array_mutex_t* mutex_array;
20
+ array_rwlock_t* rwlock_array;
21
+ } shared_t;
22
+
23
+ typedef struct
24
+ {
25
+ size_t worker_id;
26
+ shared_t* shared;
27
+ } thread_data_t;
28
+
29
+ void print_array(const char* name, array_mutex_t *array);
30
+ int test_arrays(shared_t* shared);
31
  void* test_array(void* data);
32
 
33
+ static const char* const usage_text =
34
+ "usage: array_thrsafe_perf #elements #operations %%insertions %%deletions %%searches #workers array\n";
 
 
35
 
36
+ int main(int argc, char* argv[])
37
+ {
38
+ // All arguments are required
39
+ if ( argc != 8 )
40
+ return (void)printf(usage_text), 1;
41
+
42
+ // Extract the arguments
43
+ shared_t shared;
44
+ shared.initial_element_count = strtoull(argv[1], NULL, 10);
45
+ shared.operation_count = strtoull(argv[2], NULL, 10);
46
+ shared.insertion_percent = strtod(argv[3], NULL);
47
+ shared.deletion_percent = strtod(argv[4], NULL);
48
+ shared.searching_percent = strtod(argv[5], NULL);
49
+ shared.worker_count = strtoull(argv[6], NULL, 10);
50
+
51
+ if ( strcmp(argv[7], "mutex") == 0 )
52
+ shared.tested_array = 1;
53
+ else if ( strcmp(argv[7], "rwlock") == 0 )
54
+ shared.tested_array = 2;
55
+ else
56
+ return (void)fprintf(stderr, "error: unknown array: %s", argv[7]), 2;
57
 
58
+ shared.mutex_array = NULL;
59
+ shared.rwlock_array = NULL;
60
 
61
+ // If we have to thes the mutex array
62
+ if ( shared.tested_array == 1 )
63
+ {
64
+ // Create the mutex array
65
+ shared.mutex_array = array_mutex_create(shared.initial_element_count);
66
 
67
+ // Append the intial elements
68
+ for ( size_t current = 0; current < shared.initial_element_count; ++current )
69
+ array_mutex_append( shared.mutex_array, (void*)(current) );
70
  }
71
+ else
 
72
  {
73
+ shared.rwlock_array = array_rwlock_create(shared.initial_element_count);
74
+ for ( size_t current = 0; current < shared.initial_element_count; ++current )
75
+ array_rwlock_append( shared.rwlock_array, (void*)(current) );
76
+ }
77
+
78
+ // Create and test the performance of the thread-safe arrays
79
+ int result = test_arrays(&shared);
80
+
81
+ // Destroy the arrays
82
+ if ( shared.tested_array == 1 )
83
+ array_mutex_destroy(shared.mutex_array);
84
+ else
85
+ array_rwlock_destroy(shared.rwlock_array);
86
+
87
+ return result;
88
  }
89
 
90
+ int test_arrays(shared_t* shared)
91
  {
92
+ // Init pseudo-random number generator
93
  srand( (unsigned)((unsigned)time(NULL) + (unsigned)clock()) );
94
 
95
+ // Create threads and their data
96
+ pthread_t* threads = (pthread_t*) malloc( shared->worker_count * sizeof(pthread_t) );
97
+ thread_data_t* thread_data = (thread_data_t*) malloc( shared->worker_count * sizeof(thread_data_t) );
98
 
99
+ // Start the asked number of threads
100
+ for ( size_t current = 0; current < shared->worker_count; ++current )
101
+ {
102
+ thread_data[current].worker_id = current;
103
+ thread_data[current].shared = shared;
104
+ pthread_create( threads + current, NULL, test_array, thread_data + current );
105
+ }
106
 
107
+ // Wait for all threads to finish
108
+ for ( size_t current = 0; current < shared->worker_count; ++current )
109
  pthread_join( threads[current], NULL );
110
 
111
+ // Release threads and their data
112
+ free(thread_data);
113
  free(threads);
114
+
115
+ // print_array("array1", shared->mutex_array);
116
+ // print_array("array2", shared->rwlock_array);
117
+
118
+ return 0;
119
  }
120
 
121
  void* test_array(void* data)
122
  {
123
+ // Unpack the data
124
+ thread_data_t* thread_data = (thread_data_t*)data;
125
+ shared_t* shared = thread_data->shared;
126
+
127
+ // Slice the operations among the threads
128
+ size_t my_operations = shared->operation_count / shared->worker_count
129
+ + (thread_data->worker_id < shared->operation_count % shared->worker_count);
130
+
131
+ // Execute the asked number of operations
132
+ for ( size_t operation = 0; operation < my_operations; ++operation )
133
+ {
134
+ // Get a random number to insert, find, or delete from array
135
+ size_t element = rand() % 100;
136
+
137
+ // Get a random percent to choose the operation to execute
138
+ size_t random_op = (size_t)rand() % shared->operation_count;
139
 
140
+ // Execute the operation according to the percents
141
+ if ( random_op < shared->insertion_percent * shared->operation_count )
142
  {
143
+ // Insert an element into the tested array
144
+ shared->tested_array == 1
145
+ ? array_mutex_append( shared->mutex_array, (void*)(element) )
146
+ : array_rwlock_append( shared->rwlock_array, (void*)(element) );
147
+ }
148
+ else if ( random_op < shared->deletion_percent * shared->operation_count )
149
+ {
150
+ // Remove an element in the tested array
151
+ shared->tested_array == 1
152
+ ? array_mutex_remove_first(shared->mutex_array, (void*)(element), 0)
153
+ : array_rwlock_remove_first(shared->rwlock_array, (void*)(element), 0);
154
+ }
155
  else
156
  {
157
+ // Search an element in the tested array
158
+ shared->tested_array == 1
159
+ ? array_mutex_find_first(shared->mutex_array, (void*)(element), 0)
160
+ : array_rwlock_find_first(shared->rwlock_array, (void*)(element), 0);
161
  }
162
  }
163
 
164
  return NULL;
165
  }
166
+
167
+ void print_array(const char* name, array_mutex_t* array)
168
+ {
169
+ printf("%s: %zu elements\n", name, array_mutex_get_count(array));
170
+ fflush(stdout);
171
+ }