Performance issue with dedicated server

Events happening in the community are now at Drupal community events on www.drupal.org.
newbuntu's picture

I have a dedicated server:
Intel® Celeron® 1.8 GHz, 1GB RAM
CentOS 5, Apache 2.2.3, MySQL 5, PHP 5.1.6
drupal 6.11 with a handful modules enabled
My site has moderate number of nodes (in the thousands).

The only enabled modules which are significant are "views" and CCK.

I have turned on caching. When I hit my site as visitors, I can see my CPU load stays at about 4%. However, if I hit the site as a logged in user (authenticated), a single hit will cause CPU to surge to 40~60% (combined httpd and mysqld CPU usage). If I hit the site with 3 or 4 authenticated users, CPU will peg over 90%. Requests take 4~8 seconds or longer to respond if they do not time out.

My fundamental question is: is this normal?

I have done a fair amount of search and tweaking. I found a close comparison: http://drupal.org/node/215516. If this kind of performance is expected, then what kind of server do I need so I can support roughly 5~10 concurrent authenticated users?

Does anyone know what kind of server drupal.org site uses? I think drupal.org has tens of thousands visitors on a regular basis.

I am currently conducting an ad hoc benchmarking. I used "top" command in a putty window. So the measurement is independent of my local computer or browser. Then I use browser to hit the server and observe the load change in the putty window.

I just installed a vanilla Drupal 6.14 on the server (not a single configuration change) and ran some quick tests.

I got some consistent numbers. mysqld cpu usage is minimum, response time is ok (~1 second). Hit with 3 browsers (authenticated), reponse is ok. On the average, a page hit causes 16% CPU with httpd, any real operations (editing, login/logout) causes load go up (to 20~30%).

The good news is the load is significantly below 40~50% CPU load. However, this is a blank install, without a single customer node or anything. I am afraid that 16~30% load will shoot up quickly once I start add something. What are you guys opinion on these numbers?

Below are some details:

Authenticated user httpd load (single user):
----------------------
login 30% (some times 15-18%) - actual login process
logout 30% (some times 15%)
home page 15.5%

my account page 15.0%
  view              16.2%  (click view tab)   
  edit              18.2%  (edit tab)

Create Content  15.5% 
  page 22.0% (click page tab)
  story 22.0% (story tab)
 
Visitor
-------------
Home 13-16%
Create New Acct    16%

I went on enabled "forum, contact, path, php filter, upload", but I didn't add any contents. The performance is basically the same as above, with a minor 2% CPU increase here and there. I also enabled caching, which lower the CPU load to 2% on Home / Create New Account pages for visitors.

I plan to add "Views" and CCK modules and add some contents, then test it again.

Comments

Here are my config files, if

newbuntu's picture

Here are my config files, if anyone sees any problems, please let me know.

apache

ServerTokens OS
ServerRoot "/etc/httpd"
PidFile run/httpd.pid
Timeout 120
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 2
<IfModule prefork.c>
StartServers       8
MinSpareServers    5
MaxSpareServers   20
ServerLimit      256
#MaxClients       256
MaxClients       128
MaxRequestsPerChild  4000
</IfModule>
<IfModule worker.c>
StartServers         2
MaxClients         256
MinSpareThreads     32
MaxSpareThreads     64
ThreadsPerChild     25
MaxRequestsPerChild  0
</IfModule>

Listen 80
LoadModule auth_basic_module modules/mod_auth_basic.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule authn_file_module modules/mod_authn_file.so
LoadModule authn_alias_module modules/mod_authn_alias.so
LoadModule authn_anon_module modules/mod_authn_anon.so
LoadModule authn_dbm_module modules/mod_authn_dbm.so
LoadModule authn_default_module modules/mod_authn_default.so
LoadModule authz_host_module modules/mod_authz_host.so
LoadModule authz_user_module modules/mod_authz_user.so
LoadModule authz_owner_module modules/mod_authz_owner.so
LoadModule authz_groupfile_module modules/mod_authz_groupfile.so
LoadModule authz_dbm_module modules/mod_authz_dbm.so
LoadModule authz_default_module modules/mod_authz_default.so
LoadModule ldap_module modules/mod_ldap.so
LoadModule authnz_ldap_module modules/mod_authnz_ldap.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule logio_module modules/mod_logio.so
LoadModule env_module modules/mod_env.so
LoadModule ext_filter_module modules/mod_ext_filter.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule expires_module modules/mod_expires.so
LoadModule deflate_module modules/mod_deflate.so
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule info_module modules/mod_info.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule actions_module modules/mod_actions.so
LoadModule speling_module modules/mod_speling.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule cache_module modules/mod_cache.so
LoadModule suexec_module modules/mod_suexec.so
LoadModule disk_cache_module modules/mod_disk_cache.so
LoadModule file_cache_module modules/mod_file_cache.so
LoadModule mem_cache_module modules/mod_mem_cache.so
LoadModule cgi_module modules/mod_cgi.so
LoadModule version_module modules/mod_version.so

Include conf.d/.conf
UseCanonicalName Off
DocumentRoot "/var/www/html"
<Directory />
    Options FollowSymLinks
    AllowOverride None
</Directory>
<Directory "/var/www/html">
    Options Indexes FollowSymLinks
    AllowOverride All
    Order allow,deny
    Allow from all
</Directory>

<IfModule mod_userdir.c>
    UserDir disable
</IfModule>

AccessFileName .htaccess
<Files ~ "^.ht">
    Order allow,deny
    Deny from all
</Files>
TypesConfig /etc/mime.types
DefaultType text/plain
<IfModule mod_mime_magic.c>
    MIMEMagicFile conf/magic
</IfModule>
HostnameLookups Off
ErrorLog logs/error_log
LogLevel warn
CustomLog logs/access_log combined
ServerSignature On
Alias /icons/ "/var/www/icons/"
<Directory "/var/www/icons">
    Options Indexes MultiViews
    AllowOverride None
    Order allow,deny
    Allow from all
</Directory>
<IfModule mod_dav_fs.c>
    DAVLockDB /var/lib/dav/lockdb
</IfModule>

ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<Directory "/var/www/cgi-bin">
    AllowOverride None
    Options None
    Order allow,deny
    Allow from all
</Directory>

IndexOptions FancyIndexing VersionSort NameWidth=

AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
AddIconByType (TXT,/icons/text.gif) text/
AddIconByType (IMG,/icons/image2.gif) image/

AddIconByType (SND,/icons/sound2.gif) audio/
AddIconByType (VID,/icons/movie.gif) video/


AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core

AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
DefaultIcon /icons/unknown.gif

ReadmeName README.html
HeaderName HEADER.html

IndexIgnore .??* ~ *# HEADER README* RCS CVS *,v *,t

AddLanguage ca .ca
AddLanguage cs .cz .cs
AddLanguage da .dk
AddLanguage de .de
AddLanguage el .el
AddLanguage en .en
AddLanguage eo .eo
AddLanguage es .es
AddLanguage et .et
AddLanguage fr .fr
AddLanguage he .he
AddLanguage hr .hr
AddLanguage it .it
AddLanguage ja .ja
AddLanguage ko .ko
AddLanguage ltz .ltz
AddLanguage nl .nl
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pl .po
AddLanguage pt .pt
AddLanguage pt-BR .pt-br
AddLanguage ru .ru
AddLanguage sv .sv
AddLanguage zh-CN .zh-cn
AddLanguage zh-TW .zh-tw

LanguagePriority en ca cs da de el eo es et fr he hr it ja ko ltz nl nn no pl pt pt-BR ru sv zh-CN zh-TW

ForceLanguagePriority Prefer Fallback
AddDefaultCharset UTF-8
AddCharset ISO-8859-1  .iso8859-1  .latin1
AddCharset ISO-8859-2  .iso8859-2  .latin2 .cen
AddCharset ISO-8859-3  .iso8859-3  .latin3
AddCharset ISO-8859-4  .iso8859-4  .latin4
AddCharset ISO-8859-5  .iso8859-5  .latin5 .cyr .iso-ru
AddCharset ISO-8859-6  .iso8859-6  .latin6 .arb
AddCharset ISO-8859-7  .iso8859-7  .latin7 .grk
AddCharset ISO-8859-8  .iso8859-8  .latin8 .heb
AddCharset ISO-8859-9  .iso8859-9  .latin9 .trk
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5        .Big5       .big5
# For russian, more than one charset is used (depends on client, mostly):
AddCharset WINDOWS-1251 .cp-1251   .win-1251
AddCharset CP866       .cp866
AddCharset KOI8-r      .koi8-r .koi8-ru
AddCharset KOI8-ru     .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-8       .utf8
AddCharset GB2312      .gb2312 .gb
AddCharset utf-7       .utf7
AddCharset utf-8       .utf8
AddCharset big5        .big5 .b5
AddCharset EUC-TW      .euc-tw
AddCharset EUC-JP      .euc-jp
AddCharset EUC-KR      .euc-kr
AddCharset shift_jis   .sjis

AddType application/x-compress .Z
AddType application/x-gzip .gz .tgz
AddHandler imap-file map
AddHandler type-map var

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

<IfModule mod_negotiation.c>
<IfModule mod_include.c>
    <Directory "/var/www/error">
        AllowOverride None
        Options IncludesNoExec
        AddOutputFilter Includes html
        AddHandler type-map var
        Order allow,deny
        Allow from all
        LanguagePriority en es de fr
        ForceLanguagePriority Prefer Fallback
    </Directory>
</IfModule>
</IfModule>

BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4.0" force-response-1.0
BrowserMatch "Java/1.0" force-response-1.0
BrowserMatch "JDK/1.0" force-response-1.0
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
BrowserMatch "^WebDAVFS/1.[012]" redirect-carefully
BrowserMatch "^gnome-vfs" redirect-carefully

NameVirtualHost *:80

php
[PHP]
engine = On
zend.ze1_compatibility_mode = Off
short_open_tag = On
asp_tags = Off
precision    =  14
y2k_compliance = On
output_buffering = 4096
zlib.output_compression = Off
implicit_flush = Off
unserialize_callback_func=
serialize_precision = 100
allow_call_time_pass_reference = Off
safe_mode = Off
safe_mode_gid = Off
safe_mode_include_dir =
safe_mode_exec_dir =
safe_mode_allowed_env_vars = PHP_
safe_mode_protected_env_vars = LD_LIBRARY_PATH
disable_functions =
disable_classes =
expose_php = On
max_execution_time = 30     ; Maximum execution time of each script, in seconds
max_input_time = 60    ; Maximum amount of time each script may spend parsing request data
memory_limit = 120M      ; Maximum amount of memory a script may consume (8MB)
error_reporting  =  E_ALL
display_errors = Off
display_startup_errors = Off
log_errors = On
log_errors_max_len = 1024
ignore_repeated_errors = Off
ignore_repeated_source = Off
report_memleaks = On
track_errors = Off
variables_order = "EGPCS"
register_globals = Off
register_long_arrays = Off
register_argc_argv = Off
auto_globals_jit = On
post_max_size = 15M
magic_quotes_gpc = Off
magic_quotes_runtime = Off
magic_quotes_sybase = Off
auto_prepend_file =
auto_append_file =
default_mimetype = "text/html"
doc_root =
user_dir =
extension_dir = "/usr/lib/php/modules"
enable_dl = On
file_uploads = On
upload_max_filesize = 15M
allow_url_fopen = On
default_socket_timeout = 80
[Date]
[Syslog]
define_syslog_variables  = Off
[mail function]
SMTP = localhost
smtp_port = 25
sendmail_path = /usr/sbin/sendmail -t -i
[SQL]
sql.safe_mode = Off
[ODBC]
odbc.allow_persistent = On
odbc.check_persistent = On
odbc.max_persistent = -1
odbc.max_links = -1
odbc.defaultlrl = 4096
odbc.defaultbinmode = 1
[MySQL]
mysql.allow_persistent = On
mysql.max_persistent = -1
mysql.max_links = -1
mysql.default_port =
mysql.default_socket =
mysql.default_host =
mysql.default_user =
mysql.default_password =
mysql.connect_timeout = 80
mysql.trace_mode = Off
[MySQLi]
mysqli.max_links = -1
mysqli.default_port = 3306
mysqli.default_socket =
mysqli.default_host =
mysqli.default_user =
mysqli.default_pw =
mysqli.reconnect = Off
[mSQL]
msql.allow_persistent = On
msql.max_persistent = -1
msql.max_links = -1
[PostgresSQL]
pgsql.allow_persistent = On
pgsql.auto_reset_persistent = Off
pgsql.max_persistent = -1
pgsql.max_links = -1
pgsql.ignore_notice = 0
pgsql.log_notice = 0
[Sybase]
sybase.allow_persistent = On
sybase.max_persistent = -1
sybase.max_links = -1
sybase.min_error_severity = 10
sybase.min_message_severity = 10
sybase.compatability_mode = Off
[Sybase-CT]
sybct.allow_persistent = On
sybct.max_persistent = -1
sybct.max_links = -1
sybct.min_server_severity = 10
sybct.min_client_severity = 10
[bcmath]
bcmath.scale = 0
[browscap]
[Informix]
ifx.default_host =
ifx.default_user =
ifx.default_password =
ifx.allow_persistent = On
ifx.max_persistent = -1
ifx.max_links = -1
ifx.textasvarchar = 0
ifx.byteasvarchar = 0
ifx.charasvarchar = 0
ifx.blobinfile = 0
ifx.nullformat = 0
[Session]
session.save_handler = files
session.save_path = "/var/lib/php/session"
session.use_cookies = 1
session.name = PHPSESSID
session.auto_start = 0
session.cookie_lifetime = 0
session.cookie_path = /
session.cookie_domain =
session.serialize_handler = php
session.gc_probability = 1
session.gc_divisor     = 1000
session.gc_maxlifetime = 1440
session.bug_compat_42 = 0
session.bug_compat_warn = 1
session.referer_check =
session.entropy_length = 0
session.entropy_file =
session.cache_limiter = nocache
session.cache_expire = 180
session.use_trans_sid = 0
session.hash_function = 0
session.hash_bits_per_character = 5
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
mssql.allow_persistent = On
mssql.max_persistent = -1
mssql.max_links = -1
mssql.min_error_severity = 10
mssql.min_message_severity = 10
mssql.compatability_mode = Off
mssql.secure_connection = Off
[Assertion]
[Verisign Payflow Pro]
pfpro.defaulthost = "test-payflow.verisign.com"
pfpro.defaultport = 443
pfpro.defaulttimeout = 30
[COM]
[mbstring]
[FrontBase]
[exif]
[Tidy]
tidy.clean_output = Off
[soap]
soap.wsdl_cache_enabled=1
soap.wsdl_cache_dir="/tmp"
soap.wsdl_cache_ttl=86400
max_allowed_packet=32M
;http://groups.drupal.org/node/29270#comments
realpath_cache_size=1M

mysql
[mysqld]
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
old_passwords=1

#http://groups.drupal.org/node/29232#comments
key_buffer_size=512M
delay_key_write=ALL

[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid

the drupal core cache, just

bennos's picture

the drupal core cache, just caches anonymus user. try cache modules like memcache, cacherouter or authcache.
a smal memcache instance with 128 MB or 256 MB will be a solution for your problem.

That's your entire MySQL

Jamie Holly's picture

That's your entire MySQL config? If that's the case then there's your problem (the config from the comment you have listed there is just in addition to standard configs). You don't have any caches or buffers being configured on MySQL. Run these two queries and give us the output:

SHOW variables LIKE '%buffer%'
SHOW variables LIKE '%cache%'

HollyIT - Grab the Netbeans Drupal Development Tool at GitHub.

Thanks for helping out. Here

newbuntu's picture

Thanks for helping out. Here is the output

mysql> SHOW variables LIKE '%buffer%';
+-------------------------------+-----------+
| Variable_name                 | Value     |
+-------------------------------+-----------+
| bdb_log_buffer_size           | 32768     |
| bulk_insert_buffer_size       | 8388608   |
| innodb_buffer_pool_awe_mem_mb | 0         |
| innodb_buffer_pool_size       | 8388608   |
| innodb_log_buffer_size        | 1048576   |
| join_buffer_size              | 131072    |
| key_buffer_size               | 536870912 |
| myisam_sort_buffer_size       | 8388608   |
| net_buffer_length             | 16384     |
| preload_buffer_size           | 32768     |
| read_buffer_size              | 131072    |
| read_rnd_buffer_size          | 262144    |
| sort_buffer_size              | 2097144   |
+-------------------------------+-----------+
13 rows in set (0.00 sec)

mysql> SHOW variables LIKE '%cache%';
+------------------------------+------------+
| Variable_name                | Value      |
+------------------------------+------------+
| bdb_cache_size               | 8388600    |
| binlog_cache_size            | 32768      |
| have_query_cache             | YES        |
| key_cache_age_threshold      | 300        |
| key_cache_block_size         | 1024       |
| key_cache_division_limit     | 100        |
| max_binlog_cache_size        | 4294967295 |
| query_cache_limit            | 1048576    |
| query_cache_min_res_unit     | 4096       |
| query_cache_size             | 0          |
| query_cache_type             | ON         |
| query_cache_wlock_invalidate | OFF        |
| table_cache                  | 64         |
| thread_cache_size            | 0          |
+------------------------------+------------+
14 rows in set (0.00 sec)

You don't have the

Jamie Holly's picture

You don't have the query_cache_size set, so there is no query caching going on. I would add something like:

query_cache_size=32mb for starters then run it sum and use the tuning-primer script to see what size it figures you should have.

Also grab the devel module and install it. After that enable query logging and output. Then you can look in the footer of your page and see how long each query is taking. There's a chance you have some nasty query running that is doing some heavy processing - most likely file sorting.

Once you are satisfied that MySQL is running right, then I would look at installing APC to handle op-code caching. That can give a 20-30% reduction of resources used for PHP. If you have enough RAM on the server then you can install the cacherouter module and have it use APC's user object caching to handle Drupal's caching.


HollyIT - Grab the Netbeans Drupal Development Tool at GitHub.

Hi intoxination, thanks for

newbuntu's picture

Hi intoxination,

thanks for the comment. I tried query_cache_size=32mb and didn't find any difference.

Can you recommend a tuning primer script? I checked online, they were so many versions.

Do you see anything I can tweak in httpd.conf or php.ini?

Thx!

tuning-primer.sh

christefano's picture

I recommend the MySQL tuning script at http://www.day32.com/MySQL/

well, i realized that the

newbuntu's picture

well, i realized that the changes i put in /etc/my.cnf didn't take effect, even if I rebounced mysqld. So I used mysql command to set the query_cache_size to 32M. I tested the site after that, and still did not see improvement.

Does anyone know why "query_cache_size=32M" didn't take effect in /etc/my.cnf? I did a global search on the server, that's the only my.cnf I can find.

I wonder if the problem is in httpd.cnf, because it's httpd that shows high CPU usage.

Thanks!

Sometimes the httpd will show

Carl Johan's picture

Sometimes the httpd will show a high cpu usage since it's running php, and php is waiting for the database to return data.

Apache too fat

playfulwolf's picture
  1. you are runnin prefork or worker? if worker - your settings too fat, I recommend to google for "low memory apache" or similar and look at all the advice.
  2. Install APC or eAccelerator and configure Drupal Cacherouter module for them
  3. www.mysqlperformanceblog.com - practical MySQL tunning blog. From your configuration I see that you are running default settings, which are good for nothing. Disable InnoDB, BDB engines as you probably need just MyISAM. Also, which version are you running? Your other settings also are too fat.
  4. Do overall tunning for your dedicated box - sometimes you get them from providers in really slow configurations, your provider forum should have lots of resources about that.

drupal+me: jeweler portfolio

APC

joshk's picture

The single biggest win you'll get is from installing APC.

Also, as noted, you should put apache on a diet.

Finally, use memcache or cache-router to prevent expensive drupal cache queries to the database, and expensive php unserialization calls on the results.

Thanks to everyone for your

newbuntu's picture

Thanks to everyone for your help!!!

I installed APC, already saw big improvement! I'll continue testing with the other recommendations.

I am relatively happy with

newbuntu's picture

I am relatively happy with the visitor pages now.

I'm looking for a cache module that can somewhat support authenticated users. I found some good effort for 7.x (http://drupal.org/node/495968).

Any recommendations for 6.x before 7.x becomes available?

look at Cacherouter, Memcache

bennos's picture

look at Cacherouter, Memcache API and Authcache (http://drupal.org/project/authcache).
All three are cache modules for non-anonymus user.

High performance

Group notifications

This group offers an RSS feed. Or subscribe to these personalized, sitewide feeds: