See function realname_make_name(&$account) {}
http://drupalcontrib.org/api/drupal/contributions--realname--realname.mo...
if (!db_result(db_query("SELECT uid FROM {realname} WHERE uid=%d", $account->uid))) {
db_query("INSERT INTO {realname} (uid, realname) VALUES(%d, '%s')", $account->uid, $result);
}
else {
db_query("UPDATE {realname} SET realname='s' where uid=%d", $result,$account->uid);
}
I think this is a typo.
db_query("UPDATE {realname} SET realname='s' where uid=%d", $result,$account->uid);
should be
db_query("UPDATE {realname} SET realname='%s' where uid=%d", $result,$account->uid);
I found this while using the devel query module inspecting all queries. I found out, that on my frontpage 26 times the following statement is made:
UPDATE realname SET realname='s' where uid=0
If I change the code, my number of queries on the front page reduces about 10%...
Comments
Comment #1
ayalon commentedIs this update statement really necessary? This is executed everytime a user is loaded. I should be executed only, if the username changed...
Comment #2
gaellafond commentedI just found exactly the same issue with devel query module. The typo is also in the last stable release (version 6.x-1.3)
There is something else with this function. The static variable $users used for caching is now broken. It's set in _realname_make_name() and checked in realname_make_name().
See: http://drupal.org/node/518862
Comment #3
gausarts commentedTracking. Thanks
Comment #4
YK85 commentedsubscribing
Comment #5
ayalon commentedThis is critical and should be fixed immediately. Can someone review the patch please?
Comment #6
nancydru@ayalon - please open a new issue about #1. I think you are right.
Comment #7
ayalon commentedThis IS a full featured well described issue. I also provided a patch and I will not open a second one. I can't do more... Please review this and commit the patch. I agree, that we can open a second issue for the performance optimization. But this is not the main point here.
Comment #8
nancydru@ayalon: I have just committed the patch, along with several others. It, however, did not address whether that statement was needed at all; that is why I asked you to open the other issue.
Committed to 6.x-1.x-dev.
Comment #10
starbow commentedEven with the patch, the logic in this function is wrong. It should be something like:
Comment #11
gaellafond commentedI agree that it is weird to update the name every times. I though it was some sort of optimisation, something like a "Select take the same times as an Update" (I'm pretty sure it's not the case) so you can always do an update...
I'm not sure exactly what the author was trying to do here.
As Nancy said, this part of the code is probably not needed at all...
Comment #12
cgmonroe commentedHaving just chased thru the logic to solve another issue (with content_profile), I can say that some sort of update needs to happen after the _realname_make_name() function is called.
This is the code that calls the different realname "plug-ins" that handle different profile methods. The plugs can return a new name value calculated from the source. This might have been updated thru a method realname doesn't monitor (e.g direct DB change/ content_profile node being updated / maybe even a custom LDAP call ).
Bottom line is that this update check need to be here... in a correct form.
That said, maybe there should be a check to verify that the current name matches the results returned by _realname_make_name(). Then, do the update/insert if it doesn't.
One question to the person who had multiple queries occuring on the homepage. Was this with the -dev version? The caching mechanism has been fixed in the -dev. With this version, this code should only execute once per page. All other calls get resolved via the cache.
So, if it was happening multiple times in the -dev version, there is still a bug in the cache system.... (FWIW - My recent tracing thru the code show it was working... but... ).
Comment #13
gaellafond commented@cgmonroe I had multiple queries but fixing the typo (which is the main purpose of this Bug) actually fix that. I now have a descent number of queries. I'm using the last stable release, not the dev one.
Comment #14
joelstein commentedWe only need to update if the generated realname differs from what is saved in the database. Here is a patch which is basically the same as in #10, with some clearer documentation. This reduces all those unnecessary "UPDATE" statements.
Comment #15
gappleChanging title to be more relevant to the current issue.
@joelstein's patch in #14 makes sense and looks good to me.
Comment #16
dave reidI don't think this is really necessary at this point. We don't check if someone actually changed a field on a node when someone presses 'Save' on a existing node form, but we just save it anyway. I don't see the harm here.
Comment #17
nancydruI occasionally get into a performance mood and have looked at this. I don't think the update should be there at all. The only time the table should be updated is in hook_user. But I haven't had the time to fully investigate to see if it would cause any problems.
Frankly, while there is a performance hit, I can hardly justify "major" let alone "critical."
Comment #18
joelstein commentedRegardless of the priority, I still think it's worth committing. On an intranet for a major health system, we have an "activity stream" of sorts, which (before this patch was applied) resulted in lots of user_load() calls, and the number of unnecessary UPDATEs was not insignificant. This patch is working great for us.
Comment #19
geerlingguy commentedAgreed with @joelstein above - I'm considering using this module on my own Intranet, and initial performance testing on pages listing more than 20 or 30 users at a time get a huge performance hit, and can't easily be cached...
Comment #20
dave reidSo probably the proper solution is to:
1. Have realname_make_name() first check if there is a realname in the database. If there is, store it in the static cache and return it.
2. Else generate the realname, insert into the database (since if it wasn't already found, we can assume we can just insert).
3. Ensure that hook_user('update') just removes the realname and resets the static variable in realname_make_name().
Comment #21
gappleI was going to comment on the necessity of the database update on each page-load as well, but figured it was better to close this issue (that's already changed direction once), and further optimize in a follow up (which I suppose I really should have commented to).
I agree with @NancyDru that the update shouldn't be there at all: RealName is going to the effort of creating a cache table but only using it for autocomplete calls. The first load of the realname for each account on every page always regenerates the realname and updates the cache (which doesn't help MySQl query caching at all either).
My though was that
realname_make_name()seems somewhat overloaded, fetching and storing the generated name. I would suggest separating out generation and retrieval into separate functions.As well, if an entry is known to exist in the cache table for every user (add / remove on user creation / deletion) we can always just do an update rather than having to worry about inserts as well.
My psuedo-ish-code thoughts for separation:
This would require quite a few more changes, but I think it makes sense.
Comment #22
gappleHere's a patch that tries to improve the cache handling, though keeps it in
realname_make_name()still.An update hook makes sure that every user has an entry in the realname table, and records are now only deleted on user deletion.
realname_make_name()has a reset parameter which will cause it to regenerate the real name and store it in both caches. This is used when a user or content_profile node is updated.Comment #23
gapplestatus & title
Comment #24
franzIs this patch really for the 6.x ? I'm wondering about he use of &drupal_static()
Comment #25
franzI think this is critical. The current *stable* version has no caching at all, not even static.
Comment #26
geerlingguy commentedMaybe major... I'm using the module on a decent-traffic site without much of a problem... and I will continue using the patch in #10 until a better long-term solution is accepted. As Nancy said earlier:
I think we should respect her wishes. A review would get this patch in quicker than a status change ;-)
Comment #27
gapple@franz: drupal_static is conditionally defined by the realname module in order to backport its functionality:
realname.module line 16
I think this is also one of several significant outstanding issues in the current stable (and development) release for 6.x, but it is only a performance issue rather than broken functionality or corrupt data and so 'major' is more than enough.
As @geerlingguy said, a patch review is what is most needed to move this issue along.
Comment #28
franzSorry about that, 'major' seems more reasonable.
I think this piece of code should be at least better documented, as it can get confusing.
I have nothing else to add to this patch, it looks great!
Comment #29
gappleHere's an updated patch to keep up with head and clean up some formatting.
The only functional change is that when a content profile is updated
is changed to
Hopefully this should be clearer in intent, and will avoid any potential issues of
realname_make_name()and_realname_make_name()expecting a user object.Comment #30
YK85 commented#29: realname-805526-27.patch queued for re-testing.
Comment #32
gappleHere's an updated patch. Not sure if EGit will play nice, so here's both of it's patch output formats.
Or, pull from github: https://github.com/gapple/realname/tree/bug/805526-cache-performance
Comment #33
gappleStatus
Comment #34
uayebforever commentedI believe there is a typo in the database update code. First, update 6103 clashes, so I've changed it to 6104. Second, it should be
FROM {users}notFROM {user}which barfs when one tries to run update.php.In realname.install:
Otherwise looks great. +1 for reviewed and tested if this is fixed. I would patch this myself if I knew how (always more to learn). This was pretty critical for me, as I am using CiviCRM and having RealName force a load of CiviCRM for every username was a pretty big performance hit. (I've since rewritten my CiviCRM interface for RealName to be faster as well.)
Comment #35
gappleThank you for testing the patch and finding those bugs @uayebforever.
Here's an updated patch. I changed the update hook query some more to only insert values not already present in the {realname} table in order to avoid duplicate key errors.
Comment #36
hefox commentedNew users never get realname set cause the insert never creates a record. working on patch now
Comment #37
hefox commentedFor those using this patch already, another update function needs to be added somewhere-else that is same as one added in this patch (assuming you've had new users since then).
Comment #39
hefox commentedEr, I don't think that testbot failure relates to anything I did, does it?
Comment #40
hass commented