fast_method_source 0.3.0 → 0.3.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.
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