Forum: Ruby-core [ruby-trunk - Feature #7816][Open] Don't invalidate method caches when defining a new method on a cl

Posted by charliesome (Charlie Somerville) (Guest)
on 2013-02-09 18:13
(Received via mailing list)
Issue #7816 has been reported by charliesome (Charlie Somerville).

----------------------------------------
Feature #7816: Don't invalidate method caches when defining a new method 
on a class without subclasses
https://bugs.ruby-lang.org/issues/7816

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by SASADA Koichi (Guest)
on 2013-02-09 18:34
(Received via mailing list)
(2013/02/10 2:13), charliesome (Charlie Somerville) wrote:
> In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down to ~1.4 
sec).
>
> This controller action can do ~440 requests per second with my patch, compared 
to ~320 requests per second without my patch.

charliesome++
Posted by marcandre (Marc-Andre Lafortune) (Guest)
on 2013-02-10 01:48
(Received via mailing list)
Issue #7816 has been updated by marcandre (Marc-Andre Lafortune).

Subject changed from Don't invalidate method caches when defining a new 
method on a class without subclasses to Don&#x27;t invalidate method 
caches when defining a new method on a class without subclasses

Speed boosts sounds awesome, especially the 15% rails bootup time, since 
the example is a bit contrived.

It would have been great to get this in 2.0.0

I'd split the new API from the patch; personally I'm not convinced of 
the usefulness of Class#has_subclass?  or of RubyVM.state_version
----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36105

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by mame (Yusuke Endoh) (Guest)
on 2013-02-10 02:20
(Received via mailing list)
Issue #7816 has been updated by mame (Yusuke Endoh).


marcandre (Marc-Andre Lafortune) wrote:
> It would have been great to get this in 2.0.0

Do not kamikaze!

--
Yusuke Endoh <mame@tsg.ne.jp>
----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36110

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by charliesome (Charlie Somerville) (Guest)
on 2013-02-10 02:34
(Received via mailing list)
Issue #7816 has been updated by charliesome (Charlie Somerville).


marcandre (Marc-Andre Lafortune) wrote:
> I'd split the new API from the patch; personally I'm not convinced of the 
usefulness of Class#has_subclass?  or of RubyVM.state_version

I'm not particularly attached to Class#has_subclass? - I don't care if 
that stays or goes. I figured that if we have the information, we may as 
well let the user access it.

I think RubyVM.state_version could be very useful for performance 
profiling. I work on a Rails app that invalidates the method cache ~200 
times per request (mainly due to OpenStruct). I think this patch will 
lower that number somewhat, but I want to keep this API in so I (and 
others) can monitor cache invalidations and try to eliminate the 
remaining invalidations.
----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36111

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by Nobuyoshi Nakada (nobu)
on 2013-02-10 13:35
(Received via mailing list)
Issue #7816 has been updated by nobu (Nobuyoshi Nakada).


Nice.

My thoughts are:

* RCLASS_INHERITED flag should go to internal.h.
* Class#has_subclass? is not only useless but harmful, it mimics users
  when subclasses are removed.
* RubyVM.state_version seems useless also, and should be hidden.
* why rb_method_entry() ignores the cache for an undefined method?
* what are extra parens around RB_TYPE_P() in rb_method_entry_make().
* what's inst in .gitignore.

----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36122

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by charliesome (Charlie Somerville) (Guest)
on 2013-02-10 13:58
(Received via mailing list)
Issue #7816 has been updated by charliesome (Charlie Somerville).


Thanks for the feedback nobu.

> * RCLASS_INHERITED flag should go to internal.h.

I think it should stay in include/ruby/ruby.h where all the other flags 
are defined. This way if someone adds a new class flag, they do not 
accidentally also pick FL_USER5 because they did not see it already in 
use.

> * Class#has_subclass? is not only useless but harmful, it mimics users when 
subclasses are removed.

Fair enough, I'll update my patch and remove it.

> * RubyVM.state_version seems useless also, and should be hidden.

I don't think it is useless. It will be useful for performance tuning. 
Right now there is no way to tell if the method caches have been 
cleared, which makes profiling and tuning harder.

> * why rb_method_entry() ignores the cache for an undefined method?

Here is an example:

  class Foo
    unless method_defined?(:bar)
      def bar
      end
    end
  end

If cache entries for undefined methods were not ignored, 'bar' would be 
defined, but calling it would raise NoMethodError, because the global 
cache thinks it is not defined.

> * what are extra parens around RB_TYPE_P() in rb_method_entry_make().

Whoops, this is my mistake.

> * what's inst in .gitignore.

Ditto, I use './configure --prefix=`pwd`/inst', but I forgot to stash 
before creating the patch.
----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36124

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by charliesome (Charlie Somerville) (Guest)
on 2013-02-10 14:17
(Received via mailing list)
Issue #7816 has been updated by charliesome (Charlie Somerville).

File feature-7816-v2.patch added


----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36125

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by Nobuyoshi Nakada (nobu)
on 2013-02-10 14:34
(Received via mailing list)
Issue #7816 has been updated by nobu (Nobuyoshi Nakada).


charliesome (Charlie Somerville) wrote:
> I think it should stay in include/ruby/ruby.h where all the other
> flags are defined. This way if someone adds a new class flag, they
> do not accidentally also pick FL_USER5 because they did not see it
> already in use.

Rather I think other RMODULE_* flags also should go to internal.h.

> > * Class#has_subclass? is not only useless but harmful, it mimics
> >   users when subclasses are removed.
>
> Fair enough, I'll update my patch and remove it.

Or, add subclass count in rb_classext_t.

> > * what's inst in .gitignore.
>
> Ditto, I use './configure --prefix=`pwd`/inst', but I forgot to
> stash before creating the patch.

I use dotted directories, e.g., .x86_64-linux.

----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36126

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by charliesome (Charlie Somerville) (Guest)
on 2013-02-16 10:32
(Received via mailing list)
Issue #7816 has been updated by charliesome (Charlie Somerville).

File feature-7816-v3.patch added
Subject changed from Don&#x27;t invalidate method caches when defining a 
new method on a class without subclasses to Don't invalidate method 
caches when defining a new method on a class without subclasses

I have updated my patch to not clear the cache when a class is garbage 
collected.

My reasoning is that if a class is garbage collected, then no objects of 
that class could possibly exist, so the method cache would never be hit.
----------------------------------------
Feature #7816: Don't invalidate method caches when defining a new method 
on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36340

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by Yura Sokolov (funny_falcon)
on 2013-02-16 11:35
(Received via mailing list)
Issue #7816 has been updated by funny_falcon (Yura Sokolov).


charliesome (Charlie Somerville) wrote:
> I have updated my patch to not clear the cache when a class is garbage 
collected.
>
> My reasoning is that if a class is garbage collected, then no objects of that 
class could possibly exist, so the method cache would never be hit.

That is not the true: occasionally a new class could be placed at the 
same object slot. Then method cache item will be considered as 
cache-hit, but will point to wrong direction.
----------------------------------------
Feature #7816: Don't invalidate method caches when defining a new method 
on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36342

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee:
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Posted by SASADA Koichi (Guest)
on 2013-02-17 11:47
(Received via mailing list)
(2013/02/16 18:31), charliesome (Charlie Somerville) wrote:
>
> Issue #7816 has been updated by charliesome (Charlie Somerville).
>
> File feature-7816-v3.patch added
> Subject changed from Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses to Don't invalidate method caches when 
defining a new method on a class without subclasses
>
> I have updated my patch to not clear the cache when a class is garbage 
collected.
>
> My reasoning is that if a class is garbage collected, then no objects of that 
class could possibly exist, so the method cache would never be hit.

I found another problem:

Now VM caches method_missing.

class C0
  def method_missing *args
  end
end

class C1 < C0
end

obj = C1.new

2.times{
  obj.foo
  class C1
    def foo; end
  end unless obj.respond_to? :foo
}

In this case, C0#method_missing will be called twice if cache is not
invalidated.
Posted by ko1 (Koichi Sasada) (Guest)
on 2013-02-18 01:34
(Received via mailing list)
Issue #7816 has been updated by ko1 (Koichi Sasada).

Subject changed from Don't invalidate method caches when defining a new 
method on a class without subclasses to Don&#x27;t invalidate method 
caches when defining a new method on a class without subclasses
Assignee set to ko1 (Koichi Sasada)


----------------------------------------
Feature #7816: Don&#x27;t invalidate method caches when defining a new 
method on a class without subclasses
https://bugs.ruby-lang.org/issues/7816#change-36475

Author: charliesome (Charlie Somerville)
Status: Open
Priority: Normal
Assignee: ko1 (Koichi Sasada)
Category: core
Target version: next minor


=begin
Attached is a patch that avoids incrementing the VM state version when 
defining a method and these conditions are true:

* The method is not a redefinition of an existing method in the same 
class or any superclass
* The class has no subclasses
* The class is not a module

This means that defining singleton methods on objects no longer 
invalidates every method cache. This will significantly improve 
performance of code that defines singleton methods at runtime (eg. when 
using OpenStruct)

In my testing, a fresh Rails app boots about 15% faster (~1.7 sec down 
to ~1.4 sec).

This controller action can do ~440 requests per second with my patch, 
compared to ~320 requests per second without my patch.

  class HomeController < ApplicationController
    def index
      OpenStruct.new a: 1, b: 2
      render text: "home"
    end
  end

Of course these numbers will vary between apps, but I think this is a 
good start in improving the performance of a very common use case in 
Ruby.
=end
Please log in before posting. Registration is free and takes only a minute.
Existing account (Switch to SSL-encrypted connection)
NEW: Do you have a Google/GoogleMail or Yahoo account? No registration required!
Log in with Google account | Log in with Yahoo account
No account? Register here.