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

feature request: function inliner #3564

Closed
Danack opened this issue Jun 21, 2020 · 4 comments
Closed

feature request: function inliner #3564

Danack opened this issue Jun 21, 2020 · 4 comments

Comments

@Danack
Copy link

Danack commented Jun 21, 2020

Feature Request

One thing I've been thinking about is code optimisation, particularly as the JIT for PHP 8 is not actually delivering performance increases for things that are not equivalent to fibonacci/mandelbrot generators.

This is due to the internals of PHP actually being quite fast, and so there are little areas for improvement internally.

However, there is a huge untapped reserve of optimisation around reducing/removing the function call overhead.

This is particularly relevant for trivial functions that do trivial calculations. For the example below, even just the type checking done for the parameter might be equivalent for the amount of work done for the function.

And that's even before the whole amount of work done for creating a stack frame.

Code example

So this code:

function foo(int $x) {
    if ($x > 10) {
        return 10;
    }
    return $x;
}

function bar(int $y) {
    $value = foo($y);
    // Do something with value
}

Can be refactored by:

 function bar(int $y) {
-    $value = foo($y);
+    // inline of foo function
+    if ($y > 10) {
+        $__foo = 10;
+        goto __foo_inline;
+    }
+    $__foo = $y;
+__foo_inline:
+
+    $value = $__foo;
     // Do something with value
 }

And it will be faster. Obviously, single function calls are not where the gains are, but for things that are called thousands of times in loops...

Scope of feature request

  • only work on a given list of functions, no analysis of what code would benefit from inlining.
  • reject (or just fail) any functions that have reference parameters.
  • reject (or just fail) on any instance methods that access private properties of objects.

If that was available, I would use it to experiment to see exactly how much performance could be gained for any libraries that have a relatively high number of small functions.

@TomasVotruba
Copy link
Member

TomasVotruba commented Jun 21, 2020

The code snippets are long and hard to read. Could update it with diff syntax?

-a
+b

@Danack
Copy link
Author

Danack commented Jun 21, 2020

This better?

     public function bar(int $number) {
-        $value = max($number, self::DEFAULT_VALUE);
 
-        $this->quux($value);
+// inline start of function max()
+        if ($number > self::DEFAULT_VALUE) {
+            $__maxTmp = $number;
+            goto __maxEnd;
+        }
+
+        $__maxTmp = self::DEFAULT_VALUE;
+        __maxEnd:
+
+// inline end of function max()
+
+        $this->quux($__maxTmp);
     }

Basically, just inlining the function.

@TomasVotruba
Copy link
Member

Better. Could you make it like 5 lines max? I still don't get it. The less code, the better.

Also post it into the first issues description, not to reply. I'll remove those clutter comments.

@TomasVotruba
Copy link
Member

Closing as missing test case.

The best way to create such a rule is to use Rector recipe: https://github.com/rectorphp/rector/blob/master/docs/rector_recipe.md

If you're able to add a failng test case that way, I'll help you to create it

TomasVotruba added a commit that referenced this issue Apr 5, 2023
rectorphp/rector-src@2380f6a Revert [Tests] Remove RunTestsInSeparateProcesses in rules-tests (#3564)
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

No branches or pull requests

2 participants