-
-
Notifications
You must be signed in to change notification settings - Fork 388
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
Replacing the Schema by a proxy #407
Conversation
@mikeSimonson the first run was just pseudo-code |
it needs a first run to warm up some sort of cache ? |
@mikeSimonson you didn't import any of the proxy lib stuff :-) |
use ProxyManager\Factory\LazyLoadingGhostFactory; | ||
use ProxyManager\Proxy\LazyLoadingInterface; | ||
|
||
class LazySchemaManipulator |
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.
not implementing a common interface looks wrong to me
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.
Agreed. The name also needs fixing: we just mashed it together real quick in a video call yesterday :)
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.
Any idea on a better naming ? for the class and the interface ?
@mikeSimonson I guess this is an alternative to #323. |
/** @var AbstractSchemaManager */ | ||
private $schemaManager; | ||
|
||
public function _construct(AbstractSchemaManager $schemaManager, $platform) |
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.
missing _
, so this is not a constructor. This is why you are calling on null
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.
@mikeSimonson please fix this so that tests can run for real
@mikeSimonson the PR should describe what it really does IMO, not the issue you are facing currently |
@stof The problem with your solution is that right now most of the people wouldn't benefit from it. Can you look again at the last change I made. I was thinking to something along the line of SchemaDiffProvider or SchemaProvider. Thanks for your review |
@stof Do you have some time to look at this again ? |
Schema::class, | ||
function (& $wrappedObject, $proxy, $method, array $parameters, & $initializer) use ($originalSchemaManipulator, $fromSchema) { | ||
$initializer = null; | ||
$wrappedObject = $originalSchemaManipulator->createToSchema($fromSchema); |
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.
shouldn't you force initializing the fromSchema here before passing it to the originalSchemaManipulator ?
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.
The createToSchema method clone the fromSchema and the clone trigger the initialization.
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.
then it is good
@mikeSimonson it is great to see the build being green here. |
* <http://www.doctrine-project.org>. | ||
*/ | ||
|
||
namespace Doctrine\DBAL\Migrations\Provider; |
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.
why is it in a subnamespace while implementations are not ?
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.
no valid reason
Replacing the Schema by a proxy
@stof Do you think that you could do a profile of v1.2.1 against master to see the benefits ? |
Here you go. This is the result of running 109 migrations on PostgreSQL 9.3 and PHP 5.6.16 on my laptop (with XDebug enabled as I forgot to disable it before profiling):
We have a 97% performance improvement here (from 2min20s to 4.68s). This is similar to the 94% I reported in #323 (the difference is probably related to the fact that I have more migrations than at that time, making the effect even bigger) |
That is quite... impressive :O @mikeSimonson still, are you sure that we want proxymanager installed as hard dependency? |
@Ocramius I think we do (I'm looking forward the release of a zend-code release without the zend-stdlib dependency though, to have less transitive deps) |
As far as I know, it doesn't require stdlib, but the eventmanager: https://github.com/zendframework/zend-code/blob/4972c33d975fa0c2b86ff381e83fde177079b249/composer.json#L17 That can't be fixed until we drop annotations support ( zendframework/zend-code#32 ), which will only happen in a major revision. Making it an optional dependency without dropping that feature will just lead to a lot of people having headaches when they want to actually use the annotations support :-\ |
There is a drawback in this change though: look at the metrics about the GC runs. We went from 1 to 81. |
And regarding the dependencies, I think a 97% perf increase justifies the mandatory dependency. If we make it optional, people would have to opt-in the fast way, which would not be much better than #323 (well, except the opt-in would be in a single place), and we would have to expose this layer outside the library (currently, it is hidden from the outside, allowing us to treat it as fully internal) |
The initializer closures will obviously cause cyclic graphs. There is a way to "fix that" (simply
Agree on all the conclusions. |
@Ocramius the idea is to reset the initializer at the end of the migration, when we don't need the Schema object anymore (the refcount will then destroy it) |
@stof I wouldn't do that anyway, as it may lead to unexpected bugs (in case the objects are needed after migration run, or are used in any other context) |
@mikeSimonson this patch still lacks some tests that are required to prevent any regression that may by accident initialize a migration. I know it is a pain, but that means extremely detailed mocking :-\ |
* | ||
* @return string[] | ||
*/ | ||
public function getSqlDiffToMigrate(Schema $fromSchema,Schema $toSchema); |
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.
missing space
@Ocramius What sort of test do you think are missing ? |
@stof detail but when I look at the profile of the future 1.3 and that I go in the Metrics tab I see one call to GC et 81 for the profile of the 1.2. But in the comparison page in the metrics tab the numbers seems inverted. Same for the number of PDO and SQL queries. Bug in blackfire ? Btw it make more sense to me that there would be less call to the GC with the Proxy because we are not instantiating all those Tables objects in the Schema. |
@mikeSimonson the tests that I'm referring to would expect the schema object methods to never be called: basically a set of |
@Ocramius I don't understand the goal this test ? Do you mean testing that none of the method of the schema are called in the pre and post method or something else ? |
@mikeSimonson correct. That is just to prevent regressions though. |
Looks like it is. then everything is good (and the issue would then be about the Schema system in DBAL relying on cyclic object graphs, which is off-topic) |
I reported the bug to the Blackfire team |
@mikeSimonson that test is still calling API methods on the schema objects - a test where no method calls on the schema ever happen is required |
This PR try to explore the possibility of using Proxy object instead of the costly initialization of the schema object.