Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-11-07 Thread Dik Takken
On 05-11-19 10:46, Dmitry Stogov wrote:
> I'm currently working on attempt of speculative optimizations based on 
> run-time feedback, and the results might change the whole picture a bit.

That looks like yet another impressive bit of work. It would be very
interesting to see some preliminary results when you're ready to share them.

Regards,
Dik Takken

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-11-05 Thread Dmitry Stogov
Hi Dik,

On 11/3/19 12:44 AM, Dik Takken wrote:
> On 25-10-19 12:22, Nikita Popov wrote:
>> For reference, here are the results I get with/without JIT:
>> https://gist.github.com/nikic/2a2d363fffaa3aeb251da976f0edbc33
> 
> I toyed a bit with the benchmark script (union_bench.php) as well and
> wanted to share some observations. First of all I noticed the benchmark
> script has a typo on line 90 where it is calling the wrong function. It
> should read:
> 
>func6(1, 2, 3, 4, 5);
> 
> When running the corrected script I see that adding 5 argument type
> checks and a return type check cause almost 4x slowdown. My results
> (with opcache / jit):
> 
> func($a,$b,$c,$d,$e)   0.6800.583
> func(int $a,$b,$c,$d,$e): int  2.1062.009

Thanks for catching this. At least, now I see 2 times slowdown without 
JIT, that I expected, but didn't see.

func($a,$b,$c,$d,$e)   1.7461.555
func(int $a,$b,$c,$d,$e): int  3.6473.455

JIT will able to eliminate type checks only if it exactly knows the 
called function at caller site. Unfortunately, this is quite rare case, 
because the functions may be declared in different files, OOP, type 
variance, etc.

> 
> However, this appears to be entirely due to the return type check
> lacking a JIT implementation, as pointed out by Nikita. Adding one more
> test to the benchmark shows this nicely:
> 
> func($a,$b,$c,$d,$e)   0.6750.575
> func(int $a,$b,$c,$d,$e)   0.5740.475
> func(int $a,$b,$c,$d,$e): int  2.1062.009
> 
> Now we can see that the argument type hint actually improves
> performance, I guess due to it narrowing down the number of possible
> types that need to be considered for the function arguments.
> 
> Union types allow for more accurate type hinting as well as type hinting
> in places where this is currently not possible. As a result union types
> can be used to obtain performance gains. As an example, consider the
> case where the return type hint matches the type information that
> opcache has inferred about the variable that is returned. In that case,
> the return type check is optimized away. Let us try and leverage union
> types to make this happen. From the benchmark script we take func6:
> 
>function func6(int $a, int $b, int $c, int $d, int $e) : int {
>return $a + $b + $c + $d + $e;
>}
> 
> and adjust it to read:
> 
>function func6(int $a, int $b, int $c, int $d, int $e) : int|float {
>return $a + $b + $c + $d + $e;
>}
> 
> Now the return type hint matches what opcache infers the result of the
> expression will be and the cost of return type checking disappears
> completely:
> 
> func($a,$b,$c,$d,$e) 0.6630.568
> func(int $a,$b,$c,$d,$e) 0.5740.475
> func(int $a,$b,$c,$d,$e): int|float  0.5610.466
> 
> Then, on to another observation. The SSA forms currently produced by
> opcache show union types like string|int. This suggests that opcache
> supports union types for type inference already. It explains why opcache
> can nicely optimize type checks away even when union types are used.
> 
> This is not true for unions of classes though. A union type like int|Foo
> copies into the SSA form just fine while Foo|Bar becomes 'object'. Code
> like this:
> 
>class Foo {}
>class Bar {}
> 
>function func(): Foo|Bar {
>return new Foo();
>}
> 
>func();
> 
> produces the following SSA form:
> 
>func: ; (lines=4, args=0, vars=0, tmps=1, ssa_vars=2, no_loops)
>; (before dfa pass)
>; /php-src/sapi/cli/test.php:6-8
>; return  [object]
>BB0: start exit lines=[0-3]
>; level=0
>#0.V0 [object (Foo)] = NEW 0 string("Foo")
>DO_FCALL
>VERIFY_RETURN_TYPE #0.V0 [object (Foo)] -> #1.V0 [object]
>RETURN #1.V0 [object]
> 
> which will still perform a return type check even though the return type
> hint matches the actual type of the variable. Apparently the union type
> support in opcache is present but incomplete.
> So, while union types can incur higher type checking cost they also
> provide more powerful means to help type inference and improve
> performance. As opcache improves over time I think we can expect the
> cost to decrease while the gain increases. Or am I too optimistic here?

In my experience, static optimizations are not able to eliminate most 
type checks in PHP. Probably, if we developed more complete type-system 
and used type declaration everywhere we could achieve better results.
Introducing more type checks and more complex rules will increase 
run-time overhead.

I'm currently working on attempt of speculative optimizations based on 
run-time feedback, and the results might change the whole picture a bit.

Anyway, I'm especially against of mixing multiple classes in unions, not 
because of performance, but because of complex rules of method 
inheritance compatibility checks in 

Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-11-02 Thread Dik Takken
On 25-10-19 12:22, Nikita Popov wrote:
> For reference, here are the results I get with/without JIT:
> https://gist.github.com/nikic/2a2d363fffaa3aeb251da976f0edbc33

I toyed a bit with the benchmark script (union_bench.php) as well and
wanted to share some observations. First of all I noticed the benchmark
script has a typo on line 90 where it is calling the wrong function. It
should read:

  func6(1, 2, 3, 4, 5);

When running the corrected script I see that adding 5 argument type
checks and a return type check cause almost 4x slowdown. My results
(with opcache / jit):

func($a,$b,$c,$d,$e)   0.6800.583
func(int $a,$b,$c,$d,$e): int  2.1062.009

However, this appears to be entirely due to the return type check
lacking a JIT implementation, as pointed out by Nikita. Adding one more
test to the benchmark shows this nicely:

func($a,$b,$c,$d,$e)   0.6750.575
func(int $a,$b,$c,$d,$e)   0.5740.475
func(int $a,$b,$c,$d,$e): int  2.1062.009

Now we can see that the argument type hint actually improves
performance, I guess due to it narrowing down the number of possible
types that need to be considered for the function arguments.

Union types allow for more accurate type hinting as well as type hinting
in places where this is currently not possible. As a result union types
can be used to obtain performance gains. As an example, consider the
case where the return type hint matches the type information that
opcache has inferred about the variable that is returned. In that case,
the return type check is optimized away. Let us try and leverage union
types to make this happen. From the benchmark script we take func6:

  function func6(int $a, int $b, int $c, int $d, int $e) : int {
  return $a + $b + $c + $d + $e;
  }

and adjust it to read:

  function func6(int $a, int $b, int $c, int $d, int $e) : int|float {
  return $a + $b + $c + $d + $e;
  }

Now the return type hint matches what opcache infers the result of the
expression will be and the cost of return type checking disappears
completely:

func($a,$b,$c,$d,$e) 0.6630.568
func(int $a,$b,$c,$d,$e) 0.5740.475
func(int $a,$b,$c,$d,$e): int|float  0.5610.466

Then, on to another observation. The SSA forms currently produced by
opcache show union types like string|int. This suggests that opcache
supports union types for type inference already. It explains why opcache
can nicely optimize type checks away even when union types are used.

This is not true for unions of classes though. A union type like int|Foo
copies into the SSA form just fine while Foo|Bar becomes 'object'. Code
like this:

  class Foo {}
  class Bar {}

  function func(): Foo|Bar {
  return new Foo();
  }

  func();

produces the following SSA form:

  func: ; (lines=4, args=0, vars=0, tmps=1, ssa_vars=2, no_loops)
  ; (before dfa pass)
  ; /php-src/sapi/cli/test.php:6-8
  ; return  [object]
  BB0: start exit lines=[0-3]
  ; level=0
  #0.V0 [object (Foo)] = NEW 0 string("Foo")
  DO_FCALL
  VERIFY_RETURN_TYPE #0.V0 [object (Foo)] -> #1.V0 [object]
  RETURN #1.V0 [object]

which will still perform a return type check even though the return type
hint matches the actual type of the variable. Apparently the union type
support in opcache is present but incomplete.

So, while union types can incur higher type checking cost they also
provide more powerful means to help type inference and improve
performance. As opcache improves over time I think we can expect the
cost to decrease while the gain increases. Or am I too optimistic here?

Regards,
Dik Takken

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-30 Thread Dik Takken
On 30-10-19 22:22, Mark Randall wrote:
> I don't know if this post has been accidentally sitting in an outbox for
> a bit too long and has just sent, but the vote has been underway for a
> while now.

Thanks, I simply missed that. :)

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-30 Thread Mark Randall

On 30/10/2019 21:11, Dik Takken wrote:

Perhaps it might be an idea to wait a little before starting the vote to
show the cost going down as more optimization work is done. Just to
build confidence with those who are hesitant to give it their approval.


I don't know if this post has been accidentally sitting in an outbox for 
a bit too long and has just sent, but the vote has been underway for a 
while now.


It currently has more than 90% in favour with good turnout.

--
Mark Randall

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-30 Thread Dik Takken
On 25-10-19 12:22, Nikita Popov wrote:
> I do think that performance considerations are important when it comes to
> new typing features (which is why, for example, we have categorically
> rejected a "typed arrays" implementation that has to check all array
> elements), but don't see union types are particular problematic in that
> regard, beyond what we already have.

While union types barely seem to add to the cost of type checking, I
also understand the general sentiment: Type checks can be expensive,
should we really add more?

Perhaps it might be an idea to wait a little before starting the vote to
show the cost going down as more optimization work is done. Just to
build confidence with those who are hesitant to give it their approval.

Regards,
Dik Takken

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-26 Thread Benjamin Morel
>
> As they are runtime checks, would an ini setting where they can be
> completely disabled be feasible? So during development and in production
> when the performance decrease doesn't matter, I can have the full runtime
> type checking. But when absolutely needed, the checking can be disabled.



Note that I would personally never disable these checks in production, as
they may prevent potential bugs down the road, that would not have
necessarily been caught in dev.
I would rather expect PHP to bring down the cost of these checks in
production to a negligible level, as mentioned in my previous message
(static analysis and JIT).

— Benjamin

On Fri, 25 Oct 2019 at 10:09, Peter Bowyer 
wrote:

> On Thu, 24 Oct 2019 at 13:47, Rowan Tommins 
> wrote:
>
> > I think this performance impact is a real concern; PHP is the only
> language
> > I know of which implements type checks entirely at run-time in production
> > code, and we should ask ourselves if that's definitely the right
> approach.
> >
>
> As they are runtime checks, would an ini setting where they can be
> completely disabled be feasible? So during development and in production
> when the performance decrease doesn't matter, I can have the full runtime
> type checking. But when absolutely needed, the checking can be disabled.
>
> Peter
>


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-26 Thread Benjamin Morel
>
> I think this performance impact is a real concern; PHP is the only language
> I know of which implements type checks entirely at run-time in production
> code, and we should ask ourselves if that's definitely the right approach.


Would it be possible, at least in principle, to build a static analysis
> tool which could prove that certain type checks would never fail, and prime
> OpCache with code that leaves them out? As I understand it, this is how
> Dart works: the compiler only emits run-time checks for assertions it can't
> prove true by static analysis.



I was wondering the same thing, especially in the light of preloading,
where a lot of class/function definitions are known on startup.

For example, doing:

  function x(): int {}
  function y(int $foo) {}
  y(x());

Should definitely not redundantly check the type of the y() parameter, if
possible.

Also, in the case of JIT, shouldn't type hints actually *improve*
performance?

— Benjamin


On Thu, 24 Oct 2019 at 14:47, Rowan Tommins  wrote:

> Hi Dmitry,
>
> On Wed, 23 Oct 2019 at 16:43, Dmitry Stogov  wrote:
>
> > Actually, I think PHP already took wrong direction implementing "typed
> > references" and "type variance".
> > Introducing more "typing", we suggest using it, but this "typing" comes
> > with a huge cost of run-time checks.
> > From 10% (scalar type hint of argument) to 3 times (typed reference
> > assignment) performance degradation.
> > Anyone may rerun my benchmarks
> > https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9
> >
>
>
> I think this performance impact is a real concern; PHP is the only language
> I know of which implements type checks entirely at run-time in production
> code, and we should ask ourselves if that's definitely the right approach.
>
> Would it be possible, at least in principle, to build a static analysis
> tool which could prove that certain type checks would never fail, and prime
> OpCache with code that leaves them out? As I understand it, this is how
> Dart works: the compiler only emits run-time checks for assertions it can't
> prove true by static analysis.
>
> The simpler idea I had in this area was caching what type checks a value
> had passed, either on each zval or perhaps just at the class level, so that
> checking the same type again would be much faster, even if it was a complex
> union with multiple interfaces.
>
> Regards,
> --
> Rowan Tommins
> [IMSoP]
>


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-25 Thread Dmitry Stogov
Removing references would be great for implementation  , but this doesn't look 
realistic in context of PHP language.
HHVM already made steps into this direction with Hack.

Thanks. Dmitry.


From: Dan Ackroyd 
Sent: Friday, October 25, 2019 18:40
To: Dmitry Stogov 
Cc: Nikita Popov ; PHP internals 
Subject: Re: [PHP-DEV] Re: [RFC] Union Types v2

On Fri, 25 Oct 2019 at 14:27, Dmitry Stogov  wrote:
>
> // <= 100 type checks on a single assignment

That code contains a reference that is re-used 100 times.

I personally prefer not to use references at all, but if people do
want to use them, we could put a note that references are bad for
performance when used with types. People can then choose between:

* using types, and not references for good performance.
* using references, and not types for good performance.
* using references and types, and getting slightly less good performance.

> I don't like to complicate the language with features
> that shouldn't be often used,

Can we start the discussion about deprecating references in PHP 8 then?

Very few people are writing code using them currently, and they seem
to cause quite a lot of confusion, judging by the bug reports about
them. If you're also saying that they are making it difficult to write
performant PHP, that seems to be a good argument for looking at what
would be needed to be done to remove them.

cheers
Dan
Ack


CAUTION: This email originated from outside of the organization. Do not click 
on links or open attachments unless you recognize the sender and know the 
content is safe.


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-25 Thread Dan Ackroyd
On Fri, 25 Oct 2019 at 14:27, Dmitry Stogov  wrote:
>
> // <= 100 type checks on a single assignment

That code contains a reference that is re-used 100 times.

I personally prefer not to use references at all, but if people do
want to use them, we could put a note that references are bad for
performance when used with types. People can then choose between:

* using types, and not references for good performance.
* using references, and not types for good performance.
* using references and types, and getting slightly less good performance.

> I don't like to complicate the language with features
> that shouldn't be often used,

Can we start the discussion about deprecating references in PHP 8 then?

Very few people are writing code using them currently, and they seem
to cause quite a lot of confusion, judging by the bug reports about
them. If you're also saying that they are making it difficult to write
performant PHP, that seems to be a good argument for looking at what
would be needed to be done to remove them.

cheers
Dan
Ack

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-25 Thread Dmitry Stogov
Hi Nikita,

in your results, assignment to typed reference is ~3 time slower without JIT 
and ~10 times slower with JIT.
But this is not the worst case. I can simple craft a script where single 
assignment will lead to  hundreds type checks.

ref =& $ref;
   }
}
for ($i = 0; $i < 100; $i++) {
   $a[$i] = new A($ref);
}
$ref = new A; // <= 100 type checks on a single assignment
?>

In case we add union types, we can make 200, 300 check...

The worst thing, for me, is variance together with union of multiple class 
types.
Each such method compatibility check is going to be a puzzle solving, and I 
imagine people, proud of writing "complex pearls".

My main concern, I don't like to complicate the language with features that 
shouldn't be often used, and I don't like to complicate implementation and 
reduce performance without real need.

In my opinion, union of standard types and single class or null should be 
enough for most typing use cases.

Thanks. Dmitry.

From: Nikita Popov 
Sent: Friday, October 25, 2019 13:22
To: Dmitry Stogov 
Cc: PHP internals 
Subject: Re: [PHP-DEV] Re: [RFC] Union Types v2

On Wed, Oct 23, 2019 at 5:42 PM Dmitry Stogov 
mailto:dmi...@zend.com>> wrote:
Hi Nikita,

I checked the Union Type implementation, and it more or less good. I mean, it 
implements the RFC in almost the best way.
However, as I don't like the RFC itself. Especially, unions of multiple classes 
and interference with type variance, I'll vote against this.

Actually, I think PHP already took wrong direction implementing "typed 
references" and "type variance".
Introducing more "typing", we suggest using it, but this "typing" comes with a 
huge cost of run-time checks.
>From 10% (scalar type hint of argument) to 3 times (typed reference 
>assignment) performance degradation.
Anyone may rerun my benchmarks 
https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9

Thanks. Dmitry.

For reference, here are the results I get with/without JIT: 
https://gist.github.com/nikic/2a2d363fffaa3aeb251da976f0edbc33

I think that union types don't really change much in terms of the performance 
calculus of type checking, because type checking is equally fast (or slow) for 
a single scalar type, and 5 different scalar types: they are all handled in a 
single bit check. The only case that is indeed somewhat slow is if multiple 
class types are used in the union, because we actually have to check each one 
until we find a match. I do hope that having unions with a large number of 
classes will not be common.

Generally, this area could use some more optimization from the implementation 
side. I spent a bit of time yesterday optimizing how we perform instanceof 
checks (the implementation was quite inefficient, especially for interfaces), 
which had a large positive impact on class type checks. There's more low 
hanging fruit like this, for example verify_return_type has no JIT 
implementation yet (which is why with JIT simple arg type checks have nearly 
zero overhead, while return type checks have a large overhead). Assignments to 
typed properties are also badly optimized, because everything is punted to the 
slow path, while we should be able to handle the simple cases with just one 
extra bit check, without going through the complex implementation that deals 
with things like weak typing coercions.

I do think that performance considerations are important when it comes to new 
typing features (which is why, for example, we have categorically rejected a 
"typed arrays" implementation that has to check all array elements), but don't 
see union types are particular problematic in that regard, beyond what we 
already have.

Nikita


From: Dmitry Stogov mailto:dmi...@zend.com>>
Sent: Tuesday, October 22, 2019 15:38
To: Nikita Popov mailto:nikita....@gmail.com>>; PHP 
internals mailto:internals@lists.php.net>>
Subject: Re: [PHP-DEV] Re: [RFC] Union Types v2

Hi Nikita,

Can you please give me one/two days, before starting the voting, for 
implementation review (at least until October 25),

Thanks. Dmitry.


From: Nikita Popov mailto:nikita@gmail.com>>
Sent: Tuesday, October 22, 2019 12:36
To: PHP internals mailto:internals@lists.php.net>>
Subject: [PHP-DEV] Re: [RFC] Union Types v2

On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov 
mailto:nikita@gmail.com>> wrote:

> Hi internals,
>
> I'd like to start the discussion on union types again, with a new proposal:
>
> Pull Request: https://github.com/php/php-rfcs/pull/1
> Rendered Proposal:
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
>
> As an experiment, I'm submitting this RFC as a GitHub pull request, to
> evaluate whether this might be a better medium for RFC proposals in the
> future. 

Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-25 Thread Nikita Popov
On Wed, Oct 23, 2019 at 5:42 PM Dmitry Stogov  wrote:

> Hi Nikita,
>
> I checked the Union Type implementation, and it more or less good. I mean,
> it implements the RFC in almost the best way.
> However, as I don't like the RFC itself. Especially, unions of multiple
> classes and interference with type variance, I'll vote against this.
>
> Actually, I think PHP already took wrong direction implementing "typed
> references" and "type variance".
> Introducing more "typing", we suggest using it, but this "typing" comes
> with a huge cost of run-time checks.
> From 10% (scalar type hint of argument) to 3 times (typed reference
> assignment) performance degradation.
> Anyone may rerun my benchmarks
> https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9
>
> Thanks. Dmitry.
>

For reference, here are the results I get with/without JIT:
https://gist.github.com/nikic/2a2d363fffaa3aeb251da976f0edbc33

I think that union types don't really change much in terms of the
performance calculus of type checking, because type checking is equally
fast (or slow) for a single scalar type, and 5 different scalar types: they
are all handled in a single bit check. The only case that is indeed
somewhat slow is if multiple class types are used in the union, because we
actually have to check each one until we find a match. I do hope that
having unions with a large number of classes will not be common.

Generally, this area could use some more optimization from the
implementation side. I spent a bit of time yesterday optimizing how we
perform instanceof checks (the implementation was quite inefficient,
especially for interfaces), which had a large positive impact on class type
checks. There's more low hanging fruit like this, for example
verify_return_type has no JIT implementation yet (which is why with JIT
simple arg type checks have nearly zero overhead, while return type checks
have a large overhead). Assignments to typed properties are also badly
optimized, because everything is punted to the slow path, while we should
be able to handle the simple cases with just one extra bit check, without
going through the complex implementation that deals with things like weak
typing coercions.

I do think that performance considerations are important when it comes to
new typing features (which is why, for example, we have categorically
rejected a "typed arrays" implementation that has to check all array
elements), but don't see union types are particular problematic in that
regard, beyond what we already have.

Nikita

--
> *From:* Dmitry Stogov 
> *Sent:* Tuesday, October 22, 2019 15:38
> *To:* Nikita Popov ; PHP internals <
> internals@lists.php.net>
> *Subject:* Re: [PHP-DEV] Re: [RFC] Union Types v2
>
> Hi Nikita,
>
> Can you please give me one/two days, before starting the voting, for
> implementation review (at least until October 25),
>
> Thanks. Dmitry.
>
> ----------
> *From:* Nikita Popov 
> *Sent:* Tuesday, October 22, 2019 12:36
> *To:* PHP internals 
> *Subject:* [PHP-DEV] Re: [RFC] Union Types v2
>
> On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:
>
> > Hi internals,
> >
> > I'd like to start the discussion on union types again, with a new
> proposal:
> >
> > Pull Request: https://github.com/php/php-rfcs/pull/1
> > Rendered Proposal:
> >
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
> >
> > As an experiment, I'm submitting this RFC as a GitHub pull request, to
> > evaluate whether this might be a better medium for RFC proposals in the
> > future. It would be great if we could keep the discussion to the GitHub
> > pull request for the purpose of this experiment (keep in mind that you
> can
> > also create comments on specific lines in the proposal, not just the
> > overall discussion thread!) Of course, you can also reply to this mail
> > instead. The final vote will be held in the wiki as usual.
> >
> > Relatively to the previous proposal by Bob (
> > https://wiki.php.net/rfc/union_types), I think the main differences in
> > this proposal are:
> >  * Updated to specify interaction with new language features, like full
> > variance and property types.
> >  * Updated for the use of the ?Type syntax rather than the Type|null
> > syntax.
> >  * Only supports "false" as a pseudo-type, not "true".
> >  * Slightly simplified semantics for the coercive typing mode.
> >
> > Regards,
> > Nikita
> >
>
> An implementation of this proposal is now available at
> https://github.com/php/php-src/pull/4838. As the implementation didn't
> turn
> up any new issues, I think it's time to move this RFC forward to voting.
>
> Nikita
>
>
> CAUTION: This email originated from outside of the organization. Do not
> click on links or open attachments unless you recognize the sender and know
> the content is safe.
>


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-25 Thread Peter Bowyer
On Thu, 24 Oct 2019 at 13:47, Rowan Tommins  wrote:

> I think this performance impact is a real concern; PHP is the only language
> I know of which implements type checks entirely at run-time in production
> code, and we should ask ourselves if that's definitely the right approach.
>

As they are runtime checks, would an ini setting where they can be
completely disabled be feasible? So during development and in production
when the performance decrease doesn't matter, I can have the full runtime
type checking. But when absolutely needed, the checking can be disabled.

Peter


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-24 Thread Mark Randall

On 24/10/2019 13:47, Rowan Tommins wrote:

The simpler idea I had in this area was caching what type checks a value
had passed, either on each zval or perhaps just at the class level, so that
checking the same type again would be much faster, even if it was a complex
union with multiple interfaces.


Last night I was playing about with caching the last passed interface as 
part of the instanceof_function.


https://gist.github.com/marandall/38d7dba6600889d897f2c8fc57532f31

When used in the likes of loops which are performing the same check over 
and over, it yields about a 18% increase when using a 3 layer deep 
nested interface.


It currently just stores a cache of the last match in the class entry so 
it would hit as many uses as possible.


For T_INSTANCEOF it could potentially use an extended cache slot to 
store a reference to it (would need expanding out into a separate struct 
as the cache slot is already used for converting the static name to a ce).


I'm less clear about how we could handle it for everything else, like 
parameter type validation. The underlying implementation already seems 
pretty well optimized so I'm not sure where a performance penalty is to 
be found.


--
Mark Randall

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-24 Thread Rowan Tommins
Hi Dmitry,

On Wed, 23 Oct 2019 at 16:43, Dmitry Stogov  wrote:

> Actually, I think PHP already took wrong direction implementing "typed
> references" and "type variance".
> Introducing more "typing", we suggest using it, but this "typing" comes
> with a huge cost of run-time checks.
> From 10% (scalar type hint of argument) to 3 times (typed reference
> assignment) performance degradation.
> Anyone may rerun my benchmarks
> https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9
>


I think this performance impact is a real concern; PHP is the only language
I know of which implements type checks entirely at run-time in production
code, and we should ask ourselves if that's definitely the right approach.

Would it be possible, at least in principle, to build a static analysis
tool which could prove that certain type checks would never fail, and prime
OpCache with code that leaves them out? As I understand it, this is how
Dart works: the compiler only emits run-time checks for assertions it can't
prove true by static analysis.

The simpler idea I had in this area was caching what type checks a value
had passed, either on each zval or perhaps just at the class level, so that
checking the same type again would be much faster, even if it was a complex
union with multiple interfaces.

Regards,
-- 
Rowan Tommins
[IMSoP]


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-23 Thread Dmitry Stogov
Hi Nikita,

I checked the Union Type implementation, and it more or less good. I mean, it 
implements the RFC in almost the best way.
However, as I don't like the RFC itself. Especially, unions of multiple classes 
and interference with type variance, I'll vote against this.

Actually, I think PHP already took wrong direction implementing "typed 
references" and "type variance".
Introducing more "typing", we suggest using it, but this "typing" comes with a 
huge cost of run-time checks.
>From 10% (scalar type hint of argument) to 3 times (typed reference 
>assignment) performance degradation.
Anyone may rerun my benchmarks 
https://gist.github.com/dstogov/fb32023e8dd55e58312ae0e5029556a9

Thanks. Dmitry.


From: Dmitry Stogov 
Sent: Tuesday, October 22, 2019 15:38
To: Nikita Popov ; PHP internals 
Subject: Re: [PHP-DEV] Re: [RFC] Union Types v2

Hi Nikita,

Can you please give me one/two days, before starting the voting, for 
implementation review (at least until October 25),

Thanks. Dmitry.


From: Nikita Popov 
Sent: Tuesday, October 22, 2019 12:36
To: PHP internals 
Subject: [PHP-DEV] Re: [RFC] Union Types v2

On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:

> Hi internals,
>
> I'd like to start the discussion on union types again, with a new proposal:
>
> Pull Request: https://github.com/php/php-rfcs/pull/1
> Rendered Proposal:
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
>
> As an experiment, I'm submitting this RFC as a GitHub pull request, to
> evaluate whether this might be a better medium for RFC proposals in the
> future. It would be great if we could keep the discussion to the GitHub
> pull request for the purpose of this experiment (keep in mind that you can
> also create comments on specific lines in the proposal, not just the
> overall discussion thread!) Of course, you can also reply to this mail
> instead. The final vote will be held in the wiki as usual.
>
> Relatively to the previous proposal by Bob (
> https://wiki.php.net/rfc/union_types), I think the main differences in
> this proposal are:
>  * Updated to specify interaction with new language features, like full
> variance and property types.
>  * Updated for the use of the ?Type syntax rather than the Type|null
> syntax.
>  * Only supports "false" as a pseudo-type, not "true".
>  * Slightly simplified semantics for the coercive typing mode.
>
> Regards,
> Nikita
>

An implementation of this proposal is now available at
https://github.com/php/php-src/pull/4838. As the implementation didn't turn
up any new issues, I think it's time to move this RFC forward to voting.

Nikita


CAUTION: This email originated from outside of the organization. Do not click 
on links or open attachments unless you recognize the sender and know the 
content is safe.


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-10-22 Thread Dmitry Stogov
Hi Nikita,

Can you please give me one/two days, before starting the voting, for 
implementation review (at least until October 25),

Thanks. Dmitry.


From: Nikita Popov 
Sent: Tuesday, October 22, 2019 12:36
To: PHP internals 
Subject: [PHP-DEV] Re: [RFC] Union Types v2

On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:

> Hi internals,
>
> I'd like to start the discussion on union types again, with a new proposal:
>
> Pull Request: https://github.com/php/php-rfcs/pull/1
> Rendered Proposal:
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
>
> As an experiment, I'm submitting this RFC as a GitHub pull request, to
> evaluate whether this might be a better medium for RFC proposals in the
> future. It would be great if we could keep the discussion to the GitHub
> pull request for the purpose of this experiment (keep in mind that you can
> also create comments on specific lines in the proposal, not just the
> overall discussion thread!) Of course, you can also reply to this mail
> instead. The final vote will be held in the wiki as usual.
>
> Relatively to the previous proposal by Bob (
> https://wiki.php.net/rfc/union_types), I think the main differences in
> this proposal are:
>  * Updated to specify interaction with new language features, like full
> variance and property types.
>  * Updated for the use of the ?Type syntax rather than the Type|null
> syntax.
>  * Only supports "false" as a pseudo-type, not "true".
>  * Slightly simplified semantics for the coercive typing mode.
>
> Regards,
> Nikita
>

An implementation of this proposal is now available at
https://github.com/php/php-src/pull/4838. As the implementation didn't turn
up any new issues, I think it's time to move this RFC forward to voting.

Nikita


CAUTION: This email originated from outside of the organization. Do not click 
on links or open attachments unless you recognize the sender and know the 
content is safe.


[PHP-DEV] Re: [RFC] Union Types v2

2019-10-22 Thread Nikita Popov
On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:

> Hi internals,
>
> I'd like to start the discussion on union types again, with a new proposal:
>
> Pull Request: https://github.com/php/php-rfcs/pull/1
> Rendered Proposal:
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
>
> As an experiment, I'm submitting this RFC as a GitHub pull request, to
> evaluate whether this might be a better medium for RFC proposals in the
> future. It would be great if we could keep the discussion to the GitHub
> pull request for the purpose of this experiment (keep in mind that you can
> also create comments on specific lines in the proposal, not just the
> overall discussion thread!) Of course, you can also reply to this mail
> instead. The final vote will be held in the wiki as usual.
>
> Relatively to the previous proposal by Bob (
> https://wiki.php.net/rfc/union_types), I think the main differences in
> this proposal are:
>  * Updated to specify interaction with new language features, like full
> variance and property types.
>  * Updated for the use of the ?Type syntax rather than the Type|null
> syntax.
>  * Only supports "false" as a pseudo-type, not "true".
>  * Slightly simplified semantics for the coercive typing mode.
>
> Regards,
> Nikita
>

An implementation of this proposal is now available at
https://github.com/php/php-src/pull/4838. As the implementation didn't turn
up any new issues, I think it's time to move this RFC forward to voting.

Nikita


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-09-23 Thread Andreas Hennings
To have any information content, a variable (or return value, or
parameter) needs to have more than one possible value.
If one of those values is TRUE, the most natural alternative value
would be FALSE.

But should this really be baked into the language?
Should really "try to be smart" here?
Isn't it better to aim for completeness and consistency, and provide a
"round" developer experience with the least amount of surprise?

The same could be asked about other restrictions, e.g. false|null.

Ideally we should have a type system with the properties of a
mathematical space of some sort.
Artificial restrictions would ruin this.
It won't be perfect, because the different types are not "symmetric".
But we can at least try to make it as consistent as possible.

Some use cases I can think of:


## Use case: true[] assoc

I like to use true[] for map-like associative arrays.
So, $map[$key] = true;
For each key, the array either has the value TRUE, or no value at all.
No need to store false values.

An extended use case might be a (tree = true|tree[]), where each leaf
would have the value true.

Does this mean we need true for parameters and return types?
It will be rare. Especially in the first case of a simple true[],
there is no point returning the value in a variable, if we not also
allow FALSE for "not found".


## Use case: Generics

However, what if the code is written in a generic way? E.g. if PHP
gets native generics one day, or some userland generics library based
on code generation.

For an iterator over true[], the return value for ->current() would be
"true|null". (I just tried, it is null and not false, see
https://3v4l.org/PvWWl).

For a generic method receiving values from the array, the parameter
type would be "true".

It would be really disappointing if a tool that attempts to give us
generics would have to work around arbitrary limitations of the typing
system.


## Use case: Variance

Imagine a base class or interface method which returns boolean for
success / failure.

We extend this method, and our implementation is always successful, so
we will always return true.
We can indicate this in the type hint.
This indicates that calling code does not need to check the return
value, it can simply assume that it was successful.

interface Operation {
  function run(): bool
}

interface SafeOperation extends Operation {
  function run(): true  // always successful.
}


## Use case: Code generation and reflection tools

I would say that for any automated tool, special cases of disallowed
types make things more complicated.
This could be tools for code generation, parsing, or some kind of
"type reflection" with type arithmetics.


## Use case: Legacy code

Finally, in some cases it is irrelevant whether the combination of
types makes sense or not.
We simply want to type-harden legacy code.


On Mon, 23 Sep 2019 at 22:15, Benjamin Morel  wrote:
>
> Hi Nikita,
>
> Thank you for your work on this, I look forward to being able to use union
> types!
>
> The one thing that bothers me a bit is introducing yet another
> inconsistency by supporting false and not true as a type. Sure, I do get
> the need for false as a valid type for historical reasons, but at the same
> time I thought it would be interesting to see if true was being used as
> well in the wild, before closing the door on it.
>
> Therefore I reviewed all Composer packages with > 1 million downloads (1211
> packages total), and here are the results:
>
> *31 packages
> 
> use at least one @var,  @param or @return containing true as a type.*
>
> - there are many illegitimate use cases, such as @return true
> 
> , @return bool|true
> ,
> @return true|false
> ,
> or even @return bool|true|false
> 
> - there are, however, quite a few potentially legitimate use cases. Among
> others:
>
> - @return true|WP_Error
> 
>  (*johnpbloch/wordpress-core*) : "True if the JSON data was passed or no
> JSON data was provided, WP_Error if invalid JSON was passed."
> - @return true|string
> 
>  (*johnpbloch/wordpress-core*) : "Returns true on success, or drop-in file
> to include."
> - 

Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-09-23 Thread Benjamin Morel
Hi Nikita,

Thank you for your work on this, I look forward to being able to use union
types!

The one thing that bothers me a bit is introducing yet another
inconsistency by supporting false and not true as a type. Sure, I do get
the need for false as a valid type for historical reasons, but at the same
time I thought it would be interesting to see if true was being used as
well in the wild, before closing the door on it.

Therefore I reviewed all Composer packages with > 1 million downloads (1211
packages total), and here are the results:

*31 packages

use at least one @var,  @param or @return containing true as a type.*

- there are many illegitimate use cases, such as @return true

, @return bool|true
,
@return true|false
,
or even @return bool|true|false

- there are, however, quite a few potentially legitimate use cases. Among
others:

- @return true|WP_Error

 (*johnpbloch/wordpress-core*) : "True if the JSON data was passed or no
JSON data was provided, WP_Error if invalid JSON was passed."
- @return true|string

 (*johnpbloch/wordpress-core*) : "Returns true on success, or drop-in file
to include."
- @return string|true

 (*php/di*) : True if compilable, string explaining why if not
- @return string|true

 (*zendframework/zend-authentication*) : True if successfull, error message
if not
- @param int|true

(*yiisoft/yii2*) : "Use 0 to indicate that..., Use a negative number to
indicate that..., Use boolean `true` to indicate that ..."
- @param callable|resource|string|true|null

(*symfony/symfony*) : "A line dumper callable, an opened stream, an output
path or true to return the dump"

Full list here

.

So although true as a type does not have the same historical background as
false, it does seem that it's being used by enough packages to be worth
considering; what do you think?

— Benjamin


Re: [PHP-DEV] Re: [RFC] Union Types v2

2019-09-18 Thread Björn Larsson

Den 2019-09-18 kl. 15:33, skrev Nikita Popov:

On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:


Hi internals,

I'd like to start the discussion on union types again, with a new proposal:

Pull Request: https://github.com/php/php-rfcs/pull/1
Rendered Proposal:
https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md

As an experiment, I'm submitting this RFC as a GitHub pull request, to
evaluate whether this might be a better medium for RFC proposals in the
future. It would be great if we could keep the discussion to the GitHub
pull request for the purpose of this experiment (keep in mind that you can
also create comments on specific lines in the proposal, not just the
overall discussion thread!) Of course, you can also reply to this mail
instead. The final vote will be held in the wiki as usual.

Relatively to the previous proposal by Bob (
https://wiki.php.net/rfc/union_types), I think the main differences in
this proposal are:
  * Updated to specify interaction with new language features, like full
variance and property types.
  * Updated for the use of the ?Type syntax rather than the Type|null
syntax.
  * Only supports "false" as a pseudo-type, not "true".
  * Slightly simplified semantics for the coercive typing mode.

Regards,
Nikita


Heads up, two weeks have passed, so this may now go to voting...

I believe relative to my original draft the main change that has happened
as a result of the discussion is the use of T1|T2|null syntax instead of
?(T1|T2) syntax for nullable types. ?T becomes an alias for T|null. People
felt fairly strongly that while ?T is a nice shorthand for a common case,
unions should use the T1|T2|null syntax that both reads better and is
already well-established from phpdoc.

I figured I should mentioned this for people who haven't been following the
GitHub thread...

Nikita



Hi Nikita,

Planned to comment on ? vs null on Github, but here it goes. Advantage
with ? syntax was in my eyes that it's clear it's not a stand-alone type or
what I should call it, but rather a "change/variant" to an existing type.

Having it stated as T1|T2|null lead it a bit in the direction of being a 
more

stand-alone type. Anyway, I'm quite happy with the proposal as it is. So
thanks for the excellent work!

r//Björn L

--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php



[PHP-DEV] Re: [RFC] Union Types v2

2019-09-18 Thread Nikita Popov
On Wed, Sep 4, 2019 at 10:26 AM Nikita Popov  wrote:

> Hi internals,
>
> I'd like to start the discussion on union types again, with a new proposal:
>
> Pull Request: https://github.com/php/php-rfcs/pull/1
> Rendered Proposal:
> https://github.com/nikic/php-rfcs/blob/union-types/rfcs/-union-types-v2.md
>
> As an experiment, I'm submitting this RFC as a GitHub pull request, to
> evaluate whether this might be a better medium for RFC proposals in the
> future. It would be great if we could keep the discussion to the GitHub
> pull request for the purpose of this experiment (keep in mind that you can
> also create comments on specific lines in the proposal, not just the
> overall discussion thread!) Of course, you can also reply to this mail
> instead. The final vote will be held in the wiki as usual.
>
> Relatively to the previous proposal by Bob (
> https://wiki.php.net/rfc/union_types), I think the main differences in
> this proposal are:
>  * Updated to specify interaction with new language features, like full
> variance and property types.
>  * Updated for the use of the ?Type syntax rather than the Type|null
> syntax.
>  * Only supports "false" as a pseudo-type, not "true".
>  * Slightly simplified semantics for the coercive typing mode.
>
> Regards,
> Nikita
>

Heads up, two weeks have passed, so this may now go to voting...

I believe relative to my original draft the main change that has happened
as a result of the discussion is the use of T1|T2|null syntax instead of
?(T1|T2) syntax for nullable types. ?T becomes an alias for T|null. People
felt fairly strongly that while ?T is a nice shorthand for a common case,
unions should use the T1|T2|null syntax that both reads better and is
already well-established from phpdoc.

I figured I should mentioned this for people who haven't been following the
GitHub thread...

Nikita