欢迎各位兄弟 发布技术文章
这里的技术是共享的
来自 https://stackoverflow.com/questions/11828749/drupal-7-is-too-slow-on-first-load 有大用
Drupal creates pages and serves them to clients. The completed pages are also stored in the cache_page table of the database -- referred to as the Page Cache. This function is enabled on page admin/settings/performance. The nominal settings for the Page Cache section is:
Caching Mode: Normal
Minimum Cache Lifetime: None
Page Compression: Enabled
With these settings the Page Cache will be emptied every time cron runs. Please take this into consideration when you set the number of times cron runs each day. The cron job of our production website runs once per day just after midnight when traffic on the website is low.
The problem with this setup is the Page Cache is empty after cron runs. This means the first time a user accesses a page the completed page will not be in the Page Cache and the access will be slow. We can solve this problem by loading all the webpages of the site when cron completes (known as "cache warming"). You can do this by creating a script that runs the standard cron job followed by some code that loads each page in sitemap.xml into the Page Cache:
#!/bin/bash # # this is the standard Drupal cron invocation that runs from cron # this will flush the Page Cache when Minimum Cache Lifetime set to <none> # wget -O - -q -t 1 http://www.example.com/cron.php # # use the sitemap and reload the Page Cache by accessing each page once # wget --quiet http://www.example.com/sitemap.xml --output-document - | egrep -o "http://www.example.com[^<]+" | wget -q --delete-after -i -O -
You need to change www.example.com in the code above to the domain of your website. Run this script from cron instead of the standard cron invocation. Now the webpages of your website in sitemap.xml are loaded into your Page Cache waiting for the first user access. This first user access will now be served from the Page Cache -- much faster.
This can also be done with the Cache Warmer module. It's run as a Drush command, and it takes a lot of options.
See also:
来自 https://www.drupal.org/node/1576686 有大用
My site's logs show that cron is triggered if someone visits the website. This is slowing down the load time for the first visit.
The cron is configured to run each 3 hours here: Administration » Configuration » System » Cron.
How can I run the cron scheduled and not triggered by visitors?
You should start by reading the Drupal handbook pages about cron to get background and commands to run.
If you have shell/SSH access to the (Linux) server, you can run use run crontab -u www-data -e
to edit the cron table for the web user. You should be able to use the details in the above link to set up proper cron runs as often as you'd like.
If you're on shared hosting without shell access, you'll need to use your web host's control panel (CPanel, Plesk etc.) to log in and add a 'Scheduled Task'. This provides as web interface to the cron tabs, so the same settings will be needed.
If these are not available you'll need to ask your hosting company to help, but there are also free and paid services you can use call the cron.php
page remotely for you. See Set Cron Jobfor example.
Take a look like the Elysia Cron module if you want more out of cron in general -- it's got good documentation and allows you to finely control what tasks run when.
Finally, remember to disable the site running it when visitors arrive at Administration » Configuration » System » Cron when you've managed to set this up.
Drupal 7 incorporated in its modules the code that were in Poormanscron, whose purpose is exactly to run Drupal cron tasks on a site where it is not possible to set cron tasks, when a user visits your site, and every X hours (as set in the page you saw).
If you want to avoid that behavior, you just need to set "Run cron every" to "Never"; contrary to what it could seem, that just influences what happens when users visit your site.[1] You can still run Drupal cron tasks from outside Drupal, remembering that in Drupal 7 cron.php needs to be invoked, from outside Drupal, passing the value shown in "Administration > Reports > Status report."
[1]: In fact, neither cron.php, nor drupal_cron_run() checks the Drupal variable used in that settings page. The only Drupal variables used are:
"cron_key" that contains the cron key used to avoid the Drupal cron tasks are ran from unauthorized users
"maintenance_mode" that is set to TRUE
when the site is in maintenance mode
"cron_last" that contains the timestamp of when cron tasks were ran last time
Hi,
I'm building a site for my client and we both noticed that loading time is very slow when we enter the site address for the first time. It takes about 7 seconds just to start loading files and displaying the content. Like it has some delay.
However, after that period it's very fast and everything is ok. Once the page(s) is/are loaded, we can refresh them quickly and without any delay..... It will happen again though if we weren't active for like 10 minutes...
I tried with caching & compression & optimization enabled, but no luck - first-time delay is there no matter what I do.
Is this a problem with drupal, .htaccess file (I'm using the same I received with drupal) or server?
Thanks.
do you have your minimum cache lifetime set to 10 minutes?
It's not cache or "expire" feature... this is a delay in loading. I said 10 minutes just as approximate...
Anyone?
I want to add that my drupal installation serves two sites.... don't know if that makes any difference.
This is a problem inherent in Drupal. Instead of loading a fixed HTML page, it is making a series of queries to a database and creating the page from the results. Various things can be done to make Drupal more responsive. The first place to look is caching and optimization, which it sounds like you have done.
The next thing to check is the hosting. Drupal is not very quick on a shared hosting plan. You might want to run the site from a VPS. It's more pricey, but your site will load quicker.
A list of some of the Drupal sites I have designed and/or developed can be viewed at motioncity.com
Thanks everyone!
Just as I feared... I think this is a serious drawback for drupal... it's not that waiting several seconds is the end of the world, but the user doesn't know if the site works at all! No loading icons or any signs that loading is in the process.
My drupal installation serves 2 sites. One is the main site with usual information and product catalog... it's relatively small and the other one is for e-shop (ubercart). I don't consider my site to be megalomanic and I know my client won't change the hosting.
Install Boost
http://drupal.org/project/boost
Follow the directions, it's worth it. To guarantee fast pages every time use the crawler as well.
http://drupal.org/node/363077
In short don't give up that easily. There are multiple tricks one can do on cheap hosting.
Two more things I'd check out...
1. If you have a whole lot of modules enabled (depending on which modules, "a lot" could mean anywhere from 50 to 150), that could be one of the causes of the slowness.
2. Once you have all your css/js compression + optimization and all the other basic performance stuff taken care of, if you still want a further performance boost, check out Boost. From what I hear it's pretty advanced to configure, but it does dramatically enhance the speed of your website. Basically, what it does is create cached versions of your pages (meaning once that page is first visited by a user, Boost creates a static copy so that on subsequent page loads there doesn't need to be any back-and-forth with the database).
I have experienced a similar problem on my vps with low traffic. Regardless of which page I was viewing for the first time,The server had to wake up. And it actually did it with non-drupal stuff too. I took the simple solution - made a simple cron job requesting the front page every 30 minutes (that was my sleeping time).
Googling my problem revealed a lot of similar problems with other PHP franeworks but I found the solutions to technical.
I would also recommend installing The brilliant Boost module. Drupal is ressource heavy and Boost is a nice way to make fast and scalable sites.
For my code heavy sites on my VPS, I loaded up FastCGI to keep the compiled code in memory so it didn't have to recompile again. Sped things up on first load by quite a bit.
trying to figure out molases.
On my sites things would be going great the all of a sudden site crawls.
Drupal 7 site experiencing slow execution/load time for first page visit and slower execution/load time for login. The web server and database servers are dedicated and well resourced, the site has no traffic currently.
Settings already in place
JS/CSS compression enabled
Cron is run via crontab every hour and disabled in Drupal
Cache warming 2 times a day with min, max cache expiry time at 1 day for anon
APC is set to 192MB and using about half memory
Database is on another dedicated box lots of RAM
Update manager disabled
Content translation disabled
No missing modules
Setup info
About 100 modules: 70 contrib, 30 custom
Drupal core and modules are on NFS server
apc.stat=1 , apc.stat_ctime=Off, apc.ttl=3600
php.ini - realpath_cache_size=512k
settings.php - database set via IP (not hostname)
Mysql - query_cache_size no effect with both enabled or disabled
Mysql - innodb_flush_log_at_trx_commit =2
Mysql - innodb_buffer_pool_size=4G #current DB is 100mb total
DB queries are < 110 ms. XHprof snapshots below.
Update1: Login after few silent hours
Update2: Update.php XHprof timing
Update: NFS info
%nfsstat -m Flags: rw,nosuid,nodev,relatime,vers=3,rsize=1048576,wsize=1048576,namlen=255,hard,proto=tcp,timeo=600,retrans=2,sec=sys,mountaddr=xx.xx.xx.xx,mountvers=3,mountport=xxxx,mountproto=udp,local_lock=none,addr=xx.xx.xx.xx
Any suggestions to improve load times?
Update 3: Cache configurations in settings.php When I enable and run test for cache and APC cache using Drupal's Testing module. I get fatal errors with "Class 'Database' not found"
I am using APC cache module, below are my settings. Is something wrong with this config. APC has 192MB and used about 110MB
/**** * APC Caching. ****/ $conf['cache_backends'][] = 'sites/XYZ/modules/apc/drupal_apc_cache.inc'; // cache - is used for all common cache purposes. is a default cache bin for Drupal. $conf['cache_class_cache'] = 'DrupalAPCCache'; $conf['cache_class_cache_admin_menu'] = 'DrupalAPCCache'; // cache_block - is used for storing block's cache $conf['cache_class_cache_block'] = 'DrupalAPCCache'; $conf['cache_class_cache_bootstrap'] = 'DrupalAPCCache'; $conf['cache_class_cache_field'] = 'DrupalAPCCache'; // cache_filter - is used for storing filtered input $conf['cache_class_cache_filter'] = 'DrupalAPCCache'; // cache_form - is used for storing forms. // This cache bin should not be assigned to volatile storage //$conf['cache_class_cache_form'] = 'DrupalAPCCache'; // use Database //$conf['cache_class_cache_image'] = 'DrupalAPCCache'; $conf['cache_class_cache_libraries'] = 'DrupalAPCCache'; // cache_menu - is used for storing assembled and processed menu $conf['cache_class_cache_menu'] = 'DrupalAPCCache'; // cache_page - is used to store cached pages //$conf['cache_class_cache_page'] = 'DrupalAPCCache'; $conf['cache_class_cache_path'] = 'DrupalAPCCache'; $conf['cache_class_cache_path_breadcrumbs'] = 'DrupalAPCCache'; // cache_update - if module Update status' is enabled this // bin stores Drupal, modules and themes update information. $conf['cache_class_cache_update'] = 'DrupalAPCCache'; //$conf['apc_show_debug'] = TRUE; // Remove the slashes to use debug mode. /***** * Contributed module cache ****/ // Browscap module $conf['cache_class_cache_browscap'] = 'DrupalAPCCache'; // Entity cache module // This will cache items in Database when not pointed to another cache // There is no way to disable this caching for particular entity, it is // all or nothing, erasing the potential little benefit for enabling this // module for caching entity_user to increase performance of web services /* //$conf['cache_class_cache_entity_comment'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_file'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_node'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_taxonomy_term'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_taxonomy_vocabulary'] = 'DrupalAPCCache'; $conf['cache_class_cache_entity_user'] = 'DrupalAPCCache'; */ //Panels module $conf['cache_class_cache_panels'] = 'DrupalAPCCache'; // Registration module //$conf['cache_class_cache_entity_registration'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_state'] = 'DrupalAPCCache'; //$conf['cache_class_cache_entity_type'] = 'DrupalAPCCache'; // Rules module $conf['cache_class_rules'] = 'DrupalAPCCache'; // Token module $conf['cache_class_cache_token'] = 'DrupalAPCCache'; // View module $conf['cache_class_cache_views'] = 'DrupalAPCCache'; //$conf['cache_class_cache_views_data'] = 'DrupalAPCCache'; // Default DB for the ones that change too frequently and are small $conf['cache_default_class'] = 'DrupalDatabaseCache'; // THIS MUST BE SERVED FROM DB FOR STABILITY $conf['cache_class_cache_form'] = 'DrupalDatabaseCache';
If using NFS I highly recommend using apc.stat=0
and then if you want to update the apc cache run apc_clear_cache('opcode');
.
Seeing how drupal_parse_info_file() is ran on every page load I'm guessing this core patch will help you out: https://www.drupal.org/node/1081266#comment-9411015
Another thing that can help with running code from a NFS drive is this issue: https://www.drupal.org/node/1443308
Also related to potential NFS issues these 2 modules usually help in that situation
https://www.drupal.org/project/imageinfo_cache
https://www.drupal.org/project/advagg
It seems your top time consuming function is ob_flush()
which is called only once, but for 200-500ms.
This call is invoked in drupal_page_footer()
as follow:
function drupal_page_footer() { // ... if (variable_get('cache', 0) && ($cache = drupal_page_set_cache())) { drupal_serve_page_from_cache($cache); } else { ob_flush(); }
So in both of your cases cache doesn't work, either by the 1st load or for the reason that the page was loaded by authenticated user (drupal_page_is_cacheable()
). So probably nothing that we can do here.
Function ob_flush()
send the contents of the output buffer to the client, and the latency of this transport to the client is probably higher than the actually PHP buffer flushing. See: Why does calling ob_flush() slow down my latency so much?.
Here are few ideas how to improve the load times:
enable/disable zlib.output_compression
(and see which option is quicker),
test for network bottlenecks, if the problem is not with NFS server by checking the load times of simple PHP files (such as update.php
or plain php files),
if your buffer is flushed too slow, something holds the buffer until the page has finished loading, this can be caused by some Apache modules or client it-self,
if it's server fault, review your Apache modules and APC settings (you can use strace
to investigate the problem by debugging your Apache process when it handles the request),
if it's client fault, test your page by disabling plugins or use different web browser, as well as disable any antivirus softwares (which can hold the buffer until it's checked for web viruses)
install XCache instead of APC, set xcache.count
to your cpu count something between 4-8 (check sample xcache.ini).
xcache.count
to your # of CPUs, like 4-8). – kenorb Feb 20 '15 at 23:09
Submitted by jeremy.zerr on Fri, 01/25/2013 - 15:49
When troubleshooting performance problems with any web site, I first look at the problem to try and break it down into pieces. Where is the biggest problem? One tool I use to do that is Firebug. If you don't know much about Firebug, read my article Using Firebug to Figure out Why Your Website is Running Slow.
The first attempt to break down performance problems in to pieces results in finding out if the problem is with the initial page request, or the subsequent assets that are loaded. See this Firebug screenshot of the Net panel:
When I talk about the "initial page request", I'm talking about the very first line, the www.jeremyzerr.com one. That first request is requesting the entire HTML source of the page. That entire source needs to be downloaded, then the web browser knows to make a bunch more requests for assets. This would be all the lines from the 2nd one on, includes CSS, Javascript, Images.
This article will talk about improving the performance of this intial page request, I will cover improving the subsequent asset loading in an upcoming blog post.
I will list out what to look at in the order of likelihood of being the cause of your problem in a typical Drupal site. I typically follow a strategy like this to save time and getting right to the problem.
its important to note the time above from the Firebug output. It is 516ms. When looking at these options, you want to be able to figure out how to break down that time into different components, and also remember what it was initially so you can change one thing, test, repeat.
Too Many Database Queries Needed to Generate the Page
To see how many database queries are needed, and how long they take, use the Devel module. Go to its configuration at Configuration | Development | Devel Settings. Select the checkbox for "Display Query log", and also select to Sort By duration, it is more useful than sorting by source. Save those settings, then visit the page that is slow. At the bottom of the page, you will see some extra output that looks like this:
There are a few important items here. You see the overal number of queries, the total time it took them to execute, and for each query you see the time and number of executions.
We want this information not only to look at it and see if any queries are taking too long to run, but we also want to use it as a base for our benchmarking when we start making changes.
There are a few ways we can reduce the number and overall time of access to the database.
Page and Block Caching
What page caching does is that instead of using all those queries to each get information used in making the web page, the contents of the web page are stored in a separate database cache table so that it can be recalled quicker. If you have 10 people visiting the site from different computers, Drupal first looks into the database cache table to see if the page is there, if it is, it just gives them the page. Think of saving the output of 50 separate queries so that is accessible with a single query. You obviously are reducing the SQL queries required by a lot. What the page cache table actually stores is HTML content.
One gotcha with this Page Caching is that it only works to optimize the page load time for Anonymous users. This is because when you are logged in, you might have blocks that show up on the page that are customized for you, if it served everybody the same page, they would see your customized information (think of My Recent Posts), so Drupal does not use the Page Cache for Authenticated users automatically. This allows you to turn Page Caching on and still get the benefit for Anonymous user page load times, but does not break the site for Authenticated users.
There is another caching setting for "Cache blocks" that helps to optimize the site for Authenticated users, it fills in the gaps by caching those blocks that might be different per user. Takes up more space in the cache, but it is better than nothing.
To enable Page Caching, you go to Configuration | Development and select the checkbox next to "Cache pages for anonymous users". Also select the "Cache blocks" checkbox, this is what works for Authenticated users, blocks are cached, which means they can be assembled into an entire page easier. See screenshot:
To show you how big of an impact this can have, take a look at a Firebug output before turning on caching and viewing a page as an Anonymous user:
And after turning on caching:
You can see it shows the page loading in about 1/3 of the time. Remember when benchmarking that the first request to a page will fill the cache, the 2nd request will use the cache.
To take this one step further, you can change out your Drupal caching engine to not store to a database table, but to instead store it in memory using Memcached. So if you have plenty of RAM on your server, you can eliminate a LOT of database queries and operate even faster.
Remember what caching is though, a whole page is stored in the database and always served up. What if you actually change that page, like you make a new blog post and want your home page to show it. With page caching on, it will not show up until the cache is cleared. By default, with Drupal, the cache is cleared every time cron is run. So as always, its a tradeoff. You can clear the cache manually each time you post something new, or if its OK that a new post doesn't show up for a few hours (based on your Drupal cron period setting), then you can take advantage of some serious performance improvements.
Some of the extra settings on the Performance page also deal with this, there are settings for Minimum Cache Lifetime, and Expiration of Cached pages. See this screenshot:
So you can even further fine tune how long you would like your cached entries to live. Just be realistic about the need to show the latest content. If you are posting a few times a day, can do with hours, if you only post a few times a week, a day is just fine. But also if you want to post and then push links out to social sites about your content, you might want to clear cache manually.
As a final note, along with page and block caching, if you have a lot of Drupal Views that have blocks or pages showing slow performance, you have to make a special trip into the Views settings and change the cache settings there. You can fine tune the cache settings per View, and even separately for Blocks and Pages within a single View. Hopefully if you have a Views block or page causing you performance issues, you see that in the Devel query log and can pinpoint it back to which View it is coming from.
More Caching, MySQL Query Caching
A quick, easy thing to do to reduce the burden of lots of really small, simple database queries is to use the MySQL Query Cache. This sets aside a portion of memory to save the output of a database query so that it can be looked up if the output of the query has not changed since the last time you issued the query. Basically, if a particular database table has not had any changes to it, then any queries on that table can go in the query cache and stay there. As soon as a change happens to a table, all queries on that table that are in the query cache are invalidated.
Long story short, just give a small amount of memory to it, like 8M or 16M. By default, it is not enabled at all in the MySQL distributions that I use most, which is why its worthwhile to at least turn it on. Because of its low-level interaction with the database, it does not require any application changes.
Is your Drupal Page Using Too Much Memory?
Another slowdown possibility once you have taken care of all the database stuff is that you just have too much traffic, and your Apache web server is configured to accept a lot of connections, but your web server does not have enough memory to serve all those connections. Or it isn't configured to handle the connections you are getting, and they have to wait until another connection frees up.
Both situations cause web performance to grind to a halt, either from running out of RAM, which causes Virtual Memory disk I/O in the first case, or in the second case your requests have to pause until other requests are handled.
Another setting in the Drupal devel module helps you figure out how much memory it takes to load a page. Select the checkbox for "Display memory usage":
Then go to your slow page and look at the bottom for output that looks like this:
Your page will likely have a lot more, I'm showing this memory usage from a demo site that does not have much being loaded on the page.
The setting we look at in Apache to see how many connections we can handle is the MaxClients setting in apache.conf. If you look in your Apache error log, you can see if you have been hitting this limit, it will say that you have reached your MaxClients limit. If you look at your utilized swap space using the Linux command "top" and see that its increasing, or is non-zero, inspect the processes and see how much RAM they are using. The solution to these issues is increase your MaxClients if you are running into the connection problem. If you are hitting max RAM and still want people to use your web site, get a bigger web server with more RAM.
You can try and make Drupal use less memory by disabling modules, but in almost all cases, this is not an option as it would reduce functionality of your site. Just pay a little more for web hosting. Another pretty easy thing to do is to free RAM up on your web server by moving your database off onto another server, so you free up any RAM you had allocated to MySQL. Its always a good idea to do this anyways, and is typically one of the first things to look at when scaling from the bare bones web server + database on a single server.
Too Many PHP Files Being Interpreted
PHP is an interpreted language, which means the files have to be reduced down into opcodes in order to actually be executed by the server. One of the things you gain by using Drupal is flexibility, but you sacrifice that in terms of overhead of all those PHP files that need to be called to find all the hooks to run. Luckily, there is an option out there that will store the intermediate code of PHP files in memory so that every request does not result in fetching all those PHP files off disk and interpreting the files every time.
The component is APC, the Alternative PHP Cache, sometimes called a PHP accelerator.
All you do is edit a section in your php.ini file, allocate some memory for it, and turn it on. By turning it on, I mean use the option apc.stat = 1 that checks the timestamp of the file first to see if the file has been modified before it grabs it from the cache. That allows a development process to work smoother so as soon as you release code, it will take the new copy.
Just set:
apc.enabled = 1
apc.shm_size = 16M
apc.stat = 1
I have run into some problems if your release process involves doing a svn export over the top of your code. I still do it, but I've added in a command that clears the APC cache after I export the code so that I make sure the new files are being run. That is just a given part of my development scripts that is an acceptable for the benefit you get for it.
While I recommend this for Drupal, I cannot recommend for Wordpress with any certainty. I've had Wordpress sites that just white screen due to APC problems that weren't having code changed, has remained a mystery to this day, I'm not saying don't do it, just be careful and you can't say I didn't warn you. And these were running on the same server as Drupal sites using APC that were running fine.
Not Covering All Possibilities, Just the Big Ones
So there are a lot of additional little things to look at, but in my experience, these are the most likely culprits when your initial page load speed is suffering.
Angular vs. React - Framework Deathmatchjeremy.zerr | ||
Web apps that work offline and sync using React, Redux, and PouchDBjeremy.zerr | ||
Angular 2 with ngrx/storejeremy.zerr | ||
State of Angular Presentationjeremy.zerr | ||
Boise Code Camp 2016 Presentationsjeremy.zerr | ||
Addition to AngularJS Component Refactoring Presentationjeremy.zerr | ||
AngularJS 1.x Component-based Designjeremy.zerr | ||
React + Redux Design Lessons Presentation at Boise Frontend Development Meetupjeremy.zerr | ||
AngularJS Guest Lecture at Boise State Universityjeremy.zerr | ||
AngularJS Directive Best Practicesjeremy.zerr |
http://www.jeremyzerr.com/improving-performance-drupals-initial-page-request 有大用