fast_method_source 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d4abbc77bfa1ddd3f7d8c335e4ed45de99d1d6f
4
- data.tar.gz: 412abc3f1f3278f2a25041e3dcfc689e4c00b83d
3
+ metadata.gz: a652f4b019d35eaf42c337bed8e5a556cefaf8bc
4
+ data.tar.gz: c6dd63e38ed0542570e7bc395a1f798341021c6d
5
5
  SHA512:
6
- metadata.gz: 15c8a178256a9f168e2a2bf49a0f7a2dcba1a968664c1887d642de15685bf446d0b020eceb8fc322a1bb9e3172c158c2b28c3dc294ac8e46cc8c2406e7e479e6
7
- data.tar.gz: 2930a5f50f0cf4d7b8745d0b44ca377a312cd06bdde2944ba38686fe782c7ec1fb0d232be6dd535e547aa4214a9f8528734882ed9d9820becf4a255e2c66c20d
6
+ metadata.gz: 4194e5d174e2d5c4ff5699b20bda1ee9676edc224a05b6bd255e3f73dc723329a08468e6e5839283e1136271b1f2c7d68a83cda5979d5aaa0be714dec0e6ec45
7
+ data.tar.gz: 67b9991bff995852cba78548c5fd8aca9886f353f3ce90fdc34e78387ef25c7564102335a36f4d3263bf00eaca9865ceca0dd8f62a483fdd6df58a0dcaad2bad
data/CHANGELOG.md CHANGED
@@ -1,6 +1,12 @@
1
1
  Fast Method Source changelog
2
2
  ============================
3
3
 
4
+ ### v0.3.0 (June 11, 2015)
5
+
6
+ * _Significantly_ reduced memory consumption (`#comment_and_source` for 19K
7
+ methods uses about 100-150 MB of RES RAM)
8
+ * _Significantly_ decreased time of calculations
9
+
4
10
  ### v0.2.0 (June 11, 2015)
5
11
 
6
12
  * Significantly reduced memory consumption
data/README.md CHANGED
@@ -65,7 +65,7 @@ Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
65
65
  Counting the number of sample methods...
66
66
  Sample methods: 19438
67
67
  user system total real
68
- FastMethodSource#comment_and_source_for 26.050000 1.420000 27.470000 ( 30.528066)
68
+ FastMethodSource#comment_and_source_for 16.240000 1.180000 17.420000 ( 19.439981)
69
69
  ```
70
70
 
71
71
  #### #source
@@ -75,33 +75,32 @@ FastMethodSource#comment_and_source_for 26.050000 1.420000 27.470000 ( 30.528
75
75
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
76
76
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
77
77
  Counting the number of sample methods...
78
- Sample methods: 19596
79
- Rehearsal ------------------------------------------------------------
80
- FastMethodSource#comment 4.730000 0.300000 5.030000 ( 5.590186)
81
- MethodSource#comment 73.660000 0.340000 74.000000 ( 89.475399)
82
- -------------------------------------------------- total: 79.030000sec
78
+ Sample methods: 19438
79
+ Rehearsal -----------------------------------------------------------
80
+ FastMethodSource#source 14.220000 0.880000 15.100000 ( 16.844189)
81
+ MethodSource#source 104.140000 0.420000 104.560000 (126.567209)
82
+ ------------------------------------------------ total: 119.660000sec
83
83
 
84
- user system total real
85
- FastMethodSource#comment 4.450000 0.300000 4.750000 ( 5.278761)
86
- MethodSource#comment 69.880000 0.110000 69.990000 ( 77.663383)
84
+ user system total real
85
+ FastMethodSource#source 14.920000 0.890000 15.810000 ( 17.658905)
86
+ MethodSource#source 96.860000 0.410000 97.270000 (108.131119)
87
87
  ```
88
88
 
89
89
  #### #comment
90
90
  ##### ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
91
91
 
92
92
  ```
93
- Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
94
93
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
95
94
  Counting the number of sample methods...
96
- Sample methods: 19438
97
- Rehearsal -----------------------------------------------------------
98
- FastMethodSource#source 20.610000 1.290000 21.900000 ( 24.341358)
99
- MethodSource#source 92.730000 0.470000 93.200000 (111.384362)
100
- ------------------------------------------------ total: 115.100000sec
95
+ Sample methods: 19596
96
+ Rehearsal ------------------------------------------------------------
97
+ FastMethodSource#comment 1.790000 0.210000 2.000000 ( 2.229802)
98
+ MethodSource#comment 85.020000 0.370000 85.390000 (103.061652)
99
+ -------------------------------------------------- total: 87.390000sec
101
100
 
102
- user system total real
103
- FastMethodSource#source 20.990000 1.150000 22.140000 ( 24.612721)
104
- MethodSource#source 86.390000 0.290000 86.680000 ( 96.241494)
101
+ user system total real
102
+ FastMethodSource#comment 1.620000 0.250000 1.870000 ( 2.072023)
103
+ MethodSource#comment 84.560000 0.320000 84.880000 ( 94.465574)
105
104
  ```
106
105
 
107
106
  ### Correctness of output
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
@@ -19,145 +19,180 @@ static const char *null_filename = "/dev/null";
19
19
  #define DUP2(fd, newfd) dup2(fd, newfd)
20
20
  #endif
21
21
 
22
- #define MAXLINES 600
23
- #define MAXLINELEN 90
24
- #define COMMENT_SIZE 1000
22
+ #define EXPRESSION_SIZE 80 * 50
23
+
25
24
  #define SAFE_CHAR 'z'
26
25
 
27
26
  typedef struct {
28
- int forward : 1;
29
- int backward : 1;
30
- } read_order;
27
+ int source : 1;
28
+ int comment : 1;
29
+ } finder;
31
30
 
32
- struct filebuf {
31
+ struct method_data {
33
32
  unsigned method_location;
34
33
  const char *filename;
35
34
  VALUE method_name;
36
- char **lines;
37
- unsigned relevant_lines;
38
35
  };
39
36
 
40
- struct retval {
41
- VALUE val;
42
- VALUE method_name;
43
- };
44
-
45
- static void read_lines(read_order order, struct filebuf *filebuf);
46
- static void read_lines_before(struct filebuf *filebuf);
47
- static void read_lines_after(struct filebuf *filebuf);
48
- static void reallocate_filebuf(char **lines[], unsigned rl_len);
49
- static void reallocate_linebuf(char **linebuf, const unsigned cl_len);
50
- static VALUE find_source(struct filebuf *filebuf);
51
- static VALUE find_comment(struct filebuf *filebuf);
52
- static VALUE mMethodExtensions_source(VALUE self);
37
+ static VALUE read_lines(finder finder, struct method_data *data);
38
+ static VALUE read_lines_before(struct method_data *data);
39
+ static VALUE read_lines_after(struct method_data *data);
40
+ static VALUE find_method_comment(struct method_data *data);
41
+ static VALUE find_method_source(struct method_data *data);
53
42
  static NODE *parse_expr(VALUE rb_str);
54
43
  static NODE *parse_with_silenced_stderr(VALUE rb_str);
55
44
  static void filter_interp(char *line);
56
- static char **allocate_memory_for_file(void);
57
- static void free_memory_for_file(char **file[], const unsigned relevant_lines_n);
58
45
  static int contains_end_kw(const char *line);
59
46
  static int is_comment(const char *line, const size_t line_len);
60
47
  static int is_static_definition(const char *line);
61
48
  static int is_accessor(const char *line);
62
49
  static int is_dangling_literal_end(const char *line);
63
50
  static int is_dangling_literal_begin(const char *line);
64
- static void strnprep(char *s, const char *t, size_t len);
65
51
  static void raise_if_nil(VALUE val, VALUE method_name);
66
- static VALUE raise_if_nil_safe(VALUE args);
67
- static void realloc_comment(char **comment, unsigned len);
68
- static void filebuf_init(VALUE self, struct filebuf *filebuf);
69
- static void free_filebuf(VALUE retval, struct filebuf *filebuf);
52
+ static void realloc_expression(char **expression, size_t len);
53
+ static void method_data_init(VALUE self, struct method_data *data);
54
+ static VALUE mMethodExtensions_source(VALUE self);
70
55
 
71
56
  static VALUE rb_eSourceNotFoundError;
72
57
 
73
- static void
74
- read_lines_after(struct filebuf *filebuf)
58
+ static VALUE
59
+ find_method_source(struct method_data *data)
75
60
  {
76
- read_order order = {1, 0};
77
- read_lines(order, filebuf);
61
+ return read_lines_after(data);
78
62
  }
79
63
 
80
- static void
81
- read_lines_before(struct filebuf *filebuf)
64
+ static VALUE
65
+ find_method_comment(struct method_data *data)
82
66
  {
83
- read_order order = {0, 1};
84
- read_lines(order, filebuf);
67
+ return read_lines_before(data);
85
68
  }
86
69
 
87
- static void
88
- read_lines(read_order order, struct filebuf *filebuf)
70
+ static VALUE
71
+ read_lines_after(struct method_data *data)
72
+ {
73
+ finder finder = {1, 0};
74
+ return read_lines(finder, data);
75
+ }
76
+
77
+ static VALUE
78
+ read_lines_before(struct method_data *data)
79
+ {
80
+ finder finder = {0, 1};
81
+ return read_lines(finder, data);
82
+ }
83
+
84
+ static VALUE
85
+ read_lines(finder finder, struct method_data *data)
89
86
  {
90
87
  FILE *fp;
91
88
 
92
- if ((fp = fopen(filebuf->filename, "r")) == NULL) {
93
- rb_raise(rb_eIOError, "No such file or directory - %s", filebuf->filename);
89
+ if ((fp = fopen(data->filename, "r")) == NULL) {
90
+ rb_raise(rb_eIOError, "No such file or directory - %s", data->filename);
94
91
  }
95
92
 
96
93
  ssize_t cl_len;
94
+ VALUE rb_expr;
95
+
96
+ size_t bufsize, parse_bufsize, future_bufsize, future_parse_bufsize,
97
+ current_linebuf_size, line_count;
98
+
99
+ bufsize = parse_bufsize = EXPRESSION_SIZE;
100
+ line_count = current_linebuf_size = 0;
101
+
102
+ int should_parse, dangling_literal, found_expression;
103
+ should_parse = dangling_literal = found_expression = 0;
104
+
105
+ char *expression = ALLOC_N(char, bufsize);
106
+ expression[0] = '\0';
107
+
108
+ char *parse_expression = ALLOC_N(char, bufsize);
109
+ parse_expression[0] = '\0';
97
110
 
98
111
  char *current_line = NULL;
99
- char **current_linebuf = NULL;
100
- size_t current_linebuf_size = 0;
101
- unsigned rl_n = 0;
102
- unsigned line_count = 0;
103
112
 
104
113
  while ((cl_len = getline(&current_line, &current_linebuf_size, fp)) != -1) {
105
114
  line_count++;
106
- if (order.forward) {
107
- if (line_count < filebuf->method_location) {
108
- continue;
115
+
116
+ if (finder.source && line_count >= data->method_location) {
117
+ future_bufsize = strlen(expression) + cl_len;
118
+ if (future_bufsize >= bufsize) {
119
+ bufsize = future_bufsize + EXPRESSION_SIZE + 1;
120
+ realloc_expression(&expression, bufsize);
109
121
  }
110
- } else if (order.backward) {
111
- if (line_count > filebuf->method_location) {
112
- break;
122
+ strncat(expression, current_line, cl_len);
123
+
124
+ if (current_line[0] == '\n')
125
+ continue;
126
+
127
+ if (line_count == data->method_location) {
128
+ if (is_static_definition(current_line) || is_accessor(current_line)) {
129
+ should_parse = 1;
130
+ }
113
131
  }
114
- }
115
132
 
116
- if ((rl_n != 0) && (rl_n % (MAXLINES-1) == 0)) {
117
- reallocate_filebuf(&filebuf->lines, rl_n);
118
- }
133
+ if (is_comment(current_line, cl_len))
134
+ continue;
119
135
 
120
- current_linebuf = &(filebuf->lines)[rl_n];
136
+ if (is_dangling_literal_end(current_line)) {
137
+ dangling_literal = 0;
138
+ } else if (is_dangling_literal_begin(current_line)) {
139
+ dangling_literal = 1;
140
+ } else if (dangling_literal) {
141
+ continue;
142
+ }
121
143
 
122
- if (cl_len >= MAXLINELEN) {
123
- reallocate_linebuf(current_linebuf, cl_len);
144
+ filter_interp(current_line);
145
+ future_parse_bufsize = strlen(parse_expression) + cl_len;
146
+ if (future_parse_bufsize >= parse_bufsize) {
147
+ parse_bufsize = future_parse_bufsize + EXPRESSION_SIZE + 1;
148
+ realloc_expression(&parse_expression, parse_bufsize);
149
+ }
150
+ strncat(parse_expression, current_line, cl_len);
151
+
152
+ if (should_parse || contains_end_kw(current_line)) {
153
+ if (parse_expr(rb_str_new2(parse_expression)) != NULL) {
154
+ found_expression = 1;
155
+ break;
156
+ }
157
+ }
158
+ } else if (finder.comment) {
159
+ if (line_count < data->method_location) {
160
+ if (is_comment(current_line, cl_len)) {
161
+ future_bufsize = strlen(expression) + cl_len;
162
+ if (future_bufsize >= bufsize) {
163
+ bufsize = future_bufsize + EXPRESSION_SIZE + 1;
164
+ realloc_expression(&expression, bufsize);
165
+ }
166
+ strncat(expression, current_line, cl_len);
167
+ } else {
168
+ expression[0] = '\0';
169
+ bufsize = EXPRESSION_SIZE;
170
+ }
171
+ } else if (line_count == data->method_location) {
172
+ found_expression = 1;
173
+ break;
174
+ }
124
175
  }
176
+ }
125
177
 
126
- strncpy(*current_linebuf, current_line, cl_len);
127
- (*current_linebuf)[cl_len] = '\0';
128
- rl_n++;
178
+ if (found_expression) {
179
+ rb_expr = rb_str_new2(expression);
180
+ } else {
181
+ rb_expr = Qnil;
129
182
  }
130
183
 
184
+ xfree(parse_expression);
185
+ xfree(expression);
131
186
  free(current_line);
132
187
  fclose(fp);
133
- filebuf->relevant_lines = rl_n;
134
- }
135
-
136
- static void
137
- reallocate_linebuf(char **linebuf, const unsigned cl_len)
138
- {
139
- char *tmp_line = REALLOC_N(*linebuf, char, cl_len + 1);
140
- *linebuf = tmp_line;
141
- }
142
-
143
- static void
144
- reallocate_filebuf(char **lines[], unsigned rl_len)
145
- {
146
- unsigned new_size = rl_len + MAXLINES + 1;
147
- char **temp_lines = REALLOC_N(*lines, char *, new_size);
148
-
149
- *lines = temp_lines;
150
-
151
- for (int i = 0; i < MAXLINES; i++) {
152
- (*lines)[rl_len + i] = ALLOC_N(char, MAXLINELEN);
153
- }
188
+ return (rb_expr);
154
189
  }
155
190
 
156
191
  static void
157
- realloc_comment(char **comment, unsigned len)
192
+ realloc_expression(char **expression, size_t len)
158
193
  {
159
- char *tmp_comment = REALLOC_N(*comment, char, len);
160
- *comment = tmp_comment;
194
+ char *tmp_comment = REALLOC_N(*expression, char, len);
195
+ *expression = tmp_comment;
161
196
  }
162
197
 
163
198
  static NODE *
@@ -282,160 +317,6 @@ is_dangling_literal_begin(const char *line)
282
317
  return strstr(line, "%{") != NULL && strstr(line, "}") == NULL;
283
318
  }
284
319
 
285
- static VALUE
286
- find_source(struct filebuf *filebuf)
287
- {
288
- VALUE rb_expr;
289
-
290
- const unsigned expr_size = filebuf->relevant_lines * MAXLINELEN;
291
- char *expr = ALLOC_N(char, expr_size);
292
- expr[0] = '\0';
293
- char *parseable_expr = ALLOC_N(char, expr_size);
294
- parseable_expr[0] = '\0';
295
-
296
- int l = 0;
297
- while (filebuf->lines[l][0] == '\n') {
298
- l++;
299
- continue;
300
- }
301
- char *first_line = (filebuf->lines)[l];
302
-
303
- char *current_line = NULL;
304
- int should_parse = 0;
305
- int dangling_literal = 0;
306
- size_t current_line_len;
307
-
308
- if (is_static_definition(first_line) || is_accessor(first_line)) {
309
- should_parse = 1;
310
- }
311
-
312
- for (unsigned i = l; i < filebuf->relevant_lines; i++) {
313
- current_line = filebuf->lines[i];
314
- current_line_len = strlen(current_line);
315
-
316
- strncat(expr, current_line, current_line_len);
317
-
318
- if (is_comment(current_line, current_line_len))
319
- continue;
320
-
321
- if (is_dangling_literal_end(current_line)) {
322
- dangling_literal = 0;
323
- } else if (is_dangling_literal_begin(current_line)) {
324
- dangling_literal = 1;
325
- } else if (dangling_literal) {
326
- continue;
327
- }
328
-
329
- filter_interp(current_line);
330
- strncat(parseable_expr, current_line, current_line_len);
331
-
332
- if (should_parse || contains_end_kw(current_line)) {
333
- if (parse_expr(rb_str_new2(parseable_expr)) != NULL) {
334
- rb_expr = rb_str_new2(expr);
335
- xfree(expr);
336
- xfree(parseable_expr);
337
- return rb_expr;
338
- }
339
- }
340
- }
341
-
342
- xfree(expr);
343
- xfree(parseable_expr);
344
-
345
- return Qnil;
346
- }
347
-
348
- static void
349
- strnprep(char *s, const char *t, size_t len)
350
- {
351
- size_t i;
352
-
353
- memmove(s + len, s, strlen(s) + 1);
354
-
355
- for (i = 0; i < len; ++i) {
356
- s[i] = t[i];
357
- }
358
- }
359
-
360
- static VALUE
361
- find_comment(struct filebuf *filebuf)
362
- {
363
- size_t comment_len;
364
- size_t current_line_len;
365
- size_t future_bufsize;
366
- char *current_line = NULL;
367
- VALUE rb_comment;
368
-
369
- unsigned long bufsize = COMMENT_SIZE;
370
- char *comment = ALLOC_N(char, COMMENT_SIZE);
371
- comment[0] = '\0';
372
-
373
- int i = filebuf->method_location - 2;
374
-
375
- while (filebuf->lines[i][0] == '\n') {
376
- i--;
377
- continue;
378
- }
379
-
380
- if (!is_comment(filebuf->lines[i], strlen(filebuf->lines[i]))) {
381
- return rb_str_new("", 0);
382
- } else {
383
- while ((current_line = filebuf->lines[i]) &&
384
- is_comment(current_line, (current_line_len = strlen(current_line)))) {
385
- comment_len = strlen(comment);
386
- future_bufsize = comment_len + current_line_len;
387
-
388
- if (future_bufsize >= bufsize) {
389
- bufsize = future_bufsize + COMMENT_SIZE + 1;
390
- realloc_comment(&comment, bufsize);
391
- }
392
- strnprep(comment, current_line, current_line_len);
393
- i--;
394
- }
395
-
396
- rb_comment = rb_str_new2(comment);
397
- xfree(comment);
398
- return rb_comment;
399
- }
400
-
401
- xfree(comment);
402
- free_memory_for_file(&filebuf->lines, filebuf->relevant_lines);
403
- return Qnil;
404
- }
405
-
406
- static char **
407
- allocate_memory_for_file(void)
408
- {
409
- char **file = ALLOC_N(char *, MAXLINES);
410
-
411
- for (int i = 0; i < MAXLINES; i++) {
412
- file[i] = ALLOC_N(char, MAXLINELEN);
413
- }
414
-
415
- return file;
416
- }
417
-
418
- static void
419
- free_memory_for_file(char **file[], const unsigned relevant_lines_n)
420
- {
421
- int lines_to_free = relevant_lines_n >= MAXLINES ? relevant_lines_n : MAXLINES;
422
-
423
- for (int i = 0; i < lines_to_free; i++) {
424
- xfree((*file)[i]);
425
- }
426
-
427
- xfree(*file);
428
- }
429
-
430
- static VALUE
431
- raise_if_nil_safe(VALUE args)
432
- {
433
- struct retval *retval = (struct retval *) args;
434
- raise_if_nil(retval->val, retval->method_name);
435
-
436
- return Qnil;
437
- }
438
-
439
320
  static void
440
321
  raise_if_nil(VALUE val, VALUE method_name)
441
322
  {
@@ -446,7 +327,7 @@ raise_if_nil(VALUE val, VALUE method_name)
446
327
  }
447
328
 
448
329
  static void
449
- filebuf_init(VALUE self, struct filebuf *filebuf)
330
+ method_data_init(VALUE self, struct method_data *data)
450
331
  {
451
332
  VALUE source_location = rb_funcall(self, rb_intern("source_location"), 0);
452
333
  VALUE name = rb_funcall(self, rb_intern("name"), 0);
@@ -459,37 +340,19 @@ filebuf_init(VALUE self, struct filebuf *filebuf)
459
340
  raise_if_nil(rb_filename, name);
460
341
  raise_if_nil(rb_method_location, name);
461
342
 
462
- filebuf->filename = RSTRING_PTR(rb_filename);
463
- filebuf->method_location = FIX2INT(rb_method_location);
464
- filebuf->method_name = name;
465
- filebuf->lines = allocate_memory_for_file();
466
- }
467
-
468
- static void
469
- free_filebuf(VALUE val, struct filebuf *filebuf)
470
- {
471
- int failed;
472
- struct retval retval = {val, filebuf->method_name};
473
-
474
- rb_protect(raise_if_nil_safe, (VALUE) &retval, &failed);
475
- free_memory_for_file(&filebuf->lines, filebuf->relevant_lines);
476
-
477
- if (failed) {
478
- rb_jump_tag(failed);
479
- }
343
+ data->filename = RSTRING_PTR(rb_filename);
344
+ data->method_location = FIX2INT(rb_method_location);
345
+ data->method_name = name;
480
346
  }
481
347
 
482
348
  static VALUE
483
349
  mMethodExtensions_source(VALUE self)
484
350
  {
485
- struct filebuf filebuf;
351
+ struct method_data data;
352
+ method_data_init(self, &data);
486
353
 
487
- filebuf_init(self, &filebuf);
488
- read_lines_after(&filebuf);
489
-
490
- VALUE source = find_source(&filebuf);
491
-
492
- free_filebuf(source, &filebuf);
354
+ VALUE source = find_method_source(&data);
355
+ raise_if_nil(source, data.method_name);
493
356
 
494
357
  return source;
495
358
  }
@@ -497,14 +360,11 @@ mMethodExtensions_source(VALUE self)
497
360
  static VALUE
498
361
  mMethodExtensions_comment(VALUE self)
499
362
  {
500
- struct filebuf filebuf;
501
-
502
- filebuf_init(self, &filebuf);
503
- read_lines_before(&filebuf);
504
-
505
- VALUE comment = find_comment(&filebuf);
363
+ struct method_data data;
364
+ method_data_init(self, &data);
506
365
 
507
- free_filebuf(comment, &filebuf);
366
+ VALUE comment = find_method_comment(&data);
367
+ raise_if_nil(comment, data.method_name);
508
368
 
509
369
  return comment;
510
370
  }
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fast_method_source
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyrylo Silin