Closed Bug 91044 Opened 22 years ago Closed 6 years ago

global history datasource slow when responding to nsXULTemplateBuilder::CheckContainer() queries


(Core Graveyard :: History: Global, defect, P3)



(Not tracked)



(Reporter: waterson, Assigned: timeless)



(Keywords: perf)


(3 files)

This leads to pretty poor performance when scrolling new rows onto the screen
for the first time (cf. bug 89872, which fixes subsequent scroll performance).
Need to profile this to see what's going on, and if we can make any improvements...
Keywords: perf
Priority: -- → P3
Target Milestone: --- → mozilla0.9.4
Blocks: 66907
Target Milestone: mozilla0.9.4 → mozilla0.9.5
I'm swamped. Kicking to component owner.
Assignee: waterson → alecf
history bugs to blake.
Assignee: alecf → blakeross
Er, except hist perf, ->bryner
Assignee: blakeross → bryner
-> 0.9.6.
Target Milestone: mozilla0.9.5 → mozilla0.9.6
Blocks: 74634
Target Milestone: mozilla0.9.6 → mozilla1.0
Bugs targeted at mozilla1.0 without the mozilla1.0 keyword moved to mozilla1.0.1 
(you can query for this string to delete spam or retrieve the list of bugs I've 
Target Milestone: mozilla1.0 → mozilla1.0.1
don't move bugs that are in the 1.0 dependency tree. sorry.

Target Milestone: mozilla1.0.1 → mozilla1.0
Target Milestone: mozilla1.0 → Future
This is /unusably/ slow for me on Linux trunk of a few days ago.

Look at the attached profile: it seems Mozilla is doing something
horrible with libc calls to timezone / getenv stuff. This profile
was taken whilst scrolling through a large history for the first
time. Also (subjectively) the time taken for a page down via
the scrollbar seemed to be proportional to the number of items
previous to the visible page.

Anybody want me to test a patch ? :)

(Each profile line is VMA address, number of samples, percent of total, symbol
name, relevant binary)

000807e0 40917    3.10649     memmove                 /lib/
0000e27c 41668    3.16351     morkMap::find(morkEnv *, void const *, unsigned
int) const /home/moz/bin/mozill/bin/components/
00027668 47022    3.56999     CharsToPRInt64(char const *, unsigned int, long
long *) /home/moz/bin/mozill/bin/components/
0002e648 49149    3.73148     getenv                  /lib/
000c7a10 50190    3.81051     nsASingleFragmentCString::Length(void) const
000a6170 51394    3.90192     __tzstring              /lib/
000a50d0 58725    4.45851     tzset_internal          /lib/
000c7910 68171    5.17566    
nsASingleFragmentCString::GetReadableFragment(nsReadableFragment<char> &,
nsFragmentRequest, unsigned int) const /home/moz/bin/mozill/bin/
000a6e30 72924    5.53652     __tzfile_compute        /lib/
000a1d14 153763   11.674      __offtime               /lib/

the getenv calls are strange, but I can't figure out who is calling it. is there
any way to get a stack here?
Not with oprofile. I can hack up an LD_PRELOAD + builtin_return_address()
trick if you like to get call site
counts ... (if that'll work with shared libraries ...)
*** Bug 142514 has been marked as a duplicate of this bug. ***
Well it seemed to work, but I had to calculate the stuff manually, and I
must have cocked up, because it blamed calls inside pthreads via PR_JoinThread
in ptthread.c.

However, somebody taught me gdb, so here's the top of the backtrace from one
of the thousands of getenv() calls :

#0  getenv (name=0x405c209e "TZ") at ../sysdeps/i386/bits/string.h:343
#1  0x40554113 in tzset_internal (always=1079779486) at tzset.c:144
#2  0x40555037 in __tz_convert (timer=0xbfffd37c, use_localtime=1,
tp=0x405cf480) at tzset.c:583
#3  0x405512be in localtime (t=0xbfffd37c) at localtime.c:43
#4  0x401de402 in MT_safe_localtime (clock=0xbfffd37c, result=0xbfffd380) at
#5  0x401de506 in PR_LocalTimeParameters (gmt=0xbfffd410) at prtime.c:701
#6  0x401ddd1f in PR_ExplodeTime (usecs=1022700704021436, params=0x401de444
<PR_LocalTimeParameters>, exploded=0xbfffd410) at prtime.c:230
#7  0x40d9173d in NormalizeTime (aTime=1022700704021436) at nsGlobalHistory.cpp:268
#8  0x40d918aa in matchAgeInDaysCallback (row=0x87eae28, aClosure=0xbfffd820) at
Checking in gdb, the backtraces from the LD_PRELOAD trick :

getenv called: backtrace:

(gdb) list *0x40557113
0x40557113 is in strptime_internal (strptime.c:445).
(gdb) list *0x40558037
0x40558037 is in strptime_internal (strptime.c:922).
(gdb) list *0x405542be
0x405542be is in tzset_internal (tzset.c:93).
(gdb) list *0x401e1402
0x401e1402 is in PRP_NakedWait (ptsynch.c:1091).
1086            rv = pthread_cond_wait(&cvar->cv, &ml->mutex);
1087        else
1088            rv = pt_TimedWait(&cvar->cv, &ml->mutex, timeout);
1089        if (rv != 0)
1090        {
1091            _PR_MD_MAP_DEFAULT_ERROR(rv);
1092            return PR_FAILURE;
1093        }
1094        return PR_SUCCESS;
1095    }  /* PRP_NakedWait */
(gdb) list *0x401e1473
0x401e1473 is in pt_poll_now (ptio.c:563).
558     }  /* pt_poll_now_with_select */
560     #endif  /* _PR_POLL_WITH_SELECT */
562     static void pt_poll_now(pt_Continuation *op)
563     {
564         PRInt32 msecs;
565             PRIntervalTime epoch, now, elapsed, remaining;
566             PRBool wait_for_remaining;
567         PRThread *self = PR_GetCurrentThread();

Which doesn't look very promising in terms of this __builtin_return_address
doing anything sensible :)
holy smokes! who knew PR_ExplodeTime time would fan out like THAT. I'll see if I
figure something out there.
Any progress here ?
I optimized it a big for bug 166681, but the general algorithm is still the
same.. I don't know much else to do right now though..
I am seeing this bug within Phoenix 0.5 on Window 2000 Professional.  My history
was set for 21 days.  I cleared it before I saw how big it got.  Before the
clear, typing in the location bar was painfully slow, as was deleting characters
in the location bar.  Loading the history always took a while when sorted by
date.  A While == 15-20 seconds, maybe a little less.  

Does this bug include Phoenix (and/or all Mozilla web browsers)?  I've added
myself to the CC list.
Peter, I don't think that's the same bug ... this was concerning the old
History dialog in seamonkey in terms of what the user can see. Firebird
uses a sidebar that doesn't seem to have the problem.

If somebody needs profiles (I can also do some limited call graph stuff)
of particular operations in Firebird related to this bug, please ask.
I don't know this code; I merely implemented a suggestion dictated to me in IRC
(and verified that it compiled/ran and didn't hork history).
Attachment #129075 - Flags: superreview?(alecf)
Attachment #129075 - Flags: review?(alecf)
Assignee: bryner → timeless
Target Milestone: Future → ---
Comment on attachment 129075 [details] [diff] [review]
some modifications timeless suggested

generally looks ok, but now you have an nsAutoString created inside a loop -
was that the intent? I'd prefer something like PR_sscanf or something
Attachment #129075 - Flags: superreview?(alecf)
Attachment #129075 - Flags: superreview-
Attachment #129075 - Flags: review?(alecf)
Comment on attachment 129075 [details] [diff] [review]
some modifications timeless suggested

alecf: does pr_sscanf support wide characters?
soap does this:
/extensions/webservices/soap/src/nsDefaultSOAPEncoder.cpp, line 3031 -- PRInt32
r = PR_sscanf(NS_ConvertUCS2toUTF8(value).get(), " %lf %n", &f, &n);

Note that currently the same code is called deeper in the callstack the goal is
to simply skip calls to the time function, not fix the autostring stuff.

330 matchAgeInDaysCallback(nsIMdbRow *row, void *aClosure)
331 {
...   //  vvvvvvvvvvvvvvvvvvvvvvvvvvvvv is always false in the old code
339   if (!matchSearchTerm->haveClosure) {
/* because |matchSearchTerm_t matchSearchTerm = { mEnv, mStore, term ,
PR_FALSE};| is discarded with each iteration of the loop */
340	PRInt32 err;
341	// Need to create an nsAutoString to use ToInteger
/* so this code which i'm simply *copying* gets called with each iteration of
the loop */
342	matchSearchTerm->intValue =  nsAutoString(term->text).ToInteger(&err);
/* all i'm doing is copying lines 340,342,344 to skip the expensive 343 */
343	matchSearchTerm->now = NormalizeTime(PR_Now());
344	if (err != 0) return PR_FALSE;
345	matchSearchTerm->haveClosure = PR_TRUE;

As for those lines of code... well you own blame for them. (mkaply has tainting
blame, but your 1.73 introduced ToInteger)

I'm certainly willing to at some later time rewrite the code to at least
recycle the nsAutoString but I'd rather we get this in. (Don't ask me why I'm
poking this at 6am while i'm vacationing for a weekend.)
Attachment #129075 - Flags: superreview?(bzbarsky)
Attachment #129075 - Flags: superreview-
Attachment #129075 - Flags: review?(alecf)
*** Bug 194926 has been marked as a duplicate of this bug. ***
Comment on attachment 129075 [details] [diff] [review]
some modifications timeless suggested

well, I mean you're adding an EXTRA nsAutoString - clearly I did the wrong
thing before as well, but I see no need to make it worse by adding yet another

you get sr=alecf if you recycle the nsAutoString - you're already recycling the
"term" which we didn't do before..
Attachment #129075 - Flags: review?(alecf) → review-
Attachment #129075 - Flags: superreview?(bzbarsky)
Is anyone looking at resolving this?
This still occurs with Firefox 3 for the History container within the Library. Shall I file a new bug on that or will it be covered by this bug?
QA Contact: claudius →
Closed: 6 years ago
Resolution: --- → INVALID
Product: Core → Core Graveyard
You need to log in before you can comment on or make changes to this bug.