Hello,
I have magento 1.9.3.8 store with several extensions installed (most of them developed by me) running on Ubuntu 16.04 virtual machine with 4 cores and 32GB ram, nginx, php-fpm, memcached.
The page load times vary between 1 and 1.5 seconds, however i noticed the page is being generated in buffer and then sent to the browser. I had an idea to flush that buffer after </head> tag (in 2columns-left.phtml) so it starts downloading css and js while parsing the page body.
Unfortunately i get this error in system.log:
DEBUG (7): HEADERS ALREADY SENT: \<pre>[0] /home/furn3284/public_html/app/code/core/Mage/Core/Controller/Response/Http.php:52
Digging in lib/Zend/Controller/Response/Abstract.php around line 320:
$ok = headers_sent($file, $line); if ($ok && $throw && $this->headersSentThrowsException) { #require_once 'Zend/Controller/Response/Exception.php'; throw new Zend_Controller_Response_Exception('Cannot send headers; headers already sent in ' . $file . ', line ' . $line); } return !$ok;
i was able to see the headers_sent $file is 2columns-left.php and the line is where i use ob_flush();
Is there any option/config setting that i can tell headers to be sent before parsing the page template?
Overall it works very well when flushing. TTFB is improved alot, page loading faster and smooth, just this error message in system.log
Hi @Miro Igov,
I guess changing the abstract class isn't the best approach.
If you want to defer the javascript files maybe you can use this module: https://github.com/bobbyshaw/magento-footer-js
Then you can use https://github.com/AOEpeople/Aoe_Profiler to try to find if the problem is a module.
Another option could be to use a CDN (or at least a Poor-Man-Cdn).
Defer JS is not good idea as the TTFB will still be huge (equal to page parse time). I want to send <head></head> section to users immediately aftrer </head> tag and then continue parsing the rest of the site.
Benefits:
- Google ranks sites with low TTFB better
- JS/CSS is downloaded in parallel with remaining page parsing
I think it is pretty enough to wait for HTTP headers hooked from extensions until <head> section is parsed. However magento does not allow this because of the abstract class check executed at end of parsing.
Have you tried leveraging memcaching on the server? Also have you tried turning off all the modules, running the timing again and then turning them on one by one to just double check that one of them isn't causing an issue?
Carrie
Memcached is running well and not full at all. Plenty of RAM for it.
Of course it is from the extensions and processing (i have custom header menu with selected categories and products and also some products/categories denied for certain group of users - guests, logged in but with less permission). All that makes the load slow - 1.5 or 2sec total for the page.
But what i am trying to achieve is sending <head>....</head> section with ob_flush() to browser and then start processing mentioned above. With this i would win good ttfb (tested already by modifying core files to send response earlier) and start loading css/js before full html parsing finish.
It is well known technique in the web development but not possible in magento 1.9, as it checks if headers are already sent right at the end of page parsing.
Can you some how store the custom menu header data in a table so it doesn't have to calculate what to display? Or are you already doing that?
Sounds like you need to cache this header. You could even make multiple caches based upon the user membership logged in.
Carrie
Thanks for the reply.
No i can't store header menu in table or cache because the website have group permissions and some categories are hidden from guest users. Some directories are hidden from logged in users too but are visible to full access users.
It's not possible having header menu stored in a table, it is different for every group of users (3 groups in total).
I am caching the collection of categories and cache ID contains group so it have separate cache for each group.
Anyways i prefer sending <head></head> section to the user so browsers start loading css/js while other content is generated from cache or mysql. Flush at specific points will be very good but Magento 1.9 does not allow it.
Zend framework itself is at fault for TTFB. isn't it?
Hi there !
Magento 1 uses dependency injection...... wait for it...........Yes, it does !
https://github.com/OpenMage/magento-mirror/blob/magento-1.9/app/Mage.php#L673-L679
self::$_app = new Mage_Core_Model_App(); if (isset($options['request'])) { self::$_app->setRequest($options['request']); } if (isset($options['response'])) { self::$_app->setResponse($options['response']); }
and
public function setResponse(Mage_Core_Controller_Response_Http $response) { $this->_response = $response; return $this; }
Thus you have to "shove" your implementation into Magento 1 from index.php
Mage::run("?", "?", ["response" => new Your_Zend_Controller_Response_Abstract_Thing ])
Happy hacking in M1.....
I am thinking the same to flush head and navigation part, did you got solution?