memcached 0.6 → 0.7

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.
@@ -1,23 +1,24 @@
1
1
 
2
- require 'libmemcached'
2
+ require 'rlibmemcached'
3
3
  require 'memcached/integer'
4
4
  require 'memcached/exceptions'
5
5
  require 'memcached/behaviors'
6
6
  require 'memcached/memcached'
7
+ require 'memcached/rails'
7
8
 
8
9
  =begin rdoc
9
10
  The generated SWIG module for accessing libmemcached's C API.
10
11
 
11
12
  Includes the full set of libmemcached static methods (as defined in <tt>$INCLUDE_PATH/libmemcached/memcached.h</tt>), and classes for the available structs:
12
13
 
13
- * Libmemcached::MemcachedResultSt
14
- * Libmemcached::MemcachedServerSt
15
- * Libmemcached::MemcachedSt
16
- * Libmemcached::MemcachedStatSt
17
- * Libmemcached::MemcachedStringSt
14
+ * <b>Rlibmemcached::MemcachedResultSt</b>
15
+ * <b>Rlibmemcached::MemcachedServerSt</b>
16
+ * <b>Rlibmemcached::MemcachedSt</b>
17
+ * <b>Rlibmemcached::MemcachedStatSt</b>
18
+ * <b>Rlibmemcached::MemcachedStringSt</b>
18
19
 
19
20
  A number of SWIG typemaps and C helper methods are also defined in <tt>ext/libmemcached.i</tt>.
20
21
 
21
22
  =end
22
- module Libmemcached
23
+ module Rlibmemcached
23
24
  end
@@ -4,8 +4,8 @@ class Memcached
4
4
  #:stopdoc:
5
5
 
6
6
  def self.load_constants(prefix, hash = {}, offset = 0)
7
- Libmemcached.constants.grep(/^#{prefix}/).each do |const_name|
8
- hash[const_name[prefix.length..-1].downcase.to_sym] = Libmemcached.const_get(const_name) + offset
7
+ Rlibmemcached.constants.grep(/^#{prefix}/).each do |const_name|
8
+ hash[const_name[prefix.length..-1].downcase.to_sym] = Rlibmemcached.const_get(const_name) + offset
9
9
  end
10
10
  hash
11
11
  end
@@ -42,8 +42,8 @@ class Memcached
42
42
  # STDERR.puts "Setting #{behavior}:#{b_id} => #{value}:#{v_id}"
43
43
 
44
44
  unless value == false
45
- # XXX Setting false still turns on the behavior; maybe a Libmemcached bug
46
- Libmemcached.memcached_behavior_set(@struct, b_id, v_id)
45
+ # XXX Setting false still turns on the behavior; maybe a Rlibmemcached bug
46
+ Rlibmemcached.memcached_behavior_set(@struct, b_id, v_id)
47
47
  end
48
48
 
49
49
  end
@@ -44,6 +44,9 @@ Subclasses correspond one-to-one with server response strings or libmemcached er
44
44
  class Error < RuntimeError
45
45
  end
46
46
 
47
+ class SynchronizationError < RuntimeError
48
+ end
49
+
47
50
  # Raised if a method depends on functionality not yet completed in libmemcached.
48
51
  class NotImplemented < NoMethodError
49
52
  end
@@ -58,12 +61,12 @@ Subclasses correspond one-to-one with server response strings or libmemcached er
58
61
  end
59
62
 
60
63
  EXCEPTIONS = []
61
- EMPTY_STRUCT = Libmemcached::MemcachedSt.new
62
- Libmemcached.memcached_create(EMPTY_STRUCT)
64
+ EMPTY_STRUCT = Rlibmemcached::MemcachedSt.new
65
+ Rlibmemcached.memcached_create(EMPTY_STRUCT)
63
66
 
64
67
  # Generate exception classes
65
- Libmemcached::MEMCACHED_MAXIMUM_RETURN.times do |index|
66
- description = Libmemcached.memcached_strerror(EMPTY_STRUCT, index)
68
+ Rlibmemcached::MEMCACHED_MAXIMUM_RETURN.times do |index|
69
+ description = Rlibmemcached.memcached_strerror(EMPTY_STRUCT, index)
67
70
  exception_class = eval("class #{camelize(description)} < Error; self; end")
68
71
  EXCEPTIONS << exception_class
69
72
  end
@@ -16,7 +16,11 @@ class Memcached
16
16
  :namespace => nil
17
17
  }
18
18
 
19
- IGNORED = 0 #:nodoc:
19
+ #:stopdoc:
20
+ IGNORED = 0
21
+
22
+ NOTFOUND_INSTANCE = NotFound.new
23
+ #:startdoc:
20
24
 
21
25
  attr_reader :options # Return the options Hash used to configure this instance.
22
26
 
@@ -42,8 +46,8 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
42
46
  =end
43
47
 
44
48
  def initialize(servers, opts = {})
45
- @struct = Libmemcached::MemcachedSt.new
46
- Libmemcached.memcached_create(@struct)
49
+ @struct = Rlibmemcached::MemcachedSt.new
50
+ Rlibmemcached.memcached_create(@struct)
47
51
 
48
52
  # Servers
49
53
  Array(servers).each_with_index do |server, index|
@@ -51,12 +55,7 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
51
55
  raise ArgumentError, "Servers must be in the format ip:port (e.g., '127.0.0.1:11211')"
52
56
  end
53
57
  host, port = server.split(":")
54
- Libmemcached.memcached_server_add(@struct, host, port.to_i)
55
-
56
- # XXX To be removed once Krow fixes the write_ptr bug
57
- Libmemcached.memcached_repair_server_st(@struct,
58
- Libmemcached.memcached_select_server_at(@struct, index)
59
- )
58
+ Rlibmemcached.memcached_server_add(@struct, host, port.to_i)
60
59
  end
61
60
 
62
61
  # Behaviors
@@ -73,12 +72,11 @@ Please note that when non-blocking IO is enabled, setter and deleter methods do
73
72
 
74
73
  # Namespace
75
74
  raise ArgumentError, "Invalid namespace" if options[:namespace].to_s =~ / /
76
- @namespace = options[:namespace]
75
+ @namespace = options[:namespace].to_s
76
+ @namespace_size = @namespace.size
77
77
  end
78
78
 
79
- =begin rdoc
80
- Return the array of server strings used to configure this instance.
81
- =end
79
+ # Return the array of server strings used to configure this instance.
82
80
  def servers
83
81
  server_structs.map do |server|
84
82
  "#{server.hostname}:#{server.port}"
@@ -87,12 +85,34 @@ Return the array of server strings used to configure this instance.
87
85
 
88
86
  # Safely copy this instance. Returns a Memcached instance.
89
87
  #
90
- # <tt>clone</tt> is useful for threading, since each thread must have its own unshared Memcached object.
88
+ # <tt>clone</tt> is useful for threading, since each thread must have its own unshared Memcached
89
+ # object. However, you must call destroy before each thread returns or you will leak significant memory.
90
+ #
91
91
  def clone
92
- # XXX Could be more efficient if we used Libmemcached.memcached_clone(@struct)
93
- self.class.new(servers, options)
92
+ memcached = super
93
+ memcached.instance_variable_set('@struct', Rlibmemcached.memcached_clone(nil, @struct))
94
+ memcached
94
95
  end
95
96
 
97
+ # Destroy this instance. Frees memory associated with the C implementation.
98
+ #
99
+ # Accepts an optional parameter <tt>disable_methods</tt>. When <tt>false</tt>, destroy
100
+ # runs much faster, but your instance will segfault if you try to call any other methods on it
101
+ # after destroy. Defaults to <tt>true</tt>, which safely overwrites all instance methods.
102
+ def destroy(disable_methods = true)
103
+ Rlibmemcached.memcached_free(@struct)
104
+ @struct = nil
105
+ if disable_methods
106
+ class << self
107
+ Memcached.instance_methods.each do |method_name|
108
+ define_method method_name do |*args|
109
+ raise Memcached::ClientError, "Instance has been explicitly destroyed"
110
+ end
111
+ end
112
+ end
113
+ end
114
+ end
115
+
96
116
  #:stopdoc:
97
117
  alias :dup :clone #:nodoc:
98
118
  #:startdoc:
@@ -105,7 +125,7 @@ Return the array of server strings used to configure this instance.
105
125
  def server_structs
106
126
  array = []
107
127
  @struct.hosts.count.times do |i|
108
- array << Libmemcached.memcached_select_server_at(@struct, i)
128
+ array << Rlibmemcached.memcached_select_server_at(@struct, i)
109
129
  end
110
130
  array
111
131
  end
@@ -118,14 +138,14 @@ Return the array of server strings used to configure this instance.
118
138
 
119
139
  # Set a key/value pair. Accepts a String <tt>key</tt> and an arbitrary Ruby object. Overwrites any existing value on the server.
120
140
  #
121
- # Accepts an optional <tt>timeout</tt> value to specify the maximum lifetime of the key on the server. <tt>timeout</tt> can be either an integer number of seconds, or a Time elapsed time object. (There is no guarantee that the key will persist as long as the <tt>timeout</tt>, but it will not persist longer.)
141
+ # Accepts an optional <tt>timeout</tt> value to specify the maximum lifetime of the key on the server. <tt>timeout</tt> can be either an integer number of seconds, or a Time elapsed time object. <tt>0</tt> means no timeout. Note that there is no guarantee that the key will persist as long as the <tt>timeout</tt>, but it will not persist longer.
122
142
  #
123
143
  # Also accepts a <tt>marshal</tt> value, which defaults to <tt>true</tt>. Set <tt>marshal</tt> to <tt>false</tt> if you want the <tt>value</tt> to be set directly.
124
144
  #
125
145
  def set(key, value, timeout=0, marshal=true)
126
146
  value = marshal ? Marshal.dump(value) : value.to_s
127
147
  check_return_code(
128
- Libmemcached.memcached_set(@struct, ns(key), value, timeout, FLAGS)
148
+ Rlibmemcached.memcached_set(@struct, ns(key), value, timeout, FLAGS)
129
149
  )
130
150
  end
131
151
 
@@ -133,7 +153,7 @@ Return the array of server strings used to configure this instance.
133
153
  def add(key, value, timeout=0, marshal=true)
134
154
  value = marshal ? Marshal.dump(value) : value.to_s
135
155
  check_return_code(
136
- Libmemcached.memcached_add(@struct, ns(key), value, timeout, FLAGS)
156
+ Rlibmemcached.memcached_add(@struct, ns(key), value, timeout, FLAGS)
137
157
  )
138
158
  end
139
159
 
@@ -143,14 +163,14 @@ Return the array of server strings used to configure this instance.
143
163
  #
144
164
  # Note that the key must be initialized to an unmarshalled integer first, via <tt>set</tt>, <tt>add</tt>, or <tt>replace</tt> with <tt>marshal</tt> set to <tt>false</tt>.
145
165
  def increment(key, offset=1)
146
- ret, value = Libmemcached.memcached_increment(@struct, ns(key), offset)
166
+ ret, value = Rlibmemcached.memcached_increment(@struct, ns(key), offset)
147
167
  check_return_code(ret)
148
168
  value
149
169
  end
150
170
 
151
171
  # Decrement a key's value. The parameters and exception behavior are the same as <tt>increment</tt>.
152
172
  def decrement(key, offset=1)
153
- ret, value = Libmemcached.memcached_decrement(@struct, ns(key), offset)
173
+ ret, value = Rlibmemcached.memcached_decrement(@struct, ns(key), offset)
154
174
  check_return_code(ret)
155
175
  value
156
176
  end
@@ -164,7 +184,7 @@ Return the array of server strings used to configure this instance.
164
184
  def replace(key, value, timeout=0, marshal=true)
165
185
  value = marshal ? Marshal.dump(value) : value.to_s
166
186
  check_return_code(
167
- Libmemcached.memcached_replace(@struct, ns(key), value, timeout, FLAGS)
187
+ Rlibmemcached.memcached_replace(@struct, ns(key), value, timeout, FLAGS)
168
188
  )
169
189
  end
170
190
 
@@ -174,7 +194,7 @@ Return the array of server strings used to configure this instance.
174
194
  def append(key, value)
175
195
  # Requires memcached 1.2.4
176
196
  check_return_code(
177
- Libmemcached.memcached_append(@struct, ns(key), value.to_s, IGNORED, FLAGS)
197
+ Rlibmemcached.memcached_append(@struct, ns(key), value.to_s, IGNORED, FLAGS)
178
198
  )
179
199
  end
180
200
 
@@ -182,7 +202,7 @@ Return the array of server strings used to configure this instance.
182
202
  def prepend(key, value)
183
203
  # Requires memcached 1.2.4
184
204
  check_return_code(
185
- Libmemcached.memcached_prepend(@struct, ns(key), value.to_s, IGNORED, FLAGS)
205
+ Rlibmemcached.memcached_prepend(@struct, ns(key), value.to_s, IGNORED, FLAGS)
186
206
  )
187
207
  end
188
208
 
@@ -204,7 +224,7 @@ Return the array of server strings used to configure this instance.
204
224
  # Deletes a key/value pair from the server. Accepts a String <tt>key</tt>. Raises <b>Memcached::NotFound</b> if the key does not exist.
205
225
  def delete(key)
206
226
  check_return_code(
207
- Libmemcached.memcached_delete(@struct, ns(key), IGNORED)
227
+ Rlibmemcached.memcached_delete(@struct, ns(key), IGNORED)
208
228
  )
209
229
  end
210
230
 
@@ -214,30 +234,36 @@ Return the array of server strings used to configure this instance.
214
234
  #
215
235
  # Also accepts a <tt>marshal</tt> value, which defaults to <tt>true</tt>. Set <tt>marshal</tt> to <tt>false</tt> if you want the <tt>value</tt> to be returned directly as a String. Otherwise it will be assumed to be a marshalled Ruby object and unmarshalled.
216
236
  #
217
- # If you pass a single key, and the key does not exist on the server, <b>Memcached::NotFound</b> will be raised. If you pass an array of keys, memcached's <tt>multiget</tt> mode will be used, and an array of values will be returned. Missing values in the array will be represented as instances of <b>Memcached::NotFound</b>. This behavior may change in the future.
237
+ # If you pass a String key, and the key does not exist on the server, <b>Memcached::NotFound</b> will be raised. If you pass an array of keys, memcached's <tt>multiget</tt> mode will be used, and a hash of key/value pairs will be returned. The hash will contain only the keys that were found.
238
+ #
239
+ # The multiget behavior is subject to change in the future; however, for multiple lookups, it is much faster than normal mode.
218
240
  #
219
- def get(key, marshal=true)
220
- # XXX Could be faster if it didn't have to branch on the key type
221
- if key.is_a? Array
241
+ # Note that when you rescue Memcached::NotFound exceptions, you should use a the block rescue syntax instead of the inline syntax. Block rescues are very fast, but inline rescues are very slow.
242
+ #
243
+ def get(keys, marshal=true)
244
+ if keys.is_a? Array
222
245
  # Multi get
223
- # XXX Waiting on the real implementation
224
- key.map do |this_key|
225
- begin
226
- get(this_key, marshal)
227
- rescue NotFound => e
228
- e
229
- end
246
+ keys.map! { |key| ns(key) }
247
+ hash = {}
248
+
249
+ Rlibmemcached.memcached_mget(@struct, keys);
250
+
251
+ keys.size.times do
252
+ value, key, flags, ret = Rlibmemcached.memcached_fetch_rvalue(@struct)
253
+ break if ret == Rlibmemcached::MEMCACHED_END
254
+ check_return_code(ret)
255
+ value = Marshal.load(value) if marshal
256
+ # Assign the value, removing the namespace, if present
257
+ hash[key[@namespace_size..-1]] = value
230
258
  end
259
+ hash
231
260
  else
232
261
  # Single get
233
- # XXX Server doesn't validate keys. Regex is possibly a performance problem.
234
- raise ClientError, "Invalid key" if key =~ /\s/
235
-
236
- value, flags, ret = Libmemcached.memcached_get_ruby_string(@struct, ns(key))
262
+ value, flags, ret = Rlibmemcached.memcached_get_rvalue(@struct, ns(keys))
237
263
  check_return_code(ret)
238
264
  value = Marshal.load(value) if marshal
239
265
  value
240
- end
266
+ end
241
267
  end
242
268
 
243
269
  ### Information methods
@@ -246,18 +272,18 @@ Return the array of server strings used to configure this instance.
246
272
  def stats
247
273
  stats = Hash.new([])
248
274
 
249
- stat_struct, ret = Libmemcached.memcached_stat(@struct, "")
275
+ stat_struct, ret = Rlibmemcached.memcached_stat(@struct, "")
250
276
  check_return_code(ret)
251
277
 
252
- keys, ret = Libmemcached.memcached_stat_get_keys(@struct, stat_struct)
278
+ keys, ret = Rlibmemcached.memcached_stat_get_keys(@struct, stat_struct)
253
279
  check_return_code(ret)
254
280
 
255
281
  keys.each do |key|
256
282
  server_structs.size.times do |index|
257
283
 
258
- value, ret = Libmemcached.memcached_stat_get_value(
284
+ value, ret = Rlibmemcached.memcached_stat_get_rvalue(
259
285
  @struct,
260
- Libmemcached.memcached_select_stat_at(@struct, stat_struct, index),
286
+ Rlibmemcached.memcached_select_stat_at(@struct, stat_struct, index),
261
287
  key)
262
288
  check_return_code(ret)
263
289
 
@@ -271,7 +297,7 @@ Return the array of server strings used to configure this instance.
271
297
  end
272
298
  end
273
299
 
274
- Libmemcached.memcached_stat_free(@struct, stat_struct)
300
+ Rlibmemcached.memcached_stat_free(@struct, stat_struct)
275
301
  stats
276
302
  end
277
303
 
@@ -281,14 +307,21 @@ Return the array of server strings used to configure this instance.
281
307
 
282
308
  # Return a namespaced key for this Memcached instance. Accepts a String <tt>key</tt> value.
283
309
  def ns(key) #:doc:
310
+ # raise ClientError, "Invalid key" if key =~ /\s/ # XXX Slow
284
311
  "#{@namespace}#{key}"
285
312
  end
286
313
 
287
- # Checks the return code from Libmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code.
314
+ # Checks the return code from Rlibmemcached against the exception list. Raises the corresponding exception if the return code is not Memcached::Success or Memcached::ActionQueued. Accepts an integer return code.
288
315
  def check_return_code(ret) #:doc:
289
- # XXX 0.14 already returns 0 for an ActionQueued result
316
+ # 0.14 returns 0 for an ActionQueued result but 0.15 does not.
290
317
  return if ret == 0 or ret == 31
291
318
  raise EXCEPTIONS[ret], ""
319
+ rescue UnknownReadFailure
320
+ # libmemcached got out of sync; rebuild the struct
321
+ new_struct = Rlibmemcached.memcached_clone(nil, @struct)
322
+ Rlibmemcached.memcached_free(@struct)
323
+ @struct = new_struct
324
+ raise SynchronizationError, "Rebuilding @struct"
292
325
  end
293
326
 
294
327
  end
@@ -0,0 +1,55 @@
1
+
2
+ class Memcached
3
+
4
+ alias :get_multi :get #:nodoc:
5
+
6
+ # A legacy compatibility wrapper for the Memcached class. It has basic compatibility with the <b>memcache-client</b> API.
7
+ class Rails < ::Memcached
8
+
9
+ DEFAULTS = {}
10
+
11
+ # See Memcached#new for details.
12
+ def initialize(servers, opts = {})
13
+ super(servers, DEFAULTS.merge(opts))
14
+ end
15
+
16
+ # Wraps Memcached#get so that it doesn't raise. This has the side-effect of preventing you from
17
+ # storing <tt>nil</tt> values.
18
+ def get(key, raw = false)
19
+ super(key, !raw)
20
+ rescue NotFound
21
+ end
22
+
23
+ # Wraps Memcached#get with multiple arguments.
24
+ def get_multi(*keys)
25
+ super(keys)
26
+ end
27
+
28
+ # Wraps Memcached#set.
29
+ def set(key, value, ttl = 0, raw = false)
30
+ super(key, value, ttl, !raw)
31
+ end
32
+
33
+ # Wraps Memcached#delete so that it doesn't raise.
34
+ def delete(key)
35
+ super(key)
36
+ rescue NotFound
37
+ end
38
+
39
+ # Namespace accessor.
40
+ def namespace
41
+ @namespace
42
+ end
43
+
44
+ # Alias for get.
45
+ def [](key)
46
+ get key
47
+ end
48
+
49
+ # Alias for Memcached#set.
50
+ def []=(key, value)
51
+ set key, value
52
+ end
53
+
54
+ end
55
+ end
@@ -1,27 +1,27 @@
1
1
 
2
- # Gem::Specification for Memcached-0.6
2
+ # Gem::Specification for Memcached-0.7
3
3
  # Originally generated by Echoe
4
4
 
5
5
  Gem::Specification.new do |s|
6
6
  s.name = %q{memcached}
7
- s.version = "0.6"
7
+ s.version = "0.7"
8
8
 
9
9
  s.specification_version = 2 if s.respond_to? :specification_version=
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.authors = ["Evan Weaver"]
13
- s.date = %q{2008-01-21}
13
+ s.date = %q{2008-02-05}
14
14
  s.description = %q{An interface to the libmemcached C client.}
15
15
  s.email = %q{}
16
16
  s.extensions = ["ext/extconf.rb"]
17
- s.files = ["CHANGELOG", "ext/extconf.rb", "ext/libmemcached.i", "ext/libmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached.rb", "LICENSE", "Manifest", "README", "test/benchmark/benchmark.rb", "test/benchmark/benchmark_set_get.rb", "test/benchmark/profile.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "TODO", "memcached.gemspec"]
17
+ s.files = ["BENCHMARKS", "CHANGELOG", "COMPATIBILITY", "ext/extconf.rb", "ext/rlibmemcached.i", "ext/rlibmemcached_wrap.c", "lib/memcached/behaviors.rb", "lib/memcached/exceptions.rb", "lib/memcached/integer.rb", "lib/memcached/memcached.rb", "lib/memcached/rails.rb", "lib/memcached.rb", "LICENSE", "Manifest", "README", "test/profile/benchmark.rb", "test/profile/profile.rb", "test/profile/valgrind.rb", "test/setup.rb", "test/teardown.rb", "test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb", "TODO", "memcached.gemspec"]
18
18
  s.has_rdoc = true
19
19
  s.homepage = %q{http://blog.evanweaver.com/files/doc/fauna/memcached/}
20
20
  s.require_paths = ["lib", "ext"]
21
21
  s.rubyforge_project = %q{fauna}
22
22
  s.rubygems_version = %q{1.0.1}
23
23
  s.summary = %q{An interface to the libmemcached C client.}
24
- s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb"]
24
+ s.test_files = ["test/test_helper.rb", "test/unit/binding_test.rb", "test/unit/memcached_test.rb", "test/unit/rails_test.rb"]
25
25
  end
26
26
 
27
27
 
@@ -35,7 +35,7 @@ end
35
35
  # p.summary = "An interface to the libmemcached C client."
36
36
  # p.url = "http://blog.evanweaver.com/files/doc/fauna/memcached/"
37
37
  # p.docs_host = "blog.evanweaver.com:~/www/bax/public/files/doc/"
38
- # p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|exceptions|behaviors|memcached.rb/
38
+ # p.rdoc_pattern = /README|TODO|LICENSE|CHANGELOG|BENCH|COMPAT|exceptions|behaviors|rails.rb|memcached.rb/
39
39
  # end
40
40
  #
41
41
  # task :exceptions do
@@ -49,3 +49,11 @@ end
49
49
  # end
50
50
  # end
51
51
  # end
52
+ #
53
+ # task :valgrind do
54
+ # exec("valgrind --tool=memcheck --leak-check=yes --show-reachable=no --num-callers=15 --track-fds=yes ruby #{File.dirname(__FILE__)}/test/profile/valgrind.rb")
55
+ # end
56
+ #
57
+ # task :profile do
58
+ # exec("ruby #{File.dirname(__FILE__)}/test/profile/profile.rb")
59
+ # end