libsmatrix 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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
+