libsmatrix 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,96 @@
1
+ // This file is part of the "libsmatrix" project
2
+ // (c) 2011-2013 Paul Asmuth <paul@paulasmuth.com>
3
+ //
4
+ // Licensed under the MIT License (the "License"); you may not use this
5
+ // file except in compliance with the License. You may obtain a copy of
6
+ // the License at: http://opensource.org/licenses/MIT
7
+
8
+ #include <stdint.h>
9
+ #include <pthread.h>
10
+ #include <stdio.h>
11
+
12
+ #ifndef SMATRIX_H
13
+ #define SMATRIX_H
14
+
15
+ #define SMATRIX_META_SIZE 512
16
+ #define SMATRIX_RMAP_FLAG_LOADED 4
17
+ #define SMATRIX_RMAP_FLAG_DIRTY 8
18
+ #define SMATRIX_RMAP_FLAG_RESIZED 16
19
+ #define SMATRIX_RMAP_MAGIC "\x23\x23\x23\x23\x23\x23\x23\x23"
20
+ #define SMATRIX_RMAP_MAGIC_SIZE 8
21
+ #define SMATRIX_RMAP_INITIAL_SIZE 16
22
+ #define SMATRIX_RMAP_SLOT_SIZE 8
23
+ #define SMATRIX_RMAP_HEAD_SIZE 16
24
+ #define SMATRIX_CMAP_INITIAL_SIZE 65536
25
+ #define SMATRIX_CMAP_SLOT_SIZE 12
26
+ #define SMATRIX_CMAP_HEAD_SIZE 16
27
+ #define SMATRIX_CMAP_BLOCK_SIZE 4194304
28
+ #define SMATRIX_CMAP_SLOT_USED 1
29
+
30
+ typedef struct {
31
+ volatile uint16_t count;
32
+ volatile uint16_t mutex;
33
+ } smatrix_lock_t;
34
+
35
+ typedef struct {
36
+ uint32_t key;
37
+ uint32_t value;
38
+ } smatrix_rmap_slot_t;
39
+
40
+ typedef struct {
41
+ uint64_t fpos;
42
+ uint64_t meta_fpos;
43
+ uint32_t size;
44
+ uint32_t used;
45
+ uint32_t key;
46
+ uint32_t flags;
47
+ smatrix_rmap_slot_t* data;
48
+ smatrix_lock_t lock;
49
+ } smatrix_rmap_t;
50
+
51
+ typedef struct {
52
+ uint32_t flags;
53
+ uint32_t key;
54
+ smatrix_rmap_t* rmap;
55
+ } smatrix_cmap_slot_t;
56
+
57
+ typedef struct {
58
+ uint64_t size;
59
+ uint64_t used;
60
+ uint64_t block_fpos;
61
+ uint64_t block_used;
62
+ uint64_t block_size;
63
+ smatrix_cmap_slot_t* data;
64
+ smatrix_lock_t lock;
65
+ } smatrix_cmap_t;
66
+
67
+ typedef struct smatrix_ref_s smatrix_ref_t;
68
+
69
+ struct smatrix_ref_s {
70
+ int write;
71
+ smatrix_rmap_t* rmap;
72
+ smatrix_rmap_slot_t* slot;
73
+ smatrix_ref_t* next;
74
+ };
75
+
76
+ typedef struct {
77
+ int fd;
78
+ int shutdown;
79
+ uint64_t fpos;
80
+ uint64_t mem;
81
+ smatrix_ref_t* ioqueue;
82
+ pthread_t iothread;
83
+ smatrix_cmap_t cmap;
84
+ smatrix_lock_t lock;
85
+ } smatrix_t;
86
+
87
+ smatrix_t* smatrix_open(const char* fname);
88
+ uint32_t smatrix_get(smatrix_t* self, uint32_t x, uint32_t y);
89
+ uint32_t smatrix_set(smatrix_t* self, uint32_t x, uint32_t y, uint32_t value);
90
+ uint32_t smatrix_incr(smatrix_t* self, uint32_t x, uint32_t y, uint32_t value);
91
+ uint32_t smatrix_decr(smatrix_t* self, uint32_t x, uint32_t y, uint32_t value);
92
+ uint32_t smatrix_rowlen(smatrix_t* self, uint32_t x);
93
+ uint32_t smatrix_getrow(smatrix_t* self, uint32_t x, uint32_t* ret, size_t ret_len);
94
+ void smatrix_close(smatrix_t* self);
95
+
96
+ #endif
@@ -0,0 +1,236 @@
1
+ // This file is part of the "libsmatrix" project
2
+ // (c) 2011-2013 Paul Asmuth <paul@paulasmuth.com>
3
+ //
4
+ // Licensed under the MIT License (the "License"); you may not use this
5
+ // file except in compliance with the License. You may obtain a copy of
6
+ // the License at: http://opensource.org/licenses/MIT
7
+
8
+ #include <stdio.h>
9
+ #include <stdlib.h>
10
+ #include <string.h>
11
+ #include <sys/types.h>
12
+ #include <sys/stat.h>
13
+ #include <sys/time.h>
14
+ #include <fcntl.h>
15
+ #include <unistd.h>
16
+ #include <assert.h>
17
+ #include <pthread.h>
18
+
19
+ #include "smatrix.h"
20
+
21
+ typedef struct {
22
+ smatrix_t* smx;
23
+ int threadn;
24
+ int user1;
25
+ } args_t;
26
+
27
+ smatrix_t* smx_mem;
28
+
29
+ void* benchmark_incr_mixed(void* args_) {
30
+ args_t* args = (args_t*) args_;
31
+ int i, n, r, o;
32
+
33
+ o = 42 + args->threadn;
34
+ smatrix_t* smx = args->smx;
35
+
36
+ for (r = 0; r < args->user1; r++) {
37
+ for (n = 0; n < 23; n++) {
38
+ for (i = 0; i < 22; i++) {
39
+ smatrix_incr(smx, n + o, i + o, 1);
40
+ smatrix_incr(smx, i + o, n + o, 1);
41
+ }
42
+ }
43
+ }
44
+
45
+ return NULL;
46
+ }
47
+
48
+ void* benchmark_get_mixed(void* args_) {
49
+ args_t* args = (args_t*) args_;
50
+ int i, n, r, o;
51
+
52
+ o = 42 + args->threadn;
53
+ smatrix_t* smx = args->smx;
54
+
55
+ for (r = 0; r < args->user1; r++) {
56
+ for (n = 0; n < 23; n++) {
57
+ for (i = 0; i < 22; i++) {
58
+ smatrix_get(smx, n + o, i + o);
59
+ smatrix_get(smx, i + o, n + o);
60
+ }
61
+ }
62
+ }
63
+
64
+ return NULL;
65
+ }
66
+
67
+ void* benchmark_incr_independent(void* args_) {
68
+ args_t* args = (args_t*) args_;
69
+ int i, r, o;
70
+
71
+ smatrix_t* smx = args->smx;
72
+ o = 123 + args->threadn;
73
+
74
+ for (r = 0; r < args->user1; r++) {
75
+ for (i = 0; i < 1000; i++) {
76
+ smatrix_incr(smx, o, 1, 1);
77
+ }
78
+ }
79
+
80
+ return NULL;
81
+ }
82
+
83
+ void* benchmark_incr_compete(void* args_) {
84
+ args_t* args = (args_t*) args_;
85
+ int i, r;
86
+
87
+ smatrix_t* smx = args->smx;
88
+
89
+ for (r = 0; r < args->user1; r++) {
90
+ for (i = 0; i < 1000; i++) {
91
+ smatrix_incr(smx, 23, 1, 1);
92
+ }
93
+ }
94
+
95
+ return NULL;
96
+ }
97
+
98
+ void measure(void* (*cb)(void*), int nthreads, smatrix_t* smx, int user1) {
99
+ char str[20] = " ";
100
+ int n;
101
+ pthread_t* threads;
102
+ double elapsed;
103
+ struct timeval t0, t1;
104
+ void* retval;
105
+
106
+ args_t* args = malloc(sizeof(args_t) * nthreads);
107
+ threads = malloc(sizeof(pthread_t) * nthreads);
108
+
109
+ gettimeofday(&t0, NULL);
110
+
111
+ for (n = 0; n < nthreads; n++) {
112
+ args[n].smx = smx;
113
+ args[n].threadn = n;
114
+ args[n].user1 = user1;
115
+ pthread_create(threads + n, NULL, cb, &args[n]);
116
+ }
117
+
118
+ for (n = 0; n < nthreads; n++) {
119
+ pthread_join(threads[n], &retval);
120
+ }
121
+
122
+ gettimeofday(&t1, NULL);
123
+
124
+ elapsed = (double) (t1.tv_sec - t0.tv_sec) * 1000;
125
+ elapsed += (double) (t1.tv_usec - t0.tv_usec) / 1000;
126
+
127
+ str[snprintf(str, 20, "%.1fms", elapsed)] = ' ';
128
+
129
+ free(threads);
130
+ free(args);
131
+ printf("%s", str);
132
+ }
133
+
134
+ void print_header(const char* title) {
135
+ printf("TEST: %s\n", title);
136
+ printf("---------------------------------------------------------------\n");
137
+ printf("T=1 T=2 T=4 T=8 T=16 T=32 \n");
138
+ }
139
+
140
+ void test_incr(smatrix_t* smx_mem) {
141
+ int n, max = 10;
142
+
143
+ for (n = 0; n < max; n++) {
144
+ measure(&benchmark_incr_mixed, 1, smx_mem, 1024);
145
+ measure(&benchmark_incr_mixed, 2, smx_mem, 512);
146
+ measure(&benchmark_incr_mixed, 4, smx_mem, 256);
147
+ measure(&benchmark_incr_mixed, 8, smx_mem, 128);
148
+ measure(&benchmark_incr_mixed, 16, smx_mem, 64);
149
+ measure(&benchmark_incr_mixed, 32, smx_mem, 32);
150
+
151
+ if (n < max - 1) {
152
+ printf("\n");
153
+ }
154
+ }
155
+
156
+ printf("\n\n");
157
+ }
158
+
159
+ void test_get(smatrix_t* smx_mem) {
160
+ int n, max = 10;
161
+
162
+ for (n = 0; n < max; n++) {
163
+ measure(&benchmark_get_mixed, 1, smx_mem, 1024);
164
+ measure(&benchmark_get_mixed, 2, smx_mem, 512);
165
+ measure(&benchmark_get_mixed, 4, smx_mem, 256);
166
+ measure(&benchmark_get_mixed, 8, smx_mem, 128);
167
+ measure(&benchmark_get_mixed, 16, smx_mem, 64);
168
+ measure(&benchmark_get_mixed, 32, smx_mem, 32);
169
+
170
+ if (n < max - 1) {
171
+ printf("\n");
172
+ }
173
+ }
174
+
175
+ printf("\n\n");
176
+ }
177
+
178
+ int main(int argc, char** argv) {
179
+ int num = 1024, threads = 4;
180
+ smatrix_t* smx = NULL;
181
+
182
+ if (argc < 2) {
183
+ printf("usage: smatrix_benchmark [test] [times] [threads] [file]\n\n");
184
+ printf(" Available Tests:\n");
185
+ printf(" full test all methods\n");
186
+ printf(" incr test the incr method\n");
187
+ printf(" get test the get method\n\n");
188
+ printf(" Examples:\n");
189
+ printf(" $ smatrix_benchmark incr 1024 4\n");
190
+ printf(" $ smatrix_benchmark incr 1024 4 /tmp/test.smx\n");
191
+ printf(" $ smatrix_benchmark get 10000 2 /tmp/text.smx\n");
192
+ printf(" $ smatrix_benchmark full\n\n");
193
+ return 1;
194
+ }
195
+
196
+ if (argc > 2) {
197
+ num = atoi(argv[2]);
198
+ }
199
+
200
+ if (argc > 3) {
201
+ threads = atoi(argv[3]);
202
+ }
203
+
204
+ if (argc > 4) {
205
+ smx = smatrix_open(argv[4]);
206
+ } else {
207
+ smx = smatrix_open(NULL);
208
+ }
209
+
210
+ if (!strcmp(argv[1], "incr")) {
211
+ printf("testing: %ik x incr @ %i threads: ", num, threads);
212
+ measure(&benchmark_incr_mixed, threads, smx, num / threads);
213
+ printf("\n");
214
+ goto exit;
215
+ }
216
+
217
+ if (!strcmp(argv[1], "get")) {
218
+ printf("testing: %ik x get @ %i threads: ", num, threads);
219
+ measure(&benchmark_get_mixed, threads, smx, num / threads);
220
+ printf("\n");
221
+ goto exit;
222
+ }
223
+
224
+ printf("libsmatrix benchmark [date]\n\n");
225
+
226
+ print_header("1 million x incr (memory)");
227
+ test_incr(smx);
228
+
229
+ print_header("1 million x get (memory)");
230
+ test_get(smx);
231
+
232
+ exit:
233
+ smatrix_close(smx);
234
+
235
+ return 0;
236
+ }
@@ -0,0 +1,161 @@
1
+ /**
2
+ * This file is part of the "libsmatrix" project
3
+ * (c) 2011-2013 Paul Asmuth <paul@paulasmuth.com>
4
+ *
5
+ * Licensed under the MIT License (the "License"); you may not use this
6
+ * file except in compliance with the License. You may obtain a copy of
7
+ * the License at: http://opensource.org/licenses/MIT
8
+ */
9
+ #include <stdlib.h>
10
+ #include "smatrix_jni.h"
11
+ #include "smatrix.h"
12
+
13
+ #define _JM(X) Java_com_paulasmuth_libsmatrix_SparseMatrix_##X
14
+ #define ERR_PTRNOTFOUND "can't find native object. maybe close() was already called"
15
+
16
+ void throw_exception(JNIEnv* env, const char* error) {
17
+ jclass exception = (*env)->FindClass(env, "java/lang/IllegalArgumentException");
18
+ (*env)->ThrowNew(env, exception, error);
19
+ }
20
+
21
+ void set_ptr(JNIEnv* env, jobject self, void* ptr_) {
22
+ jclass cls;
23
+ jfieldID fid;
24
+ long ptr = (long) ptr_;
25
+
26
+ cls = (*env)->FindClass(env, "com/paulasmuth/libsmatrix/SparseMatrix");
27
+ fid = (*env)->GetFieldID(env, cls, "ptr", "J");
28
+
29
+ (*env)->SetLongField(env, self, fid, ptr);
30
+ }
31
+
32
+ int get_ptr(JNIEnv* env, jobject self, void** ptr) {
33
+ jclass cls;
34
+ jfieldID fid;
35
+ jlong ptr_;
36
+
37
+ cls = (*env)->FindClass(env, "com/paulasmuth/libsmatrix/SparseMatrix");
38
+ fid = (*env)->GetFieldID(env, cls, "ptr", "J");
39
+ ptr_ = (*env)->GetLongField(env, self, fid);
40
+
41
+ if (ptr_ > 0) {
42
+ *ptr = (void *) ptr_;
43
+ return 0;
44
+ } else {
45
+ throw_exception(env, ERR_PTRNOTFOUND);
46
+
47
+ return 1;
48
+ }
49
+ }
50
+
51
+ JNIEXPORT void JNICALL _JM(init) (JNIEnv* env, jobject self, jstring file_) {
52
+ void* ptr;
53
+ char* file = NULL;
54
+
55
+ if (file_ != NULL) {
56
+ file = (char *) (*env)->GetStringUTFChars(env, file_, 0);
57
+ }
58
+
59
+ ptr = smatrix_open(file);
60
+
61
+ if (ptr == NULL) {
62
+ throw_exception(env, "smatrix_open() failed");
63
+ } else {
64
+ set_ptr(env, self, ptr);
65
+ }
66
+
67
+ if (file != NULL) {
68
+ (*env)->ReleaseStringUTFChars(env, file_, file);
69
+ }
70
+ }
71
+
72
+ JNIEXPORT void JNICALL _JM(close) (JNIEnv* env, jobject self) {
73
+ void* ptr = NULL;
74
+
75
+ if (!get_ptr(env, self, &ptr)) {
76
+ smatrix_close(ptr);
77
+ set_ptr(env, self, NULL);
78
+ }
79
+ }
80
+
81
+ JNIEXPORT jint _JM(get) (JNIEnv* env, jobject self, jint x, jint y) {
82
+ void* ptr = NULL;
83
+
84
+ if (get_ptr(env, self, &ptr)) {
85
+ return 0;
86
+ } else {
87
+ return (jint) smatrix_get(ptr, x, y);
88
+ }
89
+ }
90
+
91
+ JNIEXPORT void JNICALL _JM(set) (JNIEnv* env, jobject self, jint x, jint y, jint v) {
92
+ void* ptr = NULL;
93
+
94
+ if (!get_ptr(env, self, &ptr)) {
95
+ smatrix_set(ptr, (uint32_t) x, (uint32_t) y, (uint32_t) v);
96
+ }
97
+ }
98
+
99
+ JNIEXPORT void JNICALL _JM(incr) (JNIEnv* env, jobject self, jint x, jint y, jint v) {
100
+ void* ptr = NULL;
101
+
102
+ if (!get_ptr(env, self, &ptr)) {
103
+ smatrix_incr(ptr, (uint32_t) x, (uint32_t) y, (uint32_t) v);
104
+ }
105
+ }
106
+
107
+ JNIEXPORT void JNICALL _JM(decr) (JNIEnv* env, jobject self, jint x, jint y, jint v) {
108
+ void* ptr = NULL;
109
+
110
+ if (!get_ptr(env, self, &ptr)) {
111
+ smatrix_decr(ptr, (uint32_t) x, (uint32_t) y, (uint32_t) v);
112
+ }
113
+ }
114
+
115
+ JNIEXPORT void JNICALL _JM(getRowNative) (JNIEnv* env, jobject self, jint x, jobject map, jint maxlen) {
116
+ jclass cls;
117
+ jint i, len;
118
+ jmethodID mid;
119
+ uint32_t *data;
120
+ void* ptr = NULL;
121
+ size_t bytes;
122
+
123
+ cls = (*env)->GetObjectClass(env, map);
124
+ mid = (*env)->GetMethodID(env, cls, "putIntTuple", "(II)V");
125
+
126
+ if (mid == NULL || get_ptr(env, self, &ptr)) {
127
+ return;
128
+ }
129
+
130
+ len = smatrix_rowlen(ptr, x);
131
+ bytes = len * 8;
132
+ data = malloc(bytes);
133
+
134
+ if (data == NULL) {
135
+ throw_exception(env, "malloc() failed");
136
+ return;
137
+ }
138
+
139
+ len = smatrix_getrow(ptr, (uint32_t) x, data, bytes);
140
+
141
+ for (i = 0; i < len; i++) {
142
+ if (maxlen > 0 && i >= maxlen) {
143
+ break;
144
+ }
145
+
146
+ (*env)->CallVoidMethod(env, map, mid, data[i * 2], data[i * 2 + 1]);
147
+ }
148
+
149
+ free(data);
150
+ }
151
+
152
+ JNIEXPORT jint JNICALL _JM(getRowLength) (JNIEnv* env, jobject self, jint x) {
153
+ void* ptr = NULL;
154
+
155
+ if (get_ptr(env, self, &ptr)) {
156
+ return 0;
157
+ } else {
158
+ return (jint) smatrix_rowlen(ptr, x);
159
+ }
160
+ }
161
+