[21:59:42] TimStarling: Reedy: semi-random ping - I wonder if either of you have noticed and/or have looked at regression around Special:Contributions. It seems to have fallen back in latency quite a bit back. And a few excimer runs show that indeed there is a ton of repeat work being done that I thoguht we fixed a few years ago. e.g. https://performance.wikimedia.org/excimer/profile/abe9b7b82ac31b52 [22:01:09] it's like 1-2s minimum for basic 50 edits for any given user. stands out: revDateLink(), generateRollback(), lots of repeat queries and message parsing. [22:03:07] hm.. I'm getting 500 by default. Has that always been the case if you have a higher API limit, that the UI also defaults to 500? [22:03:45] It's tied to `rclimit` now apparently. [22:04:56] I tend to reflexively change watchlist and special:recentchanges to 500 when I view them. I don't think I've ever before realized that this also sets the default for page history, user contribs, and special:log. [22:05:26] It still seems like something that should batch more efficiently, so not sure that's the only thing. It's certainly quicker with 50. [22:06:30] are you saying something is setting rclimit without you realising? [22:07:37] I'm saying I wasn't expecting rclimit to apply outside recent changes. I don't care either way, but if it means I"m signing up for a 2s delay on every contribs link and page history link I open, then no. I don't mind it for RC given that's usualy the start of a more in-depth workflow. [22:07:41] the Special:Preferences label says "Number of edits to show in recent changes, page histories, and in logs, by default" [22:08:16] Yeah, I see that. I search for 500 in prefs and found that. I wonder if that's alwyas been the case, but this is a red herring if the cause is that loading 500 revs used to be fast. [22:08:22] but it's in the recentchanges tab [22:08:54] I'm more interested in making it so that seemingly-simple page history and contribs responses aren't slow. [22:09:17] with limit 500 there's 217 db select queries. most coming in via LinkHolderArray::replaceInternal [22:09:22] https://performance.wikimedia.org/xhgui/run/symbol?id=672009d842997c3ebc1d391d&symbol=Wikimedia%5CRdbms%5CSelectQueryBuilder%3A%3AfetchResultSet [22:10:12] since 2007: https://static-codereview.wikimedia.org/MediaWiki/22010.html [22:11:08] set in the base class so it would have been applied to more things as we migrated them to Pager [22:13:26] Yeah ok that's not new then. I don't really mind it. I don't think it makes sense per-se given the difference in how one consumes watchlist/rc vs logs/contribs. Like when I open watchlist or RC, I"m generally going to have it open for a while and I don't yet know what to look for. Whereas logs or contribs one almost always has a purpose, I'm just waiting for it to load so I can click the next link, e.g. the last edit on the page, or that [22:13:26] edit I know myself or someone else made 3 minutes ago. [22:13:50] nvm RE LinkHolderArray, classic XHProf useless tuple fake data. [22:15:11] most of them are rollback count and page protection store [22:15:53] I wonder if something regressed in message parsing that it's so expensive for simple strings [22:19:26] in the sandwich view for Message::format, the callee side seems more or less as expected [22:20:05] lots of {{plural}} which you can't simply cache in the pager, it needs the parser for that [22:21:52] Message::format is 22% [22:29:47] ok there are a couple of odd things in message parsing [22:30:29] you don't need limit reports for messages (Parser::makeLimitReport) [22:30:51] I'm looking at showCharacterDifference as well. wgMiserMode is on, incl on Wikitech. [22:31:02] you shouldn't need tidying, the input should be tidy enough, although that's a breaking change at this point [22:32:18] Parser::finalizeHeadings() is very expensive, that's a recent change, November 2023 [22:32:39] but `rc-change-size-new` tooltip escapes that optimisation [22:33:24] TimStarling: right, that could perhaps be guarded based on `interface` mode [22:33:47] ParserOptions->getInterfaceMessage that is [22:34:44] RE: finalizeHeadings, you mean https://gerrit.wikimedia.org/r/c/mediawiki/core/+/975064 ? [22:35:52] yes, and it's a very simple fix, the cost here is just due to the DOMUtils::parseHTML() call, but it's only needed in the loop body and $headlines is empty [22:36:41] I mean the DOMUtils::parseHTML() call needs to be skipped when $headlines is empty [22:41:03] this is 2.4% of your profile but at least it is easy [22:41:42] right, that's ~57% of finalizeHeadings, or 1.2% in https://performance.wikimedia.org/excimer/profile/abe9b7b82ac31b52 [22:42:10] ah 2.4% cumulative yeah, there's a few more places [22:43:31] generateRollback() could be fixed by just removing those links -- generate them on the client side if they are needed [22:43:36] we presumably don't expose TOCData on interface messages, but there may be some non-obvious cases like special pages with interace messages and a TOC where we add to outputpage with metadata. Afaik we parse those normally though as not as interface. I don't think TOC works there today, but worth checking if that's exposed somewhere. Could ptentially cut more in that case. [22:48:04] the cost isn't in the csrf token (which we could add client-side like we do with patrol already, for ajax-ification) but the revision count and message plural parsing. The csrf token could be remoed in favour of a form fallback (right now it lacks that, but easy to add). assuming most of the rollback links will have the same single digit number, that could be cached inline to an extent, waiving potential customisations that permuate the [22:48:04] interface message based on other factors we don't anticipate. [22:50:08] the revision count... it seems like that information ought to be in memory already. But it's structured to act on one rev at a time. [22:51:00] It might miss a few for the last row but for most it'll have the revs between it and the next 10 (ShowRollbackEditCount) [22:51:17] but that seems like something that's probably always worked this way. [22:51:26] no smoking gun that made it slow recently [22:52:06] I think doing 500 rows was always pretty slow, I don't remember that being fast [22:52:37] it's slow for different reasons now, we're finding new ways to keep it slow despite faster CPUs etc. [22:53:33] > We need metrics for special page views, by analogy with the action metrics https://phabricator.wikimedia.org/T257002#7313928 [22:54:02] https://grafana-rw.wikimedia.org/d/rLMucuf4k/mediawiki-entrypoint-profiling?orgId=1&var-entrypoint=index_Contributions&var-http_method=GET&var-time_grouping_unit=3h [22:54:09] we do have something like that now [22:54:39] RestrictionStore::getRestrictions() is 209ms in your profile, that could benefit from batching [22:54:51] I recall it covering this latency metric as well https://grafana-rw.wikimedia.org/d/8j5fqcuVk/mediawiki-action-timing-index-php but it seems there isn't an equivalent for that [22:55:30] WAN cache in front of a single fast query is questionable, especially when it is called 500 times [22:56:24] right, that presumably helps on HistoryPager but not ContribsPager [22:57:07] the existence of RestrictionStore with its in-process cache would make batching pretty straightforward, it's obvious how to implement that [22:57:54] History pager has doBatchLookups() to place this [22:58:37] ContribPager.... not but,, ah yes the same, doBatchLookups in the parent, ContributionsPager, because those are obviously two different things. [23:00:07] 119ms for ConvertibleTimestamp::setTimestamp(), that is a very hot few lines of code [23:01:27] ref T341319, I recall reviewing that for RestrictionStore, but doesn't help with `rollback` [23:01:42] T341319: RecentChanges: Improve performance of Special:RecentChanges rendering - https://phabricator.wikimedia.org/T341319 [23:01:59] https://gerrit.wikimedia.org/r/c/mediawiki/core/+/938220 [23:02:05] > When rendering Special:RecentChanges for an user with rollback rights, [23:02:16] the setTimestamp() calls mostly come from ConditionalDefaultsLookup, which is new (Nov 2023) [23:02:25] .. or maybe it does. Right, of course, you can't protect against rollback. [23:04:06] I guess that's for `$authority->probablyCan( 'edit', $title );`, right above `$authority->probablyCan( 'rollback', $title ) ` also in PagerTools [23:04:34] * Krinkle has dinner ready [23:05:15] I might file a few tasks for this under T341319 or another related task if you don't. Also if you're compelled to patch, CC me :) [23:06:31] memoizing of ConditionalDefaultsLookup::getOptionDefaultForUser() looks straightforward and would save a substantial fraction of 96ms [23:06:42] TimStarling: unrelated, I'm writing a patch to tear out the shared in lock mode, we came to the same conclusion (I only noticed your analysis in the early history after I already did my own). I did end up when and "why" it was was added, https://phabricator.wikimedia.org/T199393#10270676 [23:07:02] end up finding* [23:07:19] sounds good [23:07:26] there's a ton of abstraction that's been erected since so i'll need to tear some of that down as well or make it no-op. [23:07:47] thanks for merging my installer patches [23:07:57] do you want to be added as a reviewer on the rest of them? [23:08:06] you can try, no promises though [23:08:17] feel free to. [23:08:24] ok, thanks