Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Proxy objects - frequent FETCHs #4704

Open
p6rt opened this issue Oct 31, 2015 · 7 comments
Open

Proxy objects - frequent FETCHs #4704

p6rt opened this issue Oct 31, 2015 · 7 comments
Labels

Comments

@p6rt
Copy link

p6rt commented Oct 31, 2015

Migrated from rt.perl.org#126520 (status was 'new')

Searchable as RT126520$

@p6rt
Copy link
Author

p6rt commented Oct 31, 2015

From @dwarring

Consider the following, which should be a simple and conventional use of Perl 6 Proxy objects​:

class C {
  has $!foo;
  method foo is rw {
  say "foo";
  $!foo;
  }

  has $!bar;
  method bar is rw {
  Proxy.new(
  say "proxy new";
  FETCH => sub ($) {
  say "bar fetch";
  $!bar
  },
  STORE => sub ($, $v) {
  say "bar store";
  $!bar = $v;
  },
  );
  }
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

OUTPUT​:

FETCHES
foo
proxy new
bar fetch
bar fetch
bar fetch
STORES
foo
proxy new
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar store

===================
In the above example, the bar proxy is called 10x whereas foo is called twice.

In particular, the proxy FETCH is called 7X to do a simple increment.

I'm raising this because this is the 'hot path' in projects such as https://github.com/p6-pdf/perl6-PDF-Tools.

Would like to see this reduced, if possible.

@p6rt
Copy link
Author

p6rt commented Oct 31, 2015

From @dwarring

Correct to test case, (say in wrong position)​:

class C {
  has $!foo;
  method foo is rw {
  say "foo";
  $!foo;
  }

  has $!bar;
  method bar is rw {
  say "proxy new";

  Proxy.new(
  FETCH => sub ($) {
  say "bar fetch";
  $!bar;
  },
  STORE => sub ($, $v) {
  say "bar store";
  $!bar = $v;
  },
  );
  }
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

On Sat Oct 31 12​:09​:05 2015, david.warring wrote​:

Consider the following, which should be a simple and conventional use
of Perl 6 Proxy objects​:

class C {
has $!foo;
method foo is rw {
say "foo";
$!foo;
}

has $!bar;
method bar is rw {
Proxy.new(
say "proxy new";
FETCH => sub ($) {
say "bar fetch";
$!bar
},
STORE => sub ($, $v) {
say "bar store";
$!bar = $v;
},
);
}
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

OUTPUT​:

FETCHES
foo
proxy new
bar fetch
bar fetch
bar fetch
STORES
foo
proxy new
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar store

===================
In the above example, the bar proxy is called 10x whereas foo is
called twice.

In particular, the proxy FETCH is called 7X to do a simple increment.

I'm raising this because this is the 'hot path' in projects such as
https://github.com/p6-pdf/perl6-PDF-Tools.

Would like to see this reduced, if possible.

@p6rt
Copy link
Author

p6rt commented Apr 12, 2016

From @dwarring

Here's an attempt at bench-marking proxy objects, vs a simple home-baked accessor​:

use Bench;
class C {
  has $!foo;
  method foo is rw {
  $!foo;
  }

  has $!bar;
  method bar is rw {
  Proxy.new(
  FETCH => sub ($) {
  $!bar;
  },
  STORE => sub ($, $v) {
  $!bar = $v;
  },
  );
  }
}

my $c = C.new;

Bench.new.cmpthese(1000, {
  simple-rw => {
  $c.foo = 42;
  $c.foo++ for 1..10;
  },
  proxy-rw => {
  $c.bar = 42;
  $c.bar++ for 1..10;
  },
});

# results

Benchmark​:
Timing 1000 iterations of proxy-rw, simple-rw...
  proxy-rw​: 1.1713 wallclock secs @​ 853.7233/s (n=1000)
simple-rw​: 0.0149 wallclock secs @​ 66935.9365/s (n=1000)
O-----------O---------O-----------O----------O
| | Rate | simple-rw | proxy-rw |
O===========O=========O===========O==========O
| simple-rw | 66933/s | -- | 7740% |
| proxy-rw | 854/s | -99% | -- |


Proxys look like an expensive option at the moment.
- David

On Sat Oct 31 13​:45​:28 2015, david.warring wrote​:

Correct to test case, (say in wrong position)​:

class C {
has $!foo;
method foo is rw {
say "foo";
$!foo;
}

has $\!bar;
method bar is rw \{
    say "proxy new";

    Proxy\.new\(
        FETCH => sub \($\) \{
            say "bar fetch";
            $\!bar;
        \},
        STORE => sub \($, $v\) \{
            say "bar store";
            $\!bar = $v;
        \},
    \);
\}

}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

On Sat Oct 31 12​:09​:05 2015, david.warring wrote​:

Consider the following, which should be a simple and conventional use
of Perl 6 Proxy objects​:

class C {
has $!foo;
method foo is rw {
say "foo";
$!foo;
}

has $!bar;
method bar is rw {
Proxy.new(
say "proxy new";
FETCH => sub ($) {
say "bar fetch";
$!bar
},
STORE => sub ($, $v) {
say "bar store";
$!bar = $v;
},
);
}
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

OUTPUT​:

FETCHES
foo
proxy new
bar fetch
bar fetch
bar fetch
STORES
foo
proxy new
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar store

===================
In the above example, the bar proxy is called 10x whereas foo is
called twice.

In particular, the proxy FETCH is called 7X to do a simple increment.

I'm raising this because this is the 'hot path' in projects such as
https://github.com/p6-pdf/perl6-PDF-Tools.

Would like to see this reduced, if possible.

@p6rt
Copy link
Author

p6rt commented Apr 23, 2016

From @MadcapJake

MadcapJake> m​: class N { method text { return Proxy.new​: FETCH => method () { say 'fetch​: ', ++$ }, STORE => method ($new) { say "$new​: ", ++$ } } }; N.text; N.text = 'blah';
camelia> rakudo-moar b3d816​: OUTPUT«fetch​: 1␤fetch​: 2␤fetch​: 3␤fetch​: 4␤fetch​: 5␤blah​: 1␤»

On Sat Oct 31 12​:09​:05 2015, david.warring wrote​:

Consider the following, which should be a simple and conventional use
of Perl 6 Proxy objects​:

class C {
has $!foo;
method foo is rw {
say "foo";
$!foo;
}

has $!bar;
method bar is rw {
Proxy.new(
say "proxy new";
FETCH => sub ($) {
say "bar fetch";
$!bar
},
STORE => sub ($, $v) {
say "bar store";
$!bar = $v;
},
);
}
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

OUTPUT​:

FETCHES
foo
proxy new
bar fetch
bar fetch
bar fetch
STORES
foo
proxy new
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar store

===================
In the above example, the bar proxy is called 10x whereas foo is
called twice.

In particular, the proxy FETCH is called 7X to do a simple increment.

I'm raising this because this is the 'hot path' in projects such as
https://github.com/p6-pdf/perl6-PDF-Tools.

Would like to see this reduced, if possible.

@p6rt
Copy link
Author

p6rt commented Sep 6, 2018

From @dwarring

On Fri, 22 Apr 2016 21​:35​:33 -0700, madcap.russo+p6@​gmail.com wrote​:

MadcapJake> m​: class N { method text { return Proxy.new​: FETCH =>
MadcapJake> method () { say 'fetch​: ', ++$ }, STORE => method ($new) {
MadcapJake> say "$new​: ", ++$ } } }; N.text; N.text = 'blah';
camelia> rakudo-moar b3d816​: OUTPUT«fetch​: 1␤fetch​: 2␤fetch​: 3␤fetch​:
camelia> 4␤fetch​: 5␤blah​: 1␤»

On Sat Oct 31 12​:09​:05 2015, david.warring wrote​:

Consider the following, which should be a simple and conventional use
of Perl 6 Proxy objects​:

class C {
has $!foo;
method foo is rw {
say "foo";
$!foo;
}

has $!bar;
method bar is rw {
Proxy.new(
say "proxy new";
FETCH => sub ($) {
say "bar fetch";
$!bar
},
STORE => sub ($, $v) {
say "bar store";
$!bar = $v;
},
);
}
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

OUTPUT​:

FETCHES
foo
proxy new
bar fetch
bar fetch
bar fetch
STORES
foo
proxy new
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar fetch
bar store

===================
In the above example, the bar proxy is called 10x whereas foo is
called twice.

In particular, the proxy FETCH is called 7X to do a simple increment.

I'm raising this because this is the 'hot path' in projects such as
https://github.com/p6-pdf/perl6-PDF-Tools.

Would like to see this reduced, if possible.

Related is a failed attempt to subclass Proxy with a caching version​:

my class ProxyCache is Proxy {
  has int $!cached = 0;
  has $!val;

  method FETCH {
warn "cache fetch";
  if $!cached {
  $!val;
  }
  else {
  $!cached = 1;
  $!val := callsame;
  }
  }
  method STORE($!val) {
warn "cache store";
  $!cached = 1;
  nextsame;
  }
}

class C {
  has $!foo;
  method foo is rw {
  say "foo";
  $!foo;
  }

  has $!bar;
  method bar is rw {
  ProxyCache.new(
  FETCH => sub ($) {
  say "bar fetch";
  $!bar
  },
  STORE => sub ($, $v) {
  say "bar store";
  $!bar = $v;
  },
  );
  }
}

my $c = C.new;
say "FETCHES";
$c.foo;
$c.bar;
say "STORES";
$c.foo++;
$c.bar++;

But no luck. My caching methods aren't called. Output is unchanged.

@p6rt p6rt added the perf label Jan 5, 2020
@JJ
Copy link

JJ commented May 30, 2020

You can't apparently not subclass Proxy, according to #5911

@JJ
Copy link

JJ commented May 30, 2020

This has become now:

m: class N { method text { return-rw Proxy.new: FETCH => method () { say 'fetch​: ', ++$ },STORE => method ($new) { say "$new​: ", ++$ } } }; N.text; N.text = 'blah';
# OUTPUT: «fetch​: 1␤fetch​: 2␤fetch​: 3␤blah​: 1␤»

Still the same error, though. It's fetching 3 times.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants