Take the 2-minute tour ×

I have an unusual problem that I managed to find the root of. I am currently set up on CentOS Linux 6.3 nginx/1.0.15 PHP Version 5.3.18 PHP-FPM 5.3.18-1

I have a refresh.txt file that is written every time someone posts a shout to update the new time stamp. We also have JS checking the value of this time stamp every 1 second. Now the problem with this is.. Say 5 or more people shout at the same time writing to the refresh.txt file it will use 100% cpu. just to write a time stamp!!

I don't know why it is doing this..

Here is my php code.

    $tb_send = "clear";
    $tb_send = time();

// Add flatfile check
$tbcheck = "refresh.txt";
    $tbsend = fopen($tbcheck, 'w');
    $tbtime = $tb_send;
fwrite($tbsend, $tbtime);


talk_jax.open("GET", boardurl+"/talkbox/refresh.txt?nocache="+nocache);

How can I fix this or maybe work around this? Any help would me massively appreciated.


Edit: still no solution to this. Is there a way to limit the requests? Or is there a better way todo this all together.

I have tried APC cache, the problem with that is its not serving the php file fast enough so shouts are really slow, unless I was doing something wrong?

apc_store("refresh", time());


talk_jax.open("GET", boardurl+"/talkbox/refresh.php?nocache="+nocache);

I have also tried using a database. Its same too slow to serve the php file.

share|improve this question
do you have a database you can use instead of a flat file? –  doublesharp Oct 29 '12 at 23:28
Yes I have a database, but my problem would be that I use js to check the contents of refresh.txt and I don't think that would work well with a db? It checks the contents every 1 second. –  oOo--STAR--oOo Oct 30 '12 at 2:54
This could be part of the culprit - if you are trying to get an exclusive write lock this might conflict with reading the file. I would recommend moving it to the database, and then read via an AJAX request. If you are worried about performance cache the database results using APC. –  doublesharp Oct 30 '12 at 3:12
It would be a massive performance issue calling a php script in javascript to check the timestamp from the output when you say have 50 people online so you have 50 php requests a second. currently using talk_jax.open("GET", boardurl+"/talkbox/refresh.txt?nocache="+nocache); in js –  oOo--STAR--oOo Oct 30 '12 at 3:18
You could just ditch the file and use APC only. Replace your write code with apc_store("refresh", (!empty($rf_clear))? "clear" : time()); and your AJAX request to the static file with one to a PHP page that just has echo apc_fetch("refresh"); and it will do the same thing as reading/writing to the file, but without worrying about locks. –  doublesharp Oct 30 '12 at 3:34
show 4 more comments

2 Answers

up vote 2 down vote accepted

The best option is to use flock() to lock your file for writing - http://ar2.php.net/flock - using a loop for Windows compatibility as flock does not have a blocking option (not valid in your case for CentOS, but unharmful).

$max_tries = 5; // don't loop forever
$tbcheck = "refresh.txt";
for ($try=0; $try<$max_tries, $try++){
    if (flock($tbsend, LOCK_EX, true)) {  // acquire an exclusive blocking lock
        fwrite($tbsend, $tb_send);  // write to file
        fflush($tbsend);            // flush output before releasing the lock
        flock($tbsend, LOCK_UN);    // release the lock
        break;                      // exit the loop
    usleep(100);                    // sleep for 100ms if we couldn't get a lock

Another option would be to use APC or memcached to store a lock, which can then be checked from other PHP processes. Assuming that you have memcached your code would look something like this:

$timeout = 5; // set a cache expiration so a broken process doesn't lock forever
$key = "file_locked";
$max_tries = 5; // don't loop forever
    // check to see if there is a lock
    if (!Memcached::get($key)){
        // not locked, so set a lock before processing
        Memcached::set($key, true, $timeout);

        // write to the file
        $tbcheck = "refresh.txt";
        $tbtime = $tb_send;
        fwrite($tbsend, $tbtime);

        // delete the lock

        // exit the loop
    // locked, pause for 100ms
share|improve this answer
flock($fp, LOCK_EX) seems more straighforward. –  rambo coder Oct 30 '12 at 0:36
Hey thank you very much for your reply.. I have APC not memcached.. I don't know if you can use memcached and apc together but your answer definitely sums it up. How would I do this in APC? –  oOo--STAR--oOo Oct 30 '12 at 0:44
could you show me an example rambo? –  oOo--STAR--oOo Oct 30 '12 at 0:47
@rambocoder good point, I grabbed some of my code that doesn't actually have to do with filehandles, will update answer with flock –  doublesharp Oct 30 '12 at 0:53
I have tried the flock solution and it doesn't seem to be working. if you had a php script that you executed fwrite(); say 5 times in 2 seconds would it max out your CPU? Its pretty strange that it is. The file is only written to when people press enter to send shout, but if I send 5 in a row it will time out and cpu will goto 100% –  oOo--STAR--oOo Oct 30 '12 at 2:44
show 1 more comment

Consider using Apc instead.
apc_store('refresh', time()); to store
apc_get('refresh'); to retreive

yum install php-apc

Besides, you don't even have to store the time in it.
You could just store a counter apc_inc('refresher'); to store
that will increase every time there is a change and check in js if the new value is higher than the previous one you had.

share|improve this answer
Hey I actually started to use the APC store, it doesn't that fast but its good enough. What is the best way to grab it from javascript? I have figured the problem need a solution. Even using the apc i think that when you say spam its constantly writing a new value, so it can't be read properly from the JS script. Is there a way to limit this? or make it so it queues a few of the stamps up within 1 second then only writes the last one? If I could do that I know that would be the solution to the problem. –  oOo--STAR--oOo Oct 31 '12 at 15:01
I'll try and explain better. Basically its just constantly writing the new time every time you press enter, but js can't read it because its always changing and its just writing and writing and showing no shouts at all in the TB until you have stopped.. Now there is spam protection but the thing is if 5 people write near the same time it won't be read till its finished and that can take a long time if there is a few conversations going on so nothing will be printed till its stopped writing. –  oOo--STAR--oOo Oct 31 '12 at 15:34
Why wouldn't you just check if the input is not empty and update the time only then ? –  Alex Nov 1 '12 at 10:18
The problem with js is that it is not parallel ;) While you hold the 'send' button and JS sends data, it cannot receive and while it receives - it cannot send. If you want to make a spam protection per user, store the last time each user has sent something. In session or as another apc_key. –  Alex Nov 1 '12 at 10:25
add comment

Your Answer


