I love this module and installed in on almost every site (all low volume). I just noticed that some of my sites were very fast compared to the others. After much trial and error, I figured out the performance killer is this module.

I am not a developer and am not sure how to test this. I used this module extensively, and hope there is a workaround.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

deviantintegral’s picture

What pages are slower? Can you install the devel module to determine if it's a SQL or PHP issue? And is the issue present in the latest -dev version?

johnthomas00’s picture

Scrambling today, I will look into that tomorrow for you.

I have not tested latest dev, using released version. All pages are noticeably slower. Page load times drop about 35% without the module.

The following is about 9 times faster without the module as anonymous on front pages with or without much content. Anonymous has not "rights" via masq in my tests.
ab -n 100 -c 50 http://example.com/

johnthomas00’s picture

I am not sure how to test or report on this properly. Here are results (for none, released, and dev) for the first and second click of the home page immediately following a cache clear as the root user. I also ran Apache Bench. I am not sure the devel module is "getting it." If you uninstall the module, log out, then log in and fiddle with a site, then install, log out, log in and fiddle, the difference is completely noticeable to the naked eye.

Anyway, let me know if you need anything.

Without Masquerade
First Click
Executed 55 queries in 118.18 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 398.66 ms.
Second Click
Executed 49 queries in 33.81 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 203.83 ms.
Apache Bench ab -n 100 -c 50 http://example.com/
Time taken for tests: 2.356816 seconds

With http://ftp.drupal.org/files/projects/masquerade-6.x-1.3.tar.gz
First Page Click
Executed 55 queries in 102.5 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 419.83 ms.
Second Page Click
Executed 51 queries in 52.17 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 262.22 ms.
Apache Bench ab -n 100 -c 50 http://example.com/
Time taken for tests: 13.957178 seconds

With http://ftp.drupal.org/files/projects/masquerade-6.x-1.x-dev.tar.gz
First Page Click
Executed 55 queries in 102.73 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 404.45 ms.
Second Page Click
Executed 50 queries in 33.62 milliseconds. Queries taking longer than 5 ms and queries executed more than once, are highlighted. Page execution time was 219.59 ms.
Apache Bench ab -n 100 -c 50 http://example.com/
Time taken for tests: 15.707758 seconds

seanburlington’s picture

Title: Performance Killer » enhance performace by removing hook init ( maybe use a cookie instead)

Hi,
I'm also having this problem on a high traffic site

Part of the issue is that masquerade sets a session cookie for all users - which effectively disables varnish caching.

It also makes a database query for every page view for every user

function masquerade_init() {
  global $user;

  // load from table uid + session id
  $uid = db_result(db_query("SELECT uid_from FROM {masquerade} WHERE sid = '%s' AND uid_as = %d", session_id(), $user->uid));
  // using if so that we get unset rather than false if not masqing
  if ($uid) {
    $_SESSION['masquerading'] = $uid;
  }
  else {
    $_SESSION['masquerading'] = null;
  }
}

I wonder if it would work to set a cookie to indicate masquerading ?

The cookie should still be available in the new masqueraded session - and would enable the hook_init to be dropped.

So when the user switches

* create a random ID
* save this to a db table along with the orginal user ID
* set cookie masquerade = random ID

Then check for this cookie in the masquerade block - looking up the user ID when appropriate.

Sorry I don't have a patch for this (for the time being we've just disabled masquerade) but I thought it might be worth noting the possible optimisation and seeing if people here think it's viable

Sean Burlington
www.practicalweb.co.uk

omerida’s picture

this killed us on a high traffic site, since it bypassed the caching we had set up to handle traffic. A non session based solution has to be found, otherwise I can't continue to use the module.

Since the session variable only needs to be availble for logged in users, can't the init hook be wrapped in a if (user_is_anonymous()) {} ?

deekayen’s picture

Status: Active » Needs review
FileSize
1.19 KB

I turned omerida's idea into a patch. Please try it. I don't have a high traffic site to see if it makes a difference. If someone +1, I'll commit it.

deviantintegral’s picture

Version: 6.x-1.3 » 6.x-1.x-dev
Status: Needs review » Needs work

I'm not sure I understand why Varnish would allow using a cookie as per #4 while not a session variable (which requires a cookie as well). But if the suggestion in #5 gets around it, then I'm all for it.

Two thoughts about the patch in #6:

  1. Currently, it's possible to use Masquerade to allow anonymous users to switch users. When I do it on 6.x-1.3, I get a notice, but I suppose it's possible for a site to be doing this. Even if we agree that anonymous masquerading shouldn't be allowed, the Drupal 6 permissions UI will still allow the permission to be assigned. Perhaps we could add a form_alter() on the permissions form to not allow that permission to be set? Still wouldn't fix API calls using permissions_api, but it'd be close enough. We'll need a pretty obvious update note to cover this change.
  2. Let's clean up the comments while we're at it. // load from table uid + session id either needs to be removed or cleaned up, as it's pretty obvious that's happening in the line after. For // using if so that we get unset rather than false if not masqing I'm going to suggest:
    // Ensure that $_SESSION['masquerading'] is unset and not FALSE if a user isn't masquerading.
muhleder’s picture

Subscribing. I've noticed that cache_page is never written to whilst using Pressflow if Masquerade is enabled.

deviantintegral’s picture

@muhleder, it would be great if you could try the patch from #6.

coreyp_1’s picture

I'm not trying to compete with deekayen's patch, but this is what we are using on our production site.

We, too, are using Pressflow with Varnish and had issues when masquerade is enabled, but where we noticed the most problems was with the session tables. Pressflow can be set to not save anonymous user's sessions, provided that there were no variables stored in the $_SESSION array. This is the patch that we have been using in order to keep anonymous sessions out of the database.

The main difference is that it includes a condition to disallow masquerading as an anonymous user, which is necessary if we are no longer checking for masquerading when the user is anonymous.

deekayen’s picture

There was at one time a maintainer that removed the functionality to be able to masquerade as anonymous. We could return to that. The alternative is logging out and back in, of course.

I'm OK with committing a patch that makes Pressflow work and breaks anonymous masquerading, but #6 and 10 don't quite document those realities and seem more of a hacky workaround.

bcmiller0’s picture

minor update to #10 above to make it apply cleanly on new 6.x-1.4 version of masquerade

andypost’s picture

Suppose anonymous masquerading (ability to masquerade from anonymous to registered user) should be fixed with form_alter() of permissions page.

patch #6 is more reasonable and self commented

Ability to masquerade as anonymous user seems useless because pages for anonymous mostly cached and I see no ability to display a "switch back" link.

Another idea is make setting: Allow masquerade as anonymous. Than hook_init() should check this variable, check that session started, and in case that user is masquerading as anonymous disables page caching by $conf['cache'] = FALSE;

rjbrown99’s picture

I'm using #12 at the moment, works great - no more session cookie. Thanks!

zero1eye’s picture

Patch #12 worked great for me. No more Googlebot inflating the guest users count because I have all the anon sessions tagged with "masquerading|N;"

Kars-T’s picture

Status: Needs work » Needs review
FileSize
1.56 KB

+1 for the patch in #6. The coding style seems nicer to me and both do the same. So I remade it against latest head. This is currently runnig without problems at two of our sites. One gets 5.000 Visitors a day.

bflora’s picture

I just wanted to chime in to say how important it is that this module gets fixed or at least put up a big warning that says it will destroy your site's performance.

Two years ago I started a social news site running Drupal where people post stories and vote on them. I've worked full-time on this site since then, and though we've seen thousands of people sign up and have a loyal community, we were never able to get page load times on the site under 8-15 seconds per page. It didn't make sense.

A year into it, I decided we needed to get the problem fixed. So I hired a developer to setup Nginx and PressFlow, to put our DB on one server and our web stuff on another. I've upgraded our servers big time. I've also hired in about 4 other developers, each who promised to solve our speed problem only conclude that it was a random piece of bad code somewhere in our setup that was killing things and that they were not interested in hunting for it.

These changes brought our page loads down to about 7-8 seconds. Still unacceptably slow. It's been heartbreaking and has probably cost me about $15,000 cash plus who knows how many lost readers/users.

I get invited to a fair number of conferences where people in the media ask me about using Drupal for their new projects. I've spent the last year telling people to run far far away from Drupal as it's terribly slow no matter what sensible thing you do to it. I still use it because the switching costs would be too high at this point, but I've told everyone I know never to touch the thing if they want to do anything serious with it.

And here tonight I just stumbled onto this thread and found the answer to why our sessions table is so out of control. Found the answer to why the money I spent to hire a guy to set up Pressflow was all wasted. The Masquerade module was killing it all. This was the random broken code that has made life so difficult these past few years.

I've installed the latest dev release and our site it fast as lightning. It's a bit of a revelation.

Thank you to those who started this thread and posted fixes. To the maintainer, I can't urge you strongly enough to commit these changes into production releases so that no one else will suffer from running the previous version of the module.

I'll keep an eye on performance to see how things go, but so far, this has been a real eye-opener and an answer.

deekayen’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
Status: Needs review » Patch (to be ported)

Committed #16 to DRUPAL-6--1. HEAD still needs someone to look at it.

claudiu.cristea’s picture

Status: Patch (to be ported) » Closed (duplicate)
coreyp_1’s picture

uhhh....

This one is older, so actually the other one is a duplicate of this, & standard Drupal procedure would be to link from that one to this one.

deekayen’s picture

Status: Closed (duplicate) » Needs work

There is a proposed revision to the implementation of this at #908194-5: Needless session creation = incompatible with Pressflow that would maintain masquerading as Anonymous, but I think unsetting an unset variable is a safe thing to do. I also want to stick with either using $GLOBALS or declaring global $user. I don't want every patch to be flip flopping that.

bflora’s picture

Awesome stuff, guys.

claudiu.cristea’s picture

Title: enhance performace by removing hook init ( maybe use a cookie instead) » Don't create session var when not masqerading
Version: 7.x-1.x-dev » 6.x-1.x-dev
Assigned: Unassigned » claudiu.cristea
Category: feature » bug
Status: Needs work » Needs review
FileSize
5.2 KB

OK but changed the title to be more descriptive.

... but I think unsetting an unset variable is a safe thing to do.

I cannot test what's going on in a PHP 5.3 environment. It was maybe a non necessary precaution. Maybe someone can test the patch on PHP 5.3.

I also want to stick with either using $GLOBALS or declaring global $user

global $user; is a common practice in Drupal world. So, remaining on that.

deekayen’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
Status: Needs review » Patch (to be ported)

I committed #23.

NITEMAN’s picture

Version: 7.x-1.x-dev » 6.x-1.x-dev
Status: Patch (to be ported) » Needs review

subscribing

NITEMAN’s picture

Version: 6.x-1.x-dev » 7.x-1.x-dev
Status: Needs review » Patch (to be ported)

Sorry

andypost’s picture

Status: Patch (to be ported) » Reviewed & tested by the community

This code already in D7 branch. Suppose we should cleanup code for session management.

andypost’s picture

Status: Reviewed & tested by the community » Needs work

We are using $_SESSION[masquerading] and $user->masquerading suppose $_SESSION is a preferable place and we just need _masquerade_is_masquerading() function .

andypost’s picture

+++ masquerade.module	30 Oct 2010 08:47:32 -0000
@@ -32,17 +32,19 @@ function masquerade_perm() {
+    unset($_SESSION['masquerading']);

This could initialize a new session so been fixed in #987610: Notice: Undefined variable: _SESSION in masquerade_init

Powered by Dreditor.

greggles’s picture

Subscribing.

anavarre’s picture

Subscribe

andypost’s picture

Status: Needs work » Fixed

Variables are not initialized with isset() so let's continue in #1103588: Cleanup code and optimize query count

greggles’s picture

I looked at commits back to February and none of them reference this. Was it fixed in 7.x only or 6.x as well?

Thanks for your work on the module.

andypost’s picture

I think #24 point to commit, 6.x already fixed

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.