3

EDIT: This has been because of bug in my code (probably), after debugging and adding checking for correct response in my tests, test prove NO difference (what irks me a little), more in my own answer below.
/EDIT

Hello,

I've written myself a little CSS wrapper for SASS for PHP and programmed it to accept filename and possible flags before running (and possibly caching, if not flagged otherwise) my SASS file.

I've also conducted few test and version nr. 2 is something around 2x - 4x slower than version nr. 1, although version 1 has to run more code then version 2 (It does straight include from disk, rather than parsing URL first for flags).

I don't understand it why really and tests are somewhat too consistent to call it on a disk access overhead.

Here are speed tests:

First - generate file, then - just require from cache
Version 1 total: 10.886 s avg: 10.886 ms/file first: 466.42 ms
Version 2 total: 21.235 s avg: 21.235 ms/file first: 14.54 ms

Just require from cache
Version 1 total: 7.886 s avg: 7.886 ms/file first: 2.93 ms
Version 2 total: 21.657 s avg: 21.657 ms/file first: 6.98 ms

Version with readfile instead of require
Version 1 run 1: total: 7.915 avg: 7.915 ms/file first: 2.49 ms
Version 2 run 1: total: 9.508 avg: 9.508 ms/file first: 3.23 ms
Version 1 run 2: total: 1:17.137 avg: 7.714 ms/file first: 4.61 ms
Version 2 run 2: total: 1:15.717 avg: 7.572 ms/file first: 2.69 ms * - run 2 was 10,000 calls.

Version 1

/* HELPER FUNCTIONS */
function is_option($opt) { global $url_options; return in_array($opt,$url_options); }
function fail($message) { echo $message; die(); }

//prepare options array
$options=array();

$url_options = @explode('_',basename($_GET['f']));
if (!is_array($url_options))
    { fail('Wrong parameters given (or parameter can\'t be accepted)'); }
$loadfile = array_shift($url_options);

if (!file_exists('source/'.$loadfile.'.sass'))
{
    if (!file_exists('source/'.$loadfile.'.scss'))
        fail('Wrong parameters given (file doesn\'t exist)');
    else
        $options['property_syntax']='scss';
}else{
    $options['property_syntax']='sass';
}

$src_file = 'source/'.$loadfile.'.'.$options['property_syntax'];
$css_file = 'cache/'.$loadfile.'.css';

if (file_exists($css_file) && !is_option('no-cache'))
{
    header('content-type: text/css');
    require($css_file);
    die(); //ALL OK, loaded from cache
}

Version 2

//quick! load from cache if exists!
if (file_exists('cache/'.($cachefile=basename('/',$_GET['f']))))
{
    header('content-type: text/css');
    require('cache/'.$cachefile);
    die(); //ALL OK, loaded from cache
}

/* HELPER FUNCTIONS */
function is_option($opt) { global $url_options; return in_array($opt,$url_options); }
function fail($message) { echo $message; die(); }

//prepare options array
$options=array();

$url_options = @explode('_',basename($cachefile));
if (!is_array($url_options))
    { fail('Wrong parameters given (or parameter can\'t be accepted)'); }
$loadfile = array_shift($url_options);

if (!file_exists('source/'.$loadfile.'.sass'))
{
    if (!file_exists('source/'.$loadfile.'.scss'))
        fail('Wrong parameters given (file doesn\'t exist)');
    else
        $options['property_syntax']='scss';
}else{
    $options['property_syntax']='sass';
}

$src_file = 'source/'.$loadfile.'.'.$options['property_syntax'];
$css_file = 'cache/'.$loadfile.'.css';

I will go with version 1 probably, I would just like to understand WHY exactly v2 is slower, although it runs less code...

EDIT: Seems that readfile is a little faster than require, brought the two version to be statistically the same, although version 1 is still faster (but it's just 2 seconds for 1000 AND 10000 calls, so this might be just random disk usage)

Adam Kiss
  • 11,811
  • 9
  • 48
  • 81

3 Answers3

1

What do you mean, "version 2 has to run more code" ?

Version 2 is checking the cache first and skipping all the rest if it finds the cached file.

Of course, it is also completely ignoring all the "URL options".

Zecc
  • 4,220
  • 19
  • 17
  • That was just misplaced numbers - due to testing in reversered order - i test version1 with `test2.php` and version 2 with `test1.php`, just a mistake on my part – Adam Kiss Dec 18 '10 at 12:08
1

It seems there is a bug in

  if (file_exists('cache/'.($cachefile=basename('/',$_GET['f']))))

either

  • there is a type and explode wanted to be used instead
  • or basename is not used as it should - i.e. basename($_GET['f']) instead of basename('/', $_GET['f'])

Therefore the $cachefile is blank, the if is always true and the require applies to the cache directory.

Déjà vu
  • 28,223
  • 6
  • 72
  • 100
  • I thought that that might be it! But, it seems that the only result is, that it deleted any speed bump gaind by using `readfile` against `require`, so I'm conducting more tests with actual responses. – Adam Kiss Dec 18 '10 at 12:41
1

So, the main difference was due to error in my code, pointed out by ring0 (thank you).

After repairing the bug, editing the tests to show response in every (n/10)th case out of n iterations and running both tests parallel, results are these:

Results for Version 1 (with require):
Processed 10000 times
It took 4:56.806 [1292676882-1292677179]
Average time: 29.681 miliseconds

Results for Version 1 (with readfile):
Processed 10000 times
It took 4:35.242 [1292677437-1292677712]
Average time: 27.524 miliseconds

Results for Version 2 (with require):
Processed 10000 times
It took 4:55.760 [1292676879-1292677175]
Average time: 29.576 miliseconds

Results for Version 2 (with readfile):
Processed 10000 times
It took 4:32.336 [1292677433-1292677706]
Average time: 27.234 miliseconds

Graph:
Speeds for 10,000 iteration calls

So, the new version/version 2 (the one, where the require/readfile is on top) is faster now, although not that significantly. I'll probably use that one, together with readfile enhancement (thanks to Emil).

Thank you all, this is what happens if you do not test properly :)

This is what happens

Community
  • 1
  • 1
Adam Kiss
  • 11,811
  • 9
  • 48
  • 81