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

Phalcon\Di Optimizations #1014

Merged
merged 3 commits into from Aug 6, 2013
Merged

Phalcon\Di Optimizations #1014

merged 3 commits into from Aug 6, 2013

Conversation

ghost
Copy link

@ghost ghost commented Aug 6, 2013

  • use return_value wherever possible instead of temporary variables;
  • use phalcon_fetch_property() instead of phalcon_read_property() (return value then does not have to be observed)
  • use phalcon_array_isset_fetch() to combine isse()/fetch() operations and avoid extra search pass
  • validate arguments and throw exceptions before the memory frame is created
  • do not convert NULLs to zvals unless absolutely necessary

@ronaldcastillo
Copy link

Sorry to bring this here, but, do you happen to have a benchmark with the optimizations you have made lately? I'd love to see the difference in performance.

@ghost
Copy link
Author

ghost commented Aug 6, 2013

I run the official test suite under callgrind before and after optimization and compare the results.

Something like this:

ZEND_MM_ALLOC=0 valgrind --tool=callgrind $(phpenv which php) unit-tests/manual-unit.php

or, if I need to test only specific class:

ZEND_MM_ALLOC=0 valgrind --tool=callgrind $(phpenv which php) unit-tests/manual-unit.php TestFile.php ClassName

Usually I take the most expensive function and try to reduce its cost (the lower the cost is, the less time is spent in the function — you can see the figures in my pull requests).

Some optimizations are somewhat evident — for example, the code will run faster without allocating/freeing a memory frame (because we save class to emalloc()/efree() and memory allocation is always costly); same when the code uses pure (constant) references instead of copies (see the recent commits that introduced phalco_read_(n)property(_this) and phalcon_array_isset_fetch() functions) as this saves at least one memory allocation and copy; every such a reference saves at least 32 bytes (sizeof(zval*) on a 64-bit platform) etc.

If I look at the code, I can usually tell how much the optimization allowed one to save memory but I do not record such figures.

@ghost
Copy link
Author

ghost commented Aug 6, 2013

For example, for this commit:

  • chunk 1: memory frame (48 bytes), 1 zval (32 bytes), 1 emalloc(), 1 efree() => 80 bytes
  • chunk 2: 1 zval* (8 bytes), 1 zval (32 bytes) => 40 bytes
  • setShared(): same as above (40 bytes)
  • attempt(): 1 zval_, 2 zval (72 bytes) + 1 memory frame (48 bytes) and 40 bytes (zval_ + zval) if the service exists + 1 array search pass if the service exists
  • getRaw(): 2 zval (64 bytes) plus 1 array search pass if the service exists
  • getService(): 2 zval (64 bytes); if the service exists: one memory frame (48 bytes), one array search pass
  • get(): 2 zval (64 bytes), 1 array search in most cases
  • has(): 1 zval*, 2 zval, 1 memory frame (120 bytes)

etc

phalcon pushed a commit that referenced this pull request Aug 6, 2013
Phalcon\Di Optimizations
@phalcon phalcon merged commit 0102222 into phalcon:1.3.0 Aug 6, 2013
@phalcon
Copy link
Collaborator

phalcon commented Aug 6, 2013

Thanks!

@ghost ghost deleted the di branch August 7, 2013 10:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants