fast_method_source 0.3.0 → 0.3.1

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: a652f4b019d35eaf42c337bed8e5a556cefaf8bc
4
- data.tar.gz: c6dd63e38ed0542570e7bc395a1f798341021c6d
3
+ metadata.gz: d73c77ef828261b4ad145f88bd1d78682133b215
4
+ data.tar.gz: 3fa8f4dc7471bd3e2b78f6c479bc795d38972f13
5
5
  SHA512:
6
- metadata.gz: 4194e5d174e2d5c4ff5699b20bda1ee9676edc224a05b6bd255e3f73dc723329a08468e6e5839283e1136271b1f2c7d68a83cda5979d5aaa0be714dec0e6ec45
7
- data.tar.gz: 67b9991bff995852cba78548c5fd8aca9886f353f3ce90fdc34e78387ef25c7564102335a36f4d3263bf00eaca9865ceca0dd8f62a483fdd6df58a0dcaad2bad
6
+ metadata.gz: 5d3ab1de1d9a55e1c681e684c85cbc92f349e77927cbfb0999ce59419c35a6120d588286133399e0484ff60258fb4313f02145de33a0f71419db504b98f24054
7
+ data.tar.gz: 4426e0c403f8de0b80bed5264cd91495a06d5468ba73912b5b5a4511ef0a4942915c7d1b19f7a64bb67d2e65d055922a6c1a6d4f298b53fff8ab3ca5f094c871
data/CHANGELOG.md CHANGED
@@ -1,6 +1,10 @@
1
1
  Fast Method Source changelog
2
2
  ============================
3
3
 
4
+ ### v0.3.1 (June 11, 2015)
5
+
6
+ * Considerable speed improvements
7
+
4
8
  ### v0.3.0 (June 11, 2015)
5
9
 
6
10
  * _Significantly_ reduced memory consumption (`#comment_and_source` for 19K
data/README.md CHANGED
@@ -1,7 +1,33 @@
1
+ <a name="Back_to_top">
1
2
  # Fast Method Source
2
3
 
3
4
  * Repository: [https://github.com/kyrylo/fast_method_source/][repo]
4
5
 
6
+ Table of Contents
7
+ -----------------
8
+
9
+ * <a href="#description">Description</a>
10
+ * <a href="#installation">Installation</a>
11
+ * <a href="#synopsis">Synopsis</a>
12
+ * <a href="#speed-improvements">Speed Improvements</a>
13
+ * <a href="#source">#source</a>
14
+ * <a href="#comment">#comment</a>
15
+ * <a href="#source-and-comment">#source_and_comment</a>
16
+ * <a href="#correctness-of-output">Correctness Of Output</a>
17
+ * <a href="#ram-consumption">RAM Consumption</a>
18
+ * <a href="#api">API</a>
19
+ * <a href="#method-information">Method Information</a>
20
+ * <a href="#fastmethodsourcesource_formethod">FastMethodSource#source_for(method)</a>
21
+ * <a href="#fastmethodsourcecomment_formethod">FastMethodSource#comment_for(method)</a>
22
+ * <a href="#fastmethodsourcecomment_and_source_formethod">FastMethodSource#comment_and_source_for(method)</a>
23
+ * <a href="#limitations">Limitations</a>
24
+ * <a href="#rubies">Rubies</a>
25
+ * <a href="#operation-systems">Operation Systems</a>
26
+ * <a href="#roadmap">Roadmap</a>
27
+ * <a href="#further-speed-improvements">Further Speed Improvements</a>
28
+ * <a href="#optional-memoization">Optional Memoization</a>
29
+ * <a href="#licence">Licence</a>
30
+
5
31
  Description
6
32
  -----------
7
33
 
@@ -10,7 +36,7 @@ their source code and comments.
10
36
 
11
37
  ```ruby
12
38
  require 'fast_method_source'
13
- require 'fast_method_source/core_ext'
39
+ require 'fast_method_source/core_ext' # Adds #source to UnboundMethod
14
40
  require 'set'
15
41
 
16
42
  puts Set.instance_method(:merge).source
@@ -40,73 +66,78 @@ All you need is to install the gem.
40
66
  Synopsis
41
67
  --------
42
68
 
43
- Fast Method Source provides similar functionality to [method_source][ms], which
44
- is being used by the Pry REPL, but with a number of major key differences.
45
-
46
- ### Speed improvements
69
+ Fast Method Source provides functionality similar to [method_source][ms], which
70
+ powers [Pry](https://github.com/pry/pry)'s `show-source`, `show-comment` and
71
+ `find-method` commands, but with a number of key differences that are listed
72
+ below.
47
73
 
48
- The main goal of Fast Method Source is to be as fast as possible. In result, the
49
- library is much faster than method_source. What's acceptable for Pry, when you
50
- query only one method, is not acceptable for other use cases such as querying
51
- all the methods defined in your Ruby process. The benchmark showed that Fast
52
- Method Source is about 5-10x faster than its competitor.
74
+ ### Speed Improvements
53
75
 
54
- I'd be remiss if I didn't mention that there's also room for further speed
55
- improvements. The benchmarks below represent comparison of both libraries.
76
+ The main goal of Fast Method Source is to retrieve information as fast as
77
+ possible. In result, the library is extremely fast and is capable of quering
78
+ thousands of methods in a couple of seconds. The benchmarks included in this
79
+ repository show that Fast Method Source outpaces method_source in every aspect
80
+ by far. The results from those benchmarks below show the comparison of these
81
+ libraries.
56
82
 
57
- #### #comment_and_source
83
+ #### #source
58
84
  ##### ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
59
85
 
60
- This is a utility method and method_source doesn't feature it.
86
+ The speed boost of method_source after the rehearsal that can be observed in
87
+ this benchmark comes from the fact that it uses memoization. Fast Method Source
88
+ does not support it at the moment.
61
89
 
62
90
  ```
63
91
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
64
92
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
65
93
  Counting the number of sample methods...
66
- Sample methods: 19438
67
- user system total real
68
- FastMethodSource#comment_and_source_for 16.240000 1.180000 17.420000 ( 19.439981)
94
+ Sample methods: 18970
95
+ Rehearsal -----------------------------------------------------------
96
+ FastMethodSource#source 6.340000 0.460000 6.800000 ( 7.616361)
97
+ MethodSource#source 86.030000 0.500000 86.530000 (104.094356)
98
+ ------------------------------------------------- total: 93.330000sec
99
+
100
+ user system total real
101
+ FastMethodSource#source 6.830000 0.590000 7.420000 ( 8.258469)
102
+ MethodSource#source 80.470000 0.310000 80.780000 ( 89.864366)
69
103
  ```
70
104
 
71
- #### #source
105
+ #### #comment
72
106
  ##### ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
73
107
 
74
108
  ```
75
109
  Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
76
110
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
77
111
  Counting the number of sample methods...
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
112
+ Sample methods: 19596
113
+ Rehearsal ------------------------------------------------------------
114
+ FastMethodSource#comment 1.820000 0.240000 2.060000 ( 2.300117)
115
+ MethodSource#comment 77.020000 0.360000 77.380000 ( 94.672830)
116
+ -------------------------------------------------- total: 79.440000sec
83
117
 
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)
118
+ user system total real
119
+ FastMethodSource#comment 1.570000 0.230000 1.800000 ( 1.997811)
120
+ MethodSource#comment 71.410000 0.160000 71.570000 ( 79.657388)
87
121
  ```
88
122
 
89
- #### #comment
123
+ #### #comment_and_source
90
124
  ##### ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
91
125
 
126
+ This is a convenience method, and method_source doesn't have it.
127
+
92
128
  ```
129
+ Processor: Intel(R) Core(TM) i5-2410M CPU @ 2.30GHz
93
130
  Platform: ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
94
131
  Counting the number of sample methods...
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
100
-
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)
132
+ Sample methods: 18970
133
+ user system total real
134
+ FastMethodSource#comment_and_source_for 8.240000 0.750000 8.990000 ( 10.036892)
104
135
  ```
105
136
 
106
- ### Correctness of output
137
+ ### Correctness Of Output
107
138
 
108
139
  Fast Method Source is capable of displaying source code even for dynamically
109
- defined methods (there are some crazy methods in stdlib).
140
+ defined methods.
110
141
 
111
142
  ```ruby
112
143
  require 'fast_method_source'
@@ -126,38 +157,39 @@ Output.
126
157
  end
127
158
  ```
128
159
 
129
- ### RAM consumption
160
+ That said, you need to be cautious, because sometimes it's not working as
161
+ expected. Feel free to file issues.
162
+
163
+ ### RAM Consumption
130
164
 
131
165
  The [`comment_and_source`](/benchmarks/comment_and_source_for.rb) benchmark
132
- shows that at this moment the library uses about 450 MB of RAM.
166
+ shows that the library uses about 80-140 MB of RES RAM for computing information
167
+ for 19K methods.
133
168
 
134
169
  API
135
170
  ---
136
171
 
137
- ### General description
138
-
139
172
  The library provides the following methods: `#comment`, `#source` and
140
- `#comment_and_source`. There are two ways to use Fast Method Source. One way is
141
- to monkey-patch relevant core Ruby classes and use the methods directly.
173
+ `#comment_and_source`. There are two ways to use Fast Method Source.
174
+
175
+ One way is to monkey-patch relevant core Ruby classes and use the methods
176
+ directly.
142
177
 
143
178
  ```ruby
144
179
  require 'fast_method_source'
145
- require 'fast_method_source/core_ext'
180
+ require 'fast_method_source/core_ext' # <= monkey-patches
146
181
 
147
- # With UnboundMethod
148
- Set.instance_method(:merge).source
149
- #=> " def merge(enum)\n..."
182
+ # Monkey-patch of UnboundMethod
183
+ Set.instance_method(:merge).source #=> " def merge(enum)\n..."
150
184
 
151
- # With Method
152
- Set.method(:[]).source
153
- #=> " def self.[](*ary)\n..."
185
+ # Monkey-patch of Method
186
+ Set.method(:[]).source #=> " def self.[](*ary)\n..."
154
187
 
155
- # With Proc (or lambda)
188
+ # Monkey-patch of Proc (or lambda)
156
189
  myproc = proc { |arg|
157
190
  arg + 1
158
191
  }
159
- myproc.source
160
- #=> "myproc = proc { |arg|\n..."
192
+ myproc.source #=> "myproc = proc { |arg|\n..."
161
193
  ```
162
194
 
163
195
  The other way is by using these methods defined on the library's class directly.
@@ -166,22 +198,19 @@ The other way is by using these methods defined on the library's class directly.
166
198
  require 'fast_method_source'
167
199
 
168
200
  # With UnboundMethod
169
- FastMethodSource.source_for(Set.instance_method(:merge))
170
- #=> " def merge(enum)\n..."
201
+ FastMethodSource.source_for(Set.instance_method(:merge)) #=> " def merge(enum)\n..."
171
202
 
172
203
  # With Method
173
- FastMethodSource.source_for(Set.method(:[]))
174
- #=> " def self.[](*ary)\n..."
204
+ FastMethodSource.source_for(Set.method(:[])) #=> " def self.[](*ary)\n..."
175
205
 
176
206
  # With Proc (or lambda)
177
207
  myproc = proc { |arg|
178
208
  arg + 1
179
209
  }
180
- FastMethodSource.source_for(myproc)
181
- #=> "myproc = proc { |arg|\n..."
210
+ FastMethodSource.source_for(myproc) #=> "myproc = proc { |arg|\n..."
182
211
  ```
183
212
 
184
- ### Methods
213
+ ### Method Information
185
214
 
186
215
  #### FastMethodSource#source_for(method)
187
216
 
@@ -224,7 +253,7 @@ Limitations
224
253
  Rubies below 2.2.2 were not tested, so in theory if it quacks like Ruby 2, it
225
254
  may work.
226
255
 
227
- ### OS'es
256
+ ### Operation Systems
228
257
 
229
258
  * GNU/Linux
230
259
  * Mac OS (hopefully)
@@ -232,19 +261,22 @@ may work.
232
261
  Roadmap
233
262
  -------
234
263
 
235
- ### Further speed improvements
264
+ ### Further Speed Improvements
236
265
 
237
266
  Although Fast Method Source is faster than any of its competitors, it's still
238
- very slow. On average, a mature Rails 4 application has at least 45K methods. In
239
- order to query all those methods for their source code, you would need to wait
240
- for a while and perhaps to drink a cup of tea.
267
+ very slow. On average, a mature Rails 4 application has at least 45K
268
+ methods. The goal of the project is to be able to query 50K methods in less than
269
+ 15 seconds.
241
270
 
242
- The goal of the project is to be able to query 50K methods in less than 15
243
- seconds. Whether it's possible or not is to be determined.
271
+ ### Optional Memoization
244
272
 
245
- ### Decrease memory consumption
273
+ I'm not sure about this, if it's really needed, but it will speed up further
274
+ queries greatly (at the cost of RAM). At this moment I think if I add it, it
275
+ should be optional and configurable like this:
246
276
 
247
- I'm not happy about the current rates. To be investigated.
277
+ ```ruby
278
+ FastMethodSource.memoization = true # or `false`
279
+ ```
248
280
 
249
281
  Licence
250
282
  -------
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
@@ -42,6 +42,7 @@ static VALUE find_method_source(struct method_data *data);
42
42
  static NODE *parse_expr(VALUE rb_str);
43
43
  static NODE *parse_with_silenced_stderr(VALUE rb_str);
44
44
  static void filter_interp(char *line);
45
+ static int contains_skippables(const char *line);
45
46
  static int contains_end_kw(const char *line);
46
47
  static int is_comment(const char *line, const size_t line_len);
47
48
  static int is_static_definition(const char *line);
@@ -121,7 +122,8 @@ read_lines(finder finder, struct method_data *data)
121
122
  }
122
123
  strncat(expression, current_line, cl_len);
123
124
 
124
- if (current_line[0] == '\n')
125
+ if (current_line[0] == '\n' ||
126
+ is_comment(current_line, cl_len))
125
127
  continue;
126
128
 
127
129
  if (line_count == data->method_location) {
@@ -130,9 +132,6 @@ read_lines(finder finder, struct method_data *data)
130
132
  }
131
133
  }
132
134
 
133
- if (is_comment(current_line, cl_len))
134
- continue;
135
-
136
135
  if (is_dangling_literal_end(current_line)) {
137
136
  dangling_literal = 0;
138
137
  } else if (is_dangling_literal_begin(current_line)) {
@@ -149,6 +148,9 @@ read_lines(finder finder, struct method_data *data)
149
148
  }
150
149
  strncat(parse_expression, current_line, cl_len);
151
150
 
151
+ if (contains_skippables(current_line))
152
+ continue;
153
+
152
154
  if (should_parse || contains_end_kw(current_line)) {
153
155
  if (parse_expr(rb_str_new2(parse_expression)) != NULL) {
154
156
  found_expression = 1;
@@ -209,7 +211,6 @@ parse_with_silenced_stderr(VALUE rb_str)
209
211
 
210
212
  volatile VALUE vparser = rb_parser_new();
211
213
  NODE *node = rb_parser_compile_string(vparser, "-", rb_str, 1);
212
- rb_str_free(rb_str);
213
214
  rb_set_errinfo(last_exception);
214
215
 
215
216
  fflush(stderr);
@@ -255,6 +256,28 @@ filter_interp(char *line)
255
256
  }
256
257
  }
257
258
 
259
+ static int
260
+ contains_skippables(const char *line)
261
+ {
262
+
263
+ static unsigned short len = 57;
264
+ static const char *skippables[57] = {
265
+ " if ", " else ", " then ", " case ", " for ", " in ", " loop ",
266
+ " unless ", "||", "||=", "&&", " and ", " or ", " do ", " not ",
267
+ " while ", " = ", " == ", " === ", " > ", " < ", " >= ", " <= ",
268
+ " << ", " += ", "\"", "'", ":", ",", ".", " % ", "!", "?",
269
+ " until ", "(&", "|", "(", ")", "~", " * ", " - ", " + ", " / ",
270
+ " {", " raise ", " fail ", " begin ", " rescue ", " ensure ",
271
+ ".new", "@", " lambda", " proc", " ->", "[", "]", "$"};
272
+
273
+ for (unsigned short i = 0; i < len; i++) {
274
+ if (strstr(line, skippables[i]) != NULL)
275
+ return 1;
276
+ }
277
+
278
+ return 0;
279
+ }
280
+
258
281
  static int
259
282
  contains_end_kw(const char *line)
260
283
  {
@@ -283,17 +306,7 @@ is_comment(const char *line, const size_t line_len)
283
306
  for (size_t i = 0; i < line_len; i++) {
284
307
  if (line[i] == ' ')
285
308
  continue;
286
-
287
- if (line[i] == '#' && line[i + 1] != '{') {
288
- for (size_t j = i - 1; j != 0; j--) {
289
- if (line[j] != ' ')
290
- return 0;
291
- }
292
-
293
- return 1;
294
- } else {
295
- return 0;
296
- }
309
+ return line[i] == '#' && line[i + 1] != '{';
297
310
  }
298
311
 
299
312
  return 0;
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.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kyrylo Silin