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

.WHEN #8

Closed
Xliff opened this issue Apr 12, 2019 · 13 comments
Closed

.WHEN #8

Xliff opened this issue Apr 12, 2019 · 13 comments
Assignees
Labels
language Changes to the Raku Programming Language

Comments

@Xliff
Copy link

Xliff commented Apr 12, 2019

Just to brainstorm.

Would it be possible to fill out the .WHAT, .WHERE, .WHY, .HOW, with a .WHEN?

.WHEN would store the DateTime when the variable was last defined.

Would this incur a significant amount of change in CORE.setting?
How much of a performance penalty would this incur?
How much more memory would this use?

Does this really need a use-case define? If so, I can provide a simple one:

User is tracking entries via a hash. Wants to only consider entries made within the last 5 
minutes. Instead of creating ANOTHER hash entry, can always use %h<Entry>.WHEN

Is this enough to jumpstart a conversation?

@ugexe
Copy link
Contributor

ugexe commented Apr 12, 2019

$ time perl6 -e 'class Foo { }; for 1..1000000 { Foo.new }'

real	0m0.585s
user	0m0.629s
sys	0m0.051s
$ time perl6 -e 'class Foo { has $.WHEN = now; }; for 1..1000000 { Foo.new }'

real	1m12.477s
user	1m8.057s
sys	0m4.085s

This is a bit of a naive example, but the performance implications are pronounced enough to make me think its impractical.

@AlexDaniel AlexDaniel added the language Changes to the Raku Programming Language label Apr 12, 2019
@AlexDaniel
Copy link
Member

What about creating a module “WHEN::Hash” for those who need it instead of imposing the overhead on everyone?

BTW, @jnthn can you publish your document about language design principles?

@Xliff
Copy link
Author

Xliff commented Apr 12, 2019

$ time perl6 -e 'class Foo { }; for 1..1000000 { Foo.new }'

real	0m0.585s
user	0m0.629s
sys	0m0.051s
$ time perl6 -e 'class Foo { has $.WHEN = now; }; for 1..1000000 { Foo.new }'

real	1m12.477s
user	1m8.057s
sys	0m4.085s

This is a bit of a naive example, but the performance implications are pronounced enough to make me think its impractical.

Yes. Yes, that is. AlexDaniel's suggestion about a module is well taken, but if something like this can be boiled down to maybe 0.7s, would it be worthwhile? Does nqp have a native version of .now -- one that returns POSIX seconds? Might be better to benchmark that, instead.

@Xliff Xliff closed this as completed Apr 12, 2019
@Xliff Xliff reopened this Apr 12, 2019
@Xliff
Copy link
Author

Xliff commented Apr 12, 2019

Well, this is unexpected!

$ time perl6 -e 'use nqp; class Foo { }; for 1..1000000 { Foo.new }'
real    0m0.863s
user    0m0.944s
sys     0m0.061s
$ time perl6 -e 'use nqp; class Foo { has $.WHEN = nqp::time_n(); }; for 1..1000000 { Foo.new }'

real    0m0.770s
user    0m0.832s
sys     0m0.081s

(Caching?)

Of course, it really isn't that simple. This would occur at STORE, not new()

@ugexe
Copy link
Contributor

ugexe commented Apr 12, 2019

A DateTime or Instant is going to take longer to create than a Num

EDIT: actually I didn't notice it was faster

@Xliff
Copy link
Author

Xliff commented Apr 12, 2019

A DateTime or Instant is going to take longer to create than a Num

Yes, but all I really need is a num. Yes, the original message was about DateTime, but posix_t is good enough and still accomplishes the goal.

EDIT: That was why it was unexpected =)

@ugexe
Copy link
Contributor

ugexe commented Apr 12, 2019

$ time perl6 -e 'use nqp; class Foo { }; for 1..1000000 { Foo.new }'

real	0m0.675s
user	0m0.700s
sys	0m0.056s
$ time perl6 -e 'use nqp; class Foo { has $.WHEN = nqp::time_n(); }; for 1..1000000 { Foo.new }'

real	0m5.542s
user	0m2.810s
sys	0m2.790s

@Xliff
Copy link
Author

Xliff commented Apr 12, 2019

We could do this all day. I guess I need to reboot and do this outside a VM, because this just doesn't make sense!

$ time perl6 -e 'use nqp; class Foo { }; for 1..10000000 { Foo.new }'
real    0m5.941s
user    0m6.019s
sys     0m0.052s
$ time perl6 -e 'use nqp; class Foo { has $.WHEN = nqp::time_n(); }; for 1..10000000 { Foo.new }'

real    0m4.874s
user    0m4.980s
sys     0m0.040s

Also, am doing this on Linux kernel v5.

$ uname -a
Linux cbwood-VirtualBox2 5.0.0-8-generic #9-Ubuntu SMP Tue Mar 12 21:58:11 UTC 2019 x86_64 x86_64 x86_64 GNU/Linux

@jnthn
Copy link
Contributor

jnthn commented Apr 12, 2019

First, about the discrepancy: it turns out there's a performance bug lurking here. For an object with attributes, we would generate a BUILDALL. When the object had no attributes, we should have generated an empty, shared, one, but due to a bug did not do so. I've fixed that now.

The dynamic optimizer is getting increasingly sophisticated, and benchmarks like these are liable to prove little. Having fixed the BUILDALL production bug above, it turns out that:

class Foo { }; for 1..10000000 { Foo.new }

Has the object allocation optimized out completely thanks to escape analysis and resultant optimizations, meaning after optimization it turns into an empty loop body. It's not yet sophisticated enough to do the same trick for an object with an attribute that is initialized but then never read, but that's only a matter of time; it already knows that floor_n is pure if unused, so once the escape analyzer is smart enough, that'll turn into another benchmark proving nothing. :-)

As to the WHEN feature, I think that belongs in module space; getting the current timestamp is certainly not free, and storing it is not in the slightest bit free either. Imagine an array with a million elements; that's 8 megabytes worth of storage on timestamps for all of the elements, and it's difficult to optimize such things out. With ordinary lexicals it's easier, but that's also the case where it has the least storage cost. So it's not just a time issue (though that is an issue), but also a memory one.

All the same, I'm glad you opened the issue, because it led to a performance bug being fixed.

@AlexDaniel I can look into cleaning up and publishing such a document, but I'm not immediately sure where to put it; any suggestions?

@AlexDaniel
Copy link
Member

@AlexDaniel I can look into cleaning up and publishing such a document, but I'm not immediately sure where to put it; any suggestions?

roast/docs/, and please take a look at this existing document: Policy For Implementation of New Features

@AlexDaniel
Copy link
Member

To clarify, we will of course link to it from this repo too (from the issue template), but roast seems to be a more fitting place for it right now.

@AlexDaniel
Copy link
Member

And to clarify even more, yes, such documents can be added to this repo too (by going through the whole process), but currently I don't see any good reason to do that. @jnthn if you feel like waiting for all reviewers to approve what's written in that upcoming document, then surely feel free to follow the process in this repo. Otherwise you can have a document that you'd be able to tweak at any time, which IMO makes more sense.

@Xliff
Copy link
Author

Xliff commented Apr 13, 2019

Well, module space it is. Thanks, everyone!

Any suggestions for naming?

@Xliff Xliff closed this as completed Apr 13, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
language Changes to the Raku Programming Language
Projects
None yet
Development

No branches or pull requests

4 participants