-
Notifications
You must be signed in to change notification settings - Fork 240
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
Introduced and fixed CachedDoubler behaviour in order to reduce memor… #420
Introduced and fixed CachedDoubler behaviour in order to reduce memor… #420
Conversation
d83ec6f
to
d9e6ed6
Compare
d9e6ed6
to
aba3a3a
Compare
🎉 tests are now green. |
@everzet @stof @ciaranmcnulty have you had the change to check this? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This would need some functional tests proving that 2 different doubles don't get considered as equal when matching arguments and so on. I'm not confident at all that things keep working currently.
|
||
parent::registerClassPatch($patch); | ||
} | ||
private static $classes = array(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it really be static ? Registering different class patches in a different instance must not reusable the old class definition (and that's why registerClassPatch
was resetting it)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd say that the PHP engine already has a set of registered classes: if we can do a lookup via hash name (class_exists($hash, false)
) that should be enough
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Ocramius I can modify this but this PR seems to be "sleepy" and no one seems to care to get rid of that memory leak.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Attention has been drawn here from Roave/no-leaks#14 ;-)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I read the thread.
I mean, if neither @stof nor @ciaranmcnulty provide their feeback, following with a possible merge, this PR will stuck here forever.
I know that everybody is busy and this is OSS, but having those kind of feedback (like yours that is only an enhancement because I feel it doesn't really change the sense of this PR) is crucial to move to merging direction.
I can try in the following hours to make your fix but @stof was worried about other kind of issues (read below) not related to staticness of class hashes.
@stof instances are different whereas class definitios are the same. I've tested this patch against our 6000 test suite and all runs perfectly. I can - for sure - try those kind of tests when I have free time in these upcoming weeks.
That's a doubt I had. So you can confirm that, in some situation, same class could be "patched" in a different manner? WDYT? |
@DonCallisto that fact that we allow registering patchers in the Doubler instance means that 2 instances might have different patchers. |
@stof just some basic considerations here and there before work on this solution. To keep a simple design and in order to prevent iteraring two times on One final note: how would you test this in a functional fashion? I've broke my head thinking about this but I'm currently to a dead end. If you give me a feedback on the first consideration and a pointer for the latter, I will be happy to work on this. |
Moreover, thinking about a functional implementation, I’m still not sure we need that kind of test. I mean, this patch will change only the way class definitions are created, not the instances. Am I missing something? |
Maybe another option is to create a
WDYT? |
@DonCallisto what is important is not the list of applied patches (which could not be determined to build the cache key, as you would still have to create the class and then discard it), but the list of registered patchers. |
@stof whereas the idea behind applied/registered patch is not clear to me
(that's not true as we create the class after it is patched) and
here there's still not instances, only definitions I think that's fine to build with registered patches anyway because same class, with same interface and same registered patchers in the doubler will produce the same code. That means that there's no way for the same class to have applied one patch in a situation and not to be applied in other (unless the patch isn't registered, of course). I've implemented this fix in a separate commit. I'm still writing some spec tests (as stated before, I don't think we need functional tests for this as we producing class definitions, not instances) to cover all the possibilities (permutation of same/different class, same/different/no interfaces, same/different/no patches). Do it LGTY? |
Having to call the parent logic to create the class was what I was talking about.
this sentence is talking about instances of the doubler, not instance of the double.
Last time I tried enabling the CachedDoubler in my tests, the argument matching (when using a double as argument in a method of another double) broke for some cases, because 2 doubles of the same class were now considered the same for argument matching (without the cached doubler, they were instances of different classes, which is why it worked). |
Yes, I understand your point but I don't think that the following statement is true
because instances are different so from my POV. Yes, it could break some tests because Could you try it against the code you broken when tried out Thanks in advance for your review and your time. |
Any update? I would be happy to try and see what Stof claims but I really can't understand how to make (and on what) the functional test :\ |
Any news? I'm willing to continue my work but without any clue I just can't write litterally any line of those tests that stof mentioned above |
@stof maybe the tests you’re waiting for are something like this repeated for all interesting matchers on doubles? All the credits goes to my colleague @bsod85 Please let us know if this is acceptable (there is something that need to be fixed, we know, but the idea behind it should be clear) or if is not what you expect to be tested. Thanks! |
@stof Sorry to disturb you, could you give me any update on this. I know that probably you are busy but I would like only to have a feedback, even if this is "I can't take a look at this for a while". Thank you in advance guys. |
Hi @DonCallisto I just tested your patch and could see a great performance improvement indeed, for a suite of 221 tests with 591 assertions. Without the patch:
With the patch on:
However, a test of mine is broken with the patch applied: /** @test */
public function fetch_service_returns_service_with_highest_priority()
{
/* *** Initialization *** */
$source = [];
$targetType = $this->prophesize(Type::class)->reveal();
$serviceA = $this->prophesize(Service::class);
$serviceA->priority()
->shouldBeCalled()
->willReturn(100);
$serviceB = $this->prophesize(Service::class);
$serviceB->priority()
->shouldBeCalled()
->willReturn(200);
/* *** Process *** */
$this->registry->register(get_class($serviceA->reveal()));
$this->registry->register(get_class($serviceB->reveal()));
$service = $this->registry->fetchFor($source, $targetType);
/* *** Assertion *** */
$this->assertInstanceOf(get_class($serviceB->reveal()), $service);
} Maybe I shouldn't have done the assertion based on the class of the double, but as far as I can see your patch doesn't allow testing cases like this one, maybe am I missing something? |
@romm What does |
@DonCallisto adding this dumps: var_dump(get_class($serviceA->reveal()));
var_dump(get_class($serviceB->reveal())); I get the following values: Without your patch
With your patch
After some more analysis, the services are instantiated with the given class and that's probably not the best way to do it: an instance of the object should be given instead. So I think I'm going to change the implementation anyway, but you better know what was going on here. |
@romm Yes, it is was I suspected without seeing you implementation. That's a case where Prophecy didn't catch a possible problem with your implementation due to different class names. This patch will correct this scenario also. |
@ciaranmcnulty could you please take a look at this? We're basically stuck but I feel like this PR could be merged with right PHPUnit tests done (see #420 (comment)) |
@everzet could you take a look at this? It's four months since this PR is open and I feel like we're there or at least very close to mergeable code. |
Hello, any news concerning this PR? Could we help to get it merged somehow? :) |
@romm it seems not |
@ciaranmcnulty as I see you're quite active these days, could you try to take a look a this and thread? |
@stof do you have some time to continue the conversation here? I am not clear what the issues you observed were |
Just to provide more context (as one year has passed), an interesting question never answered was this. PS.: I'm using since a year a fork of mine with modification I've provided in this PR. Old examples (as pointed out in first comment) ~ 6000 didn't broke and new examples (can't quantify them) worked as expected. |
OK I'm going to merge this, we can always back it out if users find issues We aren't maintaining actively enough to get into long 'what if' conversations if they're not resolved |
Thanks @ciaranmcnulty! |
…y usage
With this PR we resolve #96 and phpspec/phpspec#884.
Our empirical tests:
~ 6000 PHPSpec examples
Before patch:
After patch:
Only thing that should be considered here is the static-ness nature of
CachedDoubler
.Is this fine or is it improvable?