Chris@13: Performance Chris@13: =========== Chris@13: Chris@13: Parsing is computationally expensive task, to which the PHP language is not very well suited. Chris@13: Nonetheless, there are a few things you can do to improve the performance of this library, which are Chris@13: described in the following. Chris@13: Chris@13: Xdebug Chris@13: ------ Chris@13: Chris@13: Running PHP with XDebug adds a lot of overhead, especially for code that performs many method calls. Chris@13: Just by loading XDebug (without enabling profiling or other more intrusive XDebug features), you Chris@13: can expect that code using PHP-Parser will be approximately *five times slower*. Chris@13: Chris@13: As such, you should make sure that XDebug is not loaded when using this library. Note that setting Chris@13: the `xdebug.default_enable=0` ini option does *not* disable XDebug. The *only* way to disable Chris@13: XDebug is to not load the extension in the first place. Chris@13: Chris@13: If you are building a command-line utility for use by developers (who often have XDebug enabled), Chris@13: you may want to consider automatically restarting PHP with XDebug unloaded. The Chris@13: [composer/xdebug-handler](https://github.com/composer/xdebug-handler) package can be used to do Chris@13: this. Chris@13: Chris@13: If you do run with XDebug, you may need to increase the `xdebug.max_nesting_level` option to a Chris@13: higher level, such as 3000. While the parser itself is recursion free, most other code working on Chris@13: the AST uses recursion and will generate an error if the value of this option is too low. Chris@13: Chris@13: Assertions Chris@13: ---------- Chris@13: Chris@13: Assertions should be disabled in a production context by setting `zend.assertions=-1` (or Chris@13: `zend.assertions=0` if set at runtime). The library currently doesn't make heavy use of assertions, Chris@13: but they are used in an increasing number of places. Chris@13: Chris@13: Object reuse Chris@13: ------------ Chris@13: Chris@13: Many objects in this project are designed for reuse. For example, one `Parser` object can be used to Chris@13: parse multiple files. Chris@13: Chris@13: When possible, objects should be reused rather than being newly instantiated for every use. Some Chris@13: objects have expensive initialization procedures, which will be unnecessarily repeated if the object Chris@13: is not reused. (Currently two objects with particularly expensive setup are lexers and pretty Chris@13: printers, though the details might change between versions of this library.) Chris@13: Chris@13: Garbage collection Chris@13: ------------------ Chris@13: Chris@13: A limitation in PHP's cyclic garbage collector may lead to major performance degradation when the Chris@13: active working set exceeds 10000 objects (or arrays). Especially when parsing very large files this Chris@13: limit is significantly exceeded and PHP will spend the majority of time performing unnecessary Chris@13: garbage collection attempts. Chris@13: Chris@13: Without GC, parsing time is roughly linear in the input size. With GC, this degenerates to quadratic Chris@13: runtime for large files. While the specifics may differ, as a rough guideline you may expect a 2.5x Chris@13: GC overhead for 500KB files and a 5x overhead for 1MB files. Chris@13: Chris@13: Because this a limitation in PHP's implementation, there is no easy way to work around this. If Chris@13: possible, you should avoid parsing very large files, as they will impact overall execution time Chris@13: disproportionally (and are usually generated anyway). Chris@13: Chris@13: Of course, you can also try to (temporarily) disable GC. By design the AST generated by PHP-Parser Chris@13: is cycle-free, so the AST itself will never cause leaks with GC disabled. However, other code Chris@13: (including for example the parser object itself) may hold cycles, so disabling of GC should be Chris@13: approached with care.