Memory Usage in WordPress 2.0.2

Posted on Mon, 29th May 2006 at 07:39 under Software, Reviews, Skills, WordPress, Education, Coding, Publicity

I’m a sensitive soul with computers. Whilst I appreciate the incredible power and capacity that modern computers provide, I cannot help but remember those hazy days during my youth when I learned how to program. My first computer was modest by today’s standards - a Sinclair ZX81 with 8Kb of ROM (including a built-in BASIC interpreter) and 1Kb of RAM. That was enough for some but I didn’t really get started until I had 16Kb of RAM. That was enough for me and my skills at the time. I proceeded to write computer games.

WordPress is a personal publishing system designed to work on modern servers. Servers are enormous. The server that hosts this blog has 125,000 times more RAM than my first computer. My blog may use only 8MB, a limit enforced by the programming language that the blog uses; PHP.

So how does WordPress fill this tiny pocket of the big machine? Today I’m looking at the memory footprint of WordPress 2.0.2. How efficiently does WordPress use its most precious resource?

PHP provides limited memory diagnostic tools as standard. One. memory_get_usage() returns the amount of memory, in bytes, currently allocated to the running PHP script.

Plan

PHP alone

  <p><?php echo memory_get_usage();?></p>

Default installation (no plugins, default theme, default data);

Default installation (no plugins, default theme), with posts and comments;

Memory Probing Plugin For WordPress

WordPress Component RAM Usage

Core
Caches
Admin Interface
Plugins

Same Tests On Latest SVN WordPress
Same Tests With PHP4

7 Responses

  1. Baseline PHP Script Memory Usage

    The tests are all run on my localhost environment, an AMD K7 running Ubuntu Linux (Dapper Drake).

    paul@kubuntu:~/public_html/wp-memtest$ cat > memtest.php
    <p> <?php echo memory_get_usage(); ?> </p>
    paul@kubuntu:~/public_html/wp-memtest$ php -v
    PHP 5.1.2 (cli) (built: May 24 2006 16:16:33)
    Copyright (c) 1997-2006 The PHP Group
    Zend Engine v2.1.0, Copyright (c) 1998-2006 Zend Technologies
    paul@kubuntu:~/public_html/wp-memtest$ php memtest.php
    <p> 38704 </p>
    paul@kubuntu:~/public_html/wp-memtest$ lynx –dump http://localhost/~paul/wp-memtest/memtest.php

    34816

    I’ll take that as 40 kilobytes.

    Reply
  2. Baseline WordPress 2.0.2 Memory Usage

    A standard installation of WordPress 2.0.2 on a new MySQL database. The main thing I want to avoid doing is running the Dashboard, which I know to have an effect, albeit minor, on the overall WordPress memory usage. I rename wp-admin/index.php to .index.php.

    Before first run I must patch the source at the correct places to give a baseline memory reading. Here I have a cunning plan. WordPress is a very customisable program due to its plugin architecture. At many points throughout the WordPress program, third-party modules can be hooked in to do just about anything. I’m going to patch the plugin points to give a readout of the memory usage throughout an entire run of the WordPress program.

    To the top of function do_action() in wp-includes/functions.php I add a single line:

    global $memory_graph; $memory_graph[] = array( $tag => memory_get_usage() );
    

    Yes, this will increase the memory usage but I am guaranteed to get the baseline in the first few elements of the array. The size of this graph array is deterministic and can be easily and progressively eliminated from the reported memory usage.

    All this information has to go somewhere to be analysed or it ain’t much use. I’m expecting quite a lot of data and many sets of it, so I reckon I’ll serialize, gzip and dump into a timestamped file. This has to be done right at the end of the program, which is an opportunity to get the final memory size statistic. I add the following lines to the end of index.php:

    global $memory_graph; $memory_graph[] = array( 'end', memory_get_usage() );
    file_put_contents( 'wp-content/memtest-'.date('Ymd-Hms'), gzcompress(serialize($memory_graph)) );
    

    Are we sitting comfortably? Let’s begin. :)

    First Run

    The administrative interface seems to work and allows me to update the admin profile. Does the front-stage work? Yes! The default WordPress installation seems to run. Now, do I have any memory probe files to play with? No. None. Damn!

    I check the Apache error logs to see if there’s any particular reason. Nothing. Maybe the code I added to index.php isn’t being executed.

    Checking around I find wp-includes/template_loader.php which is festooned with exit statements. My memory probe dump code isn’t being called. I’ll have to use another way: register_shutdown_function(). I amend index.php to have the following code at the top.

    function dump_memory_graph() {
      global $memory_graph; $memory_graph[] = array( 'end' => memory_get_usage() );
      file_put_contents( ABSPATH . '/wp-content/memtest-'.date('Ymd-Hms'), gzcompress(serialize($memory_graph)) );
    }
    register_shutdown_function( 'dump_memory_graph' );
    

    Second Run

    W00t! I have a 206 byte file named ‘memtest-20060529-100517′ in my wp-content directory. I need a program to dump that in a readable form. Start simple.

    First Memory Dump

    <?php
    $memory_graph = unserialize(gzuncompress(file_get_contents($_SERVER[’argv’][1])));
    foreach( $memory_graph as $index => $reading ) {
    list( $tag, $memory ) = each($reading);
    echo “$index,$tag,$memory\n”;
    }
    ?>

    paul@kubuntu:~/public_html/wp-memtest/wp-content$ php dump.php memtest-20060529-100517
    0,plugins_loaded,3276832
    1,init,3347112
    2,pre_get_posts,3327184
    3,template_redirect,3364960
    4,wp_head,3384816
    5,loop_start,3378560
    6,loop_end,3383216
    7,wp_meta,3411248
    8,wp_footer,3404016
    9,0,end

    Baseline WordPress memory usage appears to be 3.2 megabytes, comfortably under a half of the available memory limit.

    A couple of minor bug-fixes to my probes and I’m ready to start my analysis.

    Baseline WordPress Memory Usage

    0,plugins_loaded,3276736
    1,init,3347016
    2,pre_get_posts,3327088
    3,template_redirect,3364864
    4,wp_head,3384720
    5,loop_start,3378464
    6,loop_end,3383120
    7,wp_meta,3411152
    8,wp_footer,3403920
    9,end,3397160

    Reply
  3. Analysis Of Baseline WordPress Memory Usage

    WordPress needs 3MB of RAM to load and an extra 150KB to process the default content with the default theme. That’s not at all bad, for a start. Now I’ll start making the blog more realistic by adding features and content.

    Enable The Dashboard, Look At It, Look At Blog

    How much RAM does the Dashboard take if you don’t look at it? I suspect the answer is around 200KB. I rename back wp-admin/index.php, browse the Dashboard (April Fools!) then view the blog.

    php dump.php memtest-20060529-111054
    0,plugins_loaded,3276496
    1,init,3346536
    2,pre_get_posts,3326608
    3,template_redirect,3364384
    4,wp_head,3384240
    5,loop_start,3377984
    6,loop_end,3382640
    7,wp_meta,3410672
    8,wp_footer,3403440
    9,end,3396680

    No, I’m wrong. The Dashboard seems to have no effect on overall memory use. Great stuff!

    The Effect Of Content

    So far I’m only looking at the blog homepage. It has one post with one comment. I add another post, something big enough to show up on the graph. I’ll add a picture too using the inline uploading. With all the previewing and stuff, I should get quite a few probes during the process.

    Three probes to be exact. I’m not sure which one relates to which activity, so I’ll have to examine them all.

    php dump.php memtest-20060529-112348
    0,plugins_loaded,3274872
    1,init,3343544
    2,parse_query,3304032
    3,pre_get_posts,3304480
    4,template_redirect,3351696
    5,end,3372168
    php dump.php memtest-20060529-112349
    0,plugins_loaded,3274872
    1,init,3343544
    2,parse_query,3304032
    3,pre_get_posts,3304480
    4,template_redirect,3350936
    5,end,3371760
    php dump.php memtest-20060529-112353
    0,plugins_loaded,3276512
    1,init,3346568
    2,pre_get_posts,3326640
    3,template_redirect,3367688
    4,wp_head,3388000
    5,loop_start,3381880
    6,loop_end,3389064
    7,wp_meta,3414864
    8,wp_footer,3407632
    9,end,3400872

    My post appears to consume very little memory, no more than I would expect. Text doesn’t take up much space. Expand the dataset a little. Import a few hundred posts and comments. My database now comprises 64 posts and 63 categories with a total data size just over 100KB. How much memory does the homepage now use?

    Mmm… Baklava Tart

    Nothing like looking at a recipe blog to make you hungry! My drooling aside, how much trouble did these numerous new posts give WordPress?

    php dump.php memtest-20060529-114328
    0,plugins_loaded,3277800
    1,init,3348088
    2,pre_get_posts,3328232
    3,template_redirect,3441088
    4,wp_head,3454952
    5,loop_start,3447936
    6,loop_end,3460944
    7,wp_meta,3497376
    8,wp_footer,3488544
    9,end,3481720

    The trouble with looking for small things in large numbers is that the scale often confuses. The WordPress homepage deals with two things; 10 posts and the sidebar. Subtracting the latest ‘wp_meta’ (the peak memory) reading from the previous gives 82512. For now it’s just a number. Hopefully soon it will be a formula.

    Preliminary Conclusions

    So far nothing at all to worry about. WordPress seems like a model citizen, leaving more RAM available than it consumes and consuming RAM proportionate to its task. Not good enough! It must break! :)

    Reply
  4. WordPress Memory Usage Across Tasks

    The homepage alone is insufficient. I need to probe memory use across some other common tasks such as showing a single page, categories and the like. My basic assumption is that the more a page shows the more RAM is required to process it. That makes the single page view the most likely culprit for breaking memory limits, especially if there are many comments against a post.

    First, my probe code must be updated to record the requested page.

    Single Post, No Comments

    php dump.php memtest-20060529-123456
    0,plugins_loaded,3277040
    1,init,3347416
    2,parse_query,3327648
    3,pre_get_posts,3327968
    4,template_redirect,3368400
    5,wp_head,3393016
    6,loop_start,3386760
    7,comment_form,3428056
    8,loop_end,3415032
    9,wp_footer,3418176
    10,/~paul/wp-memtest/?p=36,3407384

    Sweet. As I would expect, a lower memory use than the homepage.

    Time to import a monster post with many comments. “Liberating Wordpress” will do the trick.

    Monster Post, Many Comments

    Liberating WordPress sure is a monster post. Does the memory probe reveal how monster?

    php dump.php memtest-20060529-124810 0,plugins_loaded,3276616
    1,init,3346568
    2,parse_query,3326800
    3,pre_get_posts,3327120
    4,template_redirect,3367032
    5,wp_head,3391552
    6,loop_start,3385296
    7,comment_form,3686704
    8,loop_end,3669784
    9,wp_footer,3672224
    10,/~paul/wp-memtest/?p=210,3660856

    Oh come on! Those numbers are totally useless! I can’t quickly subtract 3 million and something from 3 million and something else. I’m more interested in the delta, the change from one reading to the next. Easy.

    php dump.php memtest-20060529-124810
    0,plugins_loaded,3276616,3276616
    1,init,3346568,69952
    2,parse_query,3326800,-19768
    3,pre_get_posts,3327120,320
    4,template_redirect,3367032,39912
    5,wp_head,3391552,24520
    6,loop_start,3385296,-6256
    7,comment_form,3686704,301408
    8,loop_end,3669784,-16920
    9,wp_footer,3672224,2440
    10,/~paul/wp-memtest/?p=210,3660856,-11368

    There… much better. I can see that my post is indeed a monster, consuming 300KB during the loop. Still, that’s not bad. Time to take a tour. Take some feeds, perhaps?

    Preliminary Front-stage Analysis Complete

    I cannot find fault with the use of memory by WordPress when performing its core functions. After a short browse of the test blog, including a few searches, my final memory analysis for the homepage is as follows:

    php dump.php memtest-20060529-130805
    0,plugins_loaded,3276664,3276664
    1,init,3346704,70040
    2,pre_get_posts,3326776,-19928
    3,template_redirect,3412152,85376
    4,wp_head,3431728,19576
    5,loop_start,3425416,-6312
    6,loop_end,3445016,19600
    7,wp_meta,3483704,38688
    8,wp_footer,3474872,-8832
    9,/~paul/wp-memtest/,3468048,-6824

    Next, the admin interface.

    Reply
  5. WordPress Administrative Interface Memory Usage

    My probes are being gathered during the admin interface but not dumped. I reckon wp-admin/admin.php is a good place to register my shutdown function which dumps the memory probe data.

    First Run

    I do like it when things work first time. Especially this time, as the results confirm something I already knew.

    php dump.php admin-memtest-20060529-132332
    0,plugins_loaded,3343480,3343480
    1,init,3413632,70152
    2,admin_menu,4031776,618144
    3,admin_head,4000568,-31208
    4,admin_notices,4022600,22032
    5,update_option_rss_42109a30548dd2078da9009859b481aa_ts,4346512,323912
    6,activity_box_end,4374360,27848
    7,update_option_rss_0ff4b43bd116a9d8720d689c80e7dfd4_ts,4464528,90168
    8,update_option_rss_867bd5c64f85878d03a060509cd2f92c,4964856,500328
    9,update_option_rss_867bd5c64f85878d03a060509cd2f92c_ts,4647880,-316976
    10,admin_footer,4543160,-104720
    11,shutdown,4483112,-60048
    12,/~paul/wp-memtest/wp-admin/,4478824,-4288

    The Dashboard is a monster! It uses 4964856-3343480=1.6MB of RAM, a fifth of the total! I hope this is a limited phenomenon.

    Write A Post, Post A Picture

    Hmm… I appear to have introduced a bug. On uploading the picture for my post, the picture upload box says This script was not meant to be called directly. It worked before. Maybe a different picture. Odd, the second picture worked fine. I’ll try the first one again.

    Why does my image named emmas-flower.png upload OK but my image named emmas flower drawing.png does not? It might be the spaces in the filename, so I’ll replace them with dashes. Upload emmas-flower-drawing.png. No, same response. This script was not meant to be called directly.

    Is something wrong with the image? Oh. Yes. Duh! emmas-flower-drawing.png is 12.7MB in size! Not a hope in hell of uploading that. I’ll need to drop it in size, to under 2MB, which is the standard upload file size limit. A quick “file save as…” later and I now have a rather more svelte 750KB JPEG. Upload that. It works, almost. Although I can clearly see a thumbnail of the picture, the options menu tells me there is no thumbnail associated with the image. Whatever.

    After a bit of faffing, I post some pictures and a bit of text. What memory probe goodness have I got?

    WordPress Write Post and Inline Image Uploading Memory Use

    I have 15 probe files so I must have been doing more faffing than I thought. There are a lot from the inline uploading, as I expected. I get the feeling that I’m losing probe data due to the admin interface program being executed more than once per second. The reading I was after, the actual saving of a post, is as follows:

    php dump.php admin-memtest-20060529-135413
    0,plugins_loaded,3399288,3399288
    1,init,3472960,73672
    2,admin_menu,4090776,617816
    3,check_admin_referer,4043952,-46824
    4,publish_post,4065600,21648
    5,save_post,4241208,175608
    6,wp_insert_post,4241208,0
    7,edit_post,4270256,29048
    8,publish_post,4270256,0
    9,save_post,4271456,1200
    10,wp_insert_post,4271456,0
    11,shutdown,4262984,-8472
    12,/~paul/wp-memtest/wp-admin/post.php,4262224,-760

    Nothing unusual.

    Minor Changes To The Probe

    I ensure that the dump output filename is unique.

    Clean Sheet, Once More With A Post And Pictures

    No need to bore with the details. Overall, WordPress uses memory efficiently, apart from the Dashboard.

    Reply
  6. Nothing Unusual?

    1,init,3472960,73672
    2,admin_menu,4090776,617816

    Wait a minute! Between initialisation and admin_menu hooks being called, 600KB of RAM is consumed. I didn’t pay much attention to that earlier on because it was just there. Now I think I’ll take a closer look. If that figure could be reduced, the WP admin working set might drop below the magic 4MB limit.

    What consumes 600KB between init and menu?

    Tracing The Path Between Initialisation And The Admin Menu

    Action ‘init’ is triggered at the end of wp-settings.php, which is required by wp-config.php, which is required at the beginning of wp-admin/admin.php.

    Action ‘admin_menu’ is triggered at the end of wp-admin/menu.php.

    The code that needs to be examined lies between lines 19 to 54 of wp-admin/admin.php. The quickest way to find out what’s happening is to add more of my little memory probes. Here’s a Dashboard memory dump to get your teeth into.

    php dump.php admin-memtest-20060529-151631
    0,plugins_loaded,3347456,3347456
    1,init,3417504,70048
    2,post-admin-functions,3850776,433272
    3,post-admin-db,3949256,98480
    4,post-registration-functions,3978648,29392
    5,post-auth_redirect,3978880,232
    6,post-nocache_headers,3979000,120
    7,post-update_category_cache,3979000,0
    8,post-get_currentuserinfo,3979168,168
    9,pre-menu,3980288,1120
    10,admin_menu,4037104,56816
    11,admin_head,4003152,-33952
    12,admin_notices,4025184,22032
    13,update_option_rss_42109a30548dd2078da9009859b481aa_ts,4348832,323648
    14,activity_box_end,4376616,27784
    15,update_option_rss_0ff4b43bd116a9d8720d689c80e7dfd4_ts,4466824,90208
    16,update_option_rss_867bd5c64f85878d03a060509cd2f92c,4967152,500328
    17,update_option_rss_867bd5c64f85878d03a060509cd2f92c_ts,4650208,-316944
    18,admin_footer,4545680,-104528
    19,shutdown,4485632,-60048
    20,/~paul/wp-memtest/wp-admin/,4481344,-4288

    The inclusion of wp-admin/admin-functions.php consumes the most RAM followed by the database “abstraction” layer in wp-admin/wp-db.php. Given the nature of these files, I am not at all surprised by the scale of the memory usage so I can’t imagine I’ll find much to trim away. Best to be sure though.

    Why Do The Admin Functions Need 400KB Of RAM?

    No reason I can see. It’s just a big file that costs 400KB to load.

    Why Do The Database Functions Need 100KB Of RAM?

    This file constructs an object that connects to a database. If that only costs 100KB of RAM, fantastic!

    Reply
  7. Memory Usage of Plugins

    Your requests in a comment below please.

    Reply

Leave a Reply

You may also log in to post a comment.

XHTML:

If you want to <q>tag</q>, please balance these; a, i, em, b, strong, u, blockquote, q, ul, li, ol, abbr, code, pre, sub and sup.