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

Joomla String Class Optimisation #6787

Closed
wants to merge 3 commits into from
Closed

Joomla String Class Optimisation #6787

wants to merge 3 commits into from

Conversation

orware
Copy link
Contributor

@orware orware commented Apr 16, 2015

In testing I had done over the weekend and then again today, I was noticing that the String.php file (which is in the Joomla String package in the libraries/vendors folder) was exhibiting some odd performance behavior on my Windows machine.

Hopefully others will be able to confirm the same thing happening on their end and can confirm that this PR fixes the issue.

Overview of the Issue:

Basically I noticed that in the Joomla\String\String class a good majority of the methods have a "require_once" included in them and this seems to slow down the usage of the function over repeated calls.

Additionally, while coming up with some code that could be used by testers to see the before/after effects on their end, I noticed another issue crop up which has to do with an older call to jimport() in JApplicationWeb and JApplication so the last commit I have that changes those files is to fix that issue.

Details on Performance Improvements:

These examples are using my testing code I'm including below and cause 500 executions of each of the functions.

Before the String class optimizations (Total Time ~502 ms):

Time: 25.5 ms / 26.5 ms Memory: 1.762 MB / 2.49 MB Application: Before JString::ucfirst()
Time: 37.3 ms / 63.8 ms Memory: 0.114 MB / 2.61 MB Application: After JString::ucfirst()
Time: 0.0 ms / 63.9 ms Memory: 0.001 MB / 2.61 MB Application: Before JString::ucwords()
Time: 63.5 ms / 127.3 ms Memory: 0.005 MB / 2.61 MB Application: After JString::ucwords()
Time: 0.0 ms / 127.4 ms Memory: 0.001 MB / 2.61 MB Application: Before JString::valid()
Time: 52.7 ms / 180.1 ms Memory: 0.011 MB / 2.62 MB Application: After JString::valid()
Time: 0.0 ms / 180.1 ms Memory: 0.001 MB / 2.62 MB Application: Before JString::compliant()
Time: 42.0 ms / 222.1 ms Memory: 0.001 MB / 2.62 MB Application: After JString::compliant()
Time: 0.0 ms / 222.1 ms Memory: 0.001 MB / 2.63 MB Application: Before JString::trim()
Time: 26.3 ms / 248.4 ms Memory: 0.007 MB / 2.63 MB Application: After JString::trim()
Time: 0.0 ms / 248.5 ms Memory: 0.001 MB / 2.63 MB Application: Before JString::ltrim()
Time: 27.7 ms / 276.2 ms Memory: 0.001 MB / 2.64 MB Application: After JString::ltrim()
Time: 0.0 ms / 276.2 ms Memory: 0.001 MB / 2.64 MB Application: Before JString::rtrim()
Time: 26.0 ms / 302.2 ms Memory: 0.001 MB / 2.64 MB Application: After JString::rtrim()
Time: 0.0 ms / 302.2 ms Memory: 0.001 MB / 2.64 MB Application: Before JString::strspn()
Time: 31.5 ms / 333.7 ms Memory: 0.005 MB / 2.64 MB Application: After JString::strspn()
Time: 0.0 ms / 333.7 ms Memory: 0.001 MB / 2.64 MB Application: Before JString::strrev()
Time: 38.4 ms / 372.1 ms Memory: 0.003 MB / 2.65 MB Application: After JString::strrev()
Time: 0.0 ms / 372.1 ms Memory: 0.001 MB / 2.65 MB Application: Before JString::stristr()
Time: 41.5 ms / 413.6 ms Memory: 0.005 MB / 2.65 MB Application: After JString::stristr()
Time: 0.0 ms / 413.6 ms Memory: 0.001 MB / 2.65 MB Application: Before JString::strcspn()
Time: 30.8 ms / 444.5 ms Memory: 0.005 MB / 2.66 MB Application: After JString::strcspn()
Time: 0.0 ms / 444.5 ms Memory: 0.001 MB / 2.66 MB Application: Before JString::str_split()
Time: 38.8 ms / 483.3 ms Memory: 0.004 MB / 2.66 MB Application: After JString::str_split()
Time: 0.0 ms / 483.3 ms Memory: 0.001 MB / 2.67 MB Application: Before JString::str_ireplace()
Time: 45.1 ms / 528.4 ms Memory: 0.009 MB / 2.67 MB Application: After JString::str_ireplace()
Time: 0.0 ms / 528.4 ms Memory: 0.001 MB / 2.68 MB Application: Before JString::is_ascii()
Time: 0.0 ms / 528.4 ms Memory: 0.001 MB / 2.68 MB Application: After JString::is_ascii()

After the String class optimizations (Total Time ~101 ms):

Time: 25.4 ms / 26.3 ms Memory: 1.756 MB / 2.49 MB Application: Before JString::ucfirst()
Time: 9.4 ms / 35.7 ms Memory: 0.121 MB / 2.61 MB Application: After JString::ucfirst()
Time: 0.0 ms / 35.7 ms Memory: 0.001 MB / 2.61 MB Application: Before JString::ucwords()
Time: 31.1 ms / 66.8 ms Memory: 0.005 MB / 2.61 MB Application: After JString::ucwords()
Time: 0.0 ms / 66.8 ms Memory: 0.001 MB / 2.61 MB Application: Before JString::valid()
Time: 5.2 ms / 72.0 ms Memory: 0.011 MB / 2.62 MB Application: After JString::valid()
Time: 0.0 ms / 72.1 ms Memory: 0.001 MB / 2.62 MB Application: Before JString::compliant()
Time: 1.8 ms / 73.9 ms Memory: 0.001 MB / 2.63 MB Application: After JString::compliant()
Time: 0.0 ms / 73.9 ms Memory: 0.001 MB / 2.63 MB Application: Before JString::trim()
Time: 1.3 ms / 75.1 ms Memory: 0.007 MB / 2.63 MB Application: After JString::trim()
Time: 0.0 ms / 75.2 ms Memory: 0.001 MB / 2.63 MB Application: Before JString::ltrim()
Time: 1.0 ms / 76.1 ms Memory: 0.001 MB / 2.64 MB Application: After JString::ltrim()
Time: 0.0 ms / 76.2 ms Memory: 0.001 MB / 2.64 MB Application: Before JString::rtrim()
Time: 1.0 ms / 77.1 ms Memory: 0.001 MB / 2.64 MB Application: After JString::rtrim()
Time: 0.0 ms / 77.2 ms Memory: 0.001 MB / 2.64 MB Application: Before JString::strspn()
Time: 3.9 ms / 81.1 ms Memory: 0.005 MB / 2.64 MB Application: After JString::strspn()
Time: 0.0 ms / 81.1 ms Memory: 0.001 MB / 2.65 MB Application: Before JString::strrev()
Time: 5.9 ms / 87.0 ms Memory: 0.003 MB / 2.65 MB Application: After JString::strrev()
Time: 0.0 ms / 87.0 ms Memory: 0.001 MB / 2.65 MB Application: Before JString::stristr()
Time: 14.6 ms / 101.6 ms Memory: 0.005 MB / 2.65 MB Application: After JString::stristr()
Time: 0.0 ms / 101.6 ms Memory: 0.001 MB / 2.66 MB Application: Before JString::strcspn()
Time: 4.1 ms / 105.7 ms Memory: 0.005 MB / 2.66 MB Application: After JString::strcspn()
Time: 0.1 ms / 105.8 ms Memory: 0.001 MB / 2.66 MB Application: Before JString::str_split()
Time: 6.2 ms / 112.0 ms Memory: 0.004 MB / 2.67 MB Application: After JString::str_split()
Time: 0.0 ms / 112.0 ms Memory: 0.001 MB / 2.67 MB Application: Before JString::str_ireplace()
Time: 14.7 ms / 126.7 ms Memory: 0.009 MB / 2.68 MB Application: After JString::str_ireplace()
Time: 0.0 ms / 126.8 ms Memory: 0.001 MB / 2.68 MB Application: Before JString::is_ascii()
Time: 0.0 ms / 126.8 ms Memory: 0.001 MB / 2.68 MB Application: After JString::is_ascii()

Testing Instructions

Go into your Joomla Administrator and turn on debugging (so that you can see the profile information on the page).

Once enabled and you can see the profiler info, go ahead and copy the following lines of code into your administrator/index.php file (you can copy these lines in right after line 44...right after this line: "$app = JFactory::getApplication('administrator');")

Once the code below is copied in, go ahead and test and take note of the before timings.

Then apply the patch and observe the after timings.

$range = range(1, 500);

JDEBUG ? $_PROFILER->mark('Before JString::ucfirst()') : null;
foreach($range as $i)
{
    JString::ucfirst('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::ucfirst()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::ucwords()') : null;
foreach($range as $i)
{
    JString::ucwords('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::ucwords()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::valid()') : null;
foreach($range as $i)
{
    JString::valid('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::valid()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::compliant()') : null;
foreach($range as $i)
{
    JString::compliant('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::compliant()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::trim()') : null;
foreach($range as $i)
{
    JString::trim('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::trim()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::ltrim()') : null;
foreach($range as $i)
{
    JString::ltrim('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::ltrim()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::rtrim()') : null;
foreach($range as $i)
{
    JString::rtrim('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::rtrim()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::strspn()') : null;
foreach($range as $i)
{
    JString::strspn("42 is the answer to the 128th question.", "1234567890");
}
JDEBUG ? $_PROFILER->mark('After JString::strspn()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::strrev()') : null;
foreach($range as $i)
{
    JString::strrev('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::strrev()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::stristr()') : null;
foreach($range as $i)
{
    JString::stristr('joomla is awesome', 'is');
}
JDEBUG ? $_PROFILER->mark('After JString::stristr()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::strcspn()') : null;
foreach($range as $i)
{
    JString::strcspn("42 is the answer to the 128th question.", "1234567890");
}
JDEBUG ? $_PROFILER->mark('After JString::strcspn()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::str_split()') : null;
foreach($range as $i)
{
    JString::str_split('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::str_split()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::str_ireplace()') : null;
foreach($range as $i)
{
    JString::str_ireplace('is', 'is not', 'joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::str_ireplace()') : null;

JDEBUG ? $_PROFILER->mark('Before JString::is_ascii()') : null;
foreach($range as $i)
{
    JString::is_ascii('joomla is awesome');
}
JDEBUG ? $_PROFILER->mark('After JString::is_ascii()') : null;

…direct usage of JString::is_ascii() instead (JApplicationWeb and JApplication both imported the utf8_is_ascii() function directly from the phputf8 library and it seemed to cause a cannot redeclare function error).
@wilsonge
Copy link
Contributor

Hi Thanks for this PR! Anything that touches the framework files should be made to the string package in the framework repository (https://github.com/joomla-framework/string) If you're happy to do that it would be really appreciated :) Thanks!

@orware
Copy link
Contributor Author

orware commented Apr 16, 2015

Thanks George,

That was going to be my original plan once I noticed it was one of the framework packages...however the current version of the package we're using in Joomla doesn't seem to match up with the Master String branch in the framework repository (as an example, in the CMS there's just a String.php file, but in the framework String.php defers to another file called StringHelper.php which actually contains the function definitions...since I didn't know when/if those updates would be brought into the CMS I thought it would be better to create my PR against what is currently in the CMS first).

Maybe you have some extra info about whether or not the String package is going to be updated in the CMS soon? If it will be, I can certainly create an additional PR against the framework code.

@wilsonge
Copy link
Contributor

We will be merging the string updates into 3.5 - as there is a low chance of a b/c break because of the class rename (PHP 7 forbid us to use the word string as it's now protected). #6600 The PR is already in for it though

@orware
Copy link
Contributor Author

orware commented Apr 16, 2015

Thanks for the update...I'll work on the PR against the Framework package sometime today ;-).

@orware
Copy link
Contributor Author

orware commented Apr 16, 2015

I'm going to go ahead and close this PR since Michael merged in the separate PR I created for the String package earlier today.

@orware orware closed this Apr 16, 2015
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.

None yet

3 participants