Any feedback / experience on this topic is highly appreciated :-)Luca.
--
--
To unsubscribe, email repo-discuss...@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
--
To unsubscribe, email repo-discuss+unsub...@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
Hi Gerrit devs,we are running on GerritHub.io the "latest and greatest" of Gerrit master (2.12-rc0-247-g6a86b1b) but I still see quite a lot of SQL queries when an anonymous user is accessing https://review.gerrithub.io.It all seems caused by this REST API execution:curl 'https://review.gerrithub.io/changes/?n=25&O=81' -H 'Pragma: no-cache' -H 'Accept: application/json' -H 'Referer: https://review.gerrithub.io/' -H 'Cache-Control: no-cache'
I was hoping that after all the fixes made on master in improving the use of Gerrit caches ... the # of generated SQL queries would have gone down.It actually did go down but not enough :-(That specific HTTP REST API is actually still responsible for the 87% of our HTTP latency :-OMy understanding is that the list of open changes should be 100% resolved using Lucene Indexes, but I am possibly wrong :-(
The "top" SQL queries are:SELECT T.change_key,T.created_on,T.last_updated_on,T.owner_account_id,T.dest_project_name,T.dest_branch_name,T.status,T.current_patch_set_id,T.subject,T.topic,T.original_subject,T.submission_id,T.row_version,T.change_id FROM changes T WHERE T.change_id=?
Am Montag, 23. November 2015 15:02:06 UTC+1 schrieb lucamilanesio:Hi Gerrit devs,we are running on GerritHub.io the "latest and greatest" of Gerrit master (2.12-rc0-247-g6a86b1b) but I still see quite a lot of SQL queries when an anonymous user is accessing https://review.gerrithub.io.It all seems caused by this REST API execution:curl 'https://review.gerrithub.io/changes/?n=25&O=81' -H 'Pragma: no-cache' -H 'Accept: application/json' -H 'Referer: https://review.gerrithub.io/' -H 'Cache-Control: no-cache'How you correlate this REST API call with SQL query? Javamelody plugin?
I was hoping that after all the fixes made on master in improving the use of Gerrit caches ... the # of generated SQL queries would have gone down.It actually did go down but not enough :-(That specific HTTP REST API is actually still responsible for the 87% of our HTTP latency :-OMy understanding is that the list of open changes should be 100% resolved using Lucene Indexes, but I am possibly wrong :-(No. You are correct. We have even unit test that verifies that thisquery doesn't touch the database: [1]. I just re-checked on mostrecent master (v2.12-rc0-264-g6f7ccf5). It works here as expected.
public static void ensureChangeLoaded(Iterable<ChangeData> changes)
throws OrmException {
ChangeData first = Iterables.getFirst(changes, null);
if (first == null) {
return;
} else if (first.notesMigration.readChanges()) {
for (ChangeData cd : changes) {
cd.change();
}
}
Map<Change.Id, ChangeData> missing = Maps.newHashMap();
for (ChangeData cd : changes) {
if (cd.change == null) {
missing.put(cd.getId(), cd);
}
}
if (missing.isEmpty()) {
return;
}
for (Change change : first.db.changes().get(missing.keySet())) {
missing.get(change.getId()).change = change;
}
}
It seems that if ChangeData.change is null (how can it be? Can Lucene return a null object?) then the changes with that corresponding IDs are loaded from the DB.
Is it possible that I have problems on my Lucene Index? Is there any situation where the Lucene index returns the ID but not the object?
The "top" SQL queries are:SELECT T.change_key,T.created_on,T.last_updated_on,T.owner_account_id,T.dest_project_name,T.dest_branch_name,T.status,T.current_patch_set_id,T.subject,T.topic,T.original_subject,T.submission_id,T.row_version,T.change_id FROM changes T WHERE T.change_id=?The better question is to corelate the top SQL query with the actual action that triggers it.I think that database is not touched when list of changes is rendered. At least not on mostrecent master.
Hi David, see my feedback below.
On Monday, November 23, 2015 at 7:57:28 PM UTC, David Ostrovsky wrote:
Am Montag, 23. November 2015 15:02:06 UTC+1 schrieb lucamilanesio:Hi Gerrit devs,we are running on GerritHub.io the "latest and greatest" of Gerrit master (2.12-rc0-247-g6a86b1b) but I still see quite a lot of SQL queries when an anonymous user is accessing https://review.gerrithub.io.It all seems caused by this REST API execution:curl 'https://review.gerrithub.io/changes/?n=25&O=81' -H 'Pragma: no-cache' -H 'Accept: application/json' -H 'Referer: https://review.gerrithub.io/' -H 'Cache-Control: no-cache'How you correlate this REST API call with SQL query? Javamelody plugin?Yes, and it lists the SQL queries executed on the /changes/ URI invocation.
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
Forgot to include the SQL statements:#1 - Starred changes:SELECT T.account_id,T.change_id FROM starred_changes T WHERE T.account_id=?
#2 - Draft changes:SELECT T.line_nbr,T.author_id,T.written_on,T.status,T.side,T.message,T.parent_uuid,T.range_start_line,T.range_start_character,T.range_end_line,T.range_end_character,T.change_id,T.patch_set_id,T.file_name,T.uuid FROM patch_comments T WHERE T.status='d' AND T.author_id=?
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
I am digging down now on the query killer #1 and I think I've found a point where it gets triggered *a lot* of times:
Just a picture of the past 24h of the SQL hits per minute:You may notice the 4500 sql calls / minute (75 SQL queries per second) around 7 AM CET, and there wasn't so much traffic going to the site at the moment.Can't generate 4500 stack traces in production :-(I have to proceed with code-inspection first ...
On 17 Dec 2015, at 09:16, Matthias Sohn <matthi...@gmail.com> wrote:
On Thu, Dec 17, 2015 at 9:41 AM, Luca Milanesio <luca.mi...@gmail.com> wrote:
Just a picture of the past 24h of the SQL hits per minute:
<Screen Shot 2015-12-17 at 08.36.56.png>
You may notice the 4500 sql calls / minute (75 SQL queries per second) around 7 AM CET, and there wasn't so much traffic going to the site at the moment.Can't generate 4500 stack traces in production :-(I have to proceed with code-inspection first ...
you could log stack-traces for a small fraction of the requests in order to reduce the overhead.At this high rate of db queries you should still get enough information from these samples.
-Matthias
On 17 Dec 2015, at 09:21, Luca Milanesio <Luca.Mi...@gmail.com> wrote:
... instrumenting now ... will post laster today the stack-traces so that we can comment on "facts" rather than code-inspection-based guesses :-)
On 17 Dec 2015, at 11:51, Luca Milanesio <Luca.Mi...@gmail.com> wrote:Stack-traces coming ... there are actuall 10 different scenarios where a Gerrit query (which isn't supposed to be resolved on the DB) triggers a Get change by ID query on the DB:#1 - First conflicts query>> com.google.gerrit.server.query.change.ChangeQueryBuilder.parseChange(ChangeQueryBuilder.java:975) >> com.google.gerrit.server.query.change.ChangeQueryBuilder.conflicts(ChangeQueryBuilder.java:479) >> sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source) >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >> java.lang.reflect.Method.invoke(Method.java:606) >> com.google.gerrit.server.query.QueryBuilder$ReflectionFactory.create(QueryBuilder.java:352) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:273) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:258) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:227) >> com.google.gerrit.server.query.QueryBuilder.children(QueryBuilder.java:311) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:217) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:189) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:208) >> com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) >> com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)
#2 - Access control on changes>> com.google.gerrit.server.project.ChangeControl$GenericFactory.controlFor(ChangeControl.java:60) >> com.google.gerrit.server.ChangeUtil.findChanges(ChangeUtil.java:350) >> com.google.gerrit.server.change.ChangesCollection.parse(ChangesCollection.java:88) >> com.google.gerrit.server.change.ChangesCollection.parse(ChangesCollection.java:42) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:240) >> javax.servlet.http.HttpServlet.service(HttpServlet.java:729) >> com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:287) >> com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:277) >> com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:182)
#3 - Another conflicts query>> com.google.gerrit.server.query.change.ChangeQueryBuilder.parseChange(ChangeQueryBuilder.java:975) >> com.google.gerrit.server.query.change.ChangeQueryBuilder.conflicts(ChangeQueryBuilder.java:479) >> sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) >> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >> java.lang.reflect.Method.invoke(Method.java:606) >> com.google.gerrit.server.query.QueryBuilder$ReflectionFactory.create(QueryBuilder.java:352) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:273) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:258) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:227) >> com.google.gerrit.server.query.QueryBuilder.children(QueryBuilder.java:311) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:217) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:189) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:208) >> com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) >> com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)
com.google.gerrit.server.query.change.IsStarredByPredicate.read(IsStarredByPredicate.java:70) >> com.google.gerrit.server.query.change.AndSource.readImpl(AndSource.java:115) >> com.google.gerrit.server.query.change.AndSource.read(AndSource.java:99) >> com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:186) >> com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:123) >> com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) >> com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)
com.google.gerrit.server.query.change.ChangeData.reloadChange(ChangeData.java:581) >> com.google.gerrit.server.query.change.ChangeData.change(ChangeData.java:571) >> com.google.gerrit.server.git.ChangeSet.changesByProject(ChangeSet.java:89) >> com.google.gerrit.server.git.MergeSuperSet.completeChangeSetWithoutTopic(MergeSuperSet.java:100) >> com.google.gerrit.server.git.MergeSuperSet.completeChangeSet(MergeSuperSet.java:91) >> com.google.gerrit.server.change.GetRevisionActions.getETag(GetRevisionActions.java:71) >> com.google.gerrit.server.change.GetRevisionActions.getETag(GetRevisionActions.java:39) >> com.google.gerrit.httpd.restapi.RestApiServlet.addResourceStateHeaders(RestApiServlet.java:489) >> com.google.gerrit.httpd.restapi.RestApiServlet.configureCaching(RestApiServlet.java:469) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:345)
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
To unsubscribe, email repo-discuss...@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
ping ... any feedback on the "facts" ?
I have found another stack-trace with a possibly very easy fix:PatchLineCommentAccess.draftByAuthor(<userId>) - > com.google.gerrit.server.PatchLineCommentsUtil.draftByAuthor(PatchLineCommentsUtil.java:275) > com.google.gerrit.server.query.change.HasDraftByPredicate.read(HasDraftByPredicate.java:54) > com.google.gerrit.server.query.change.AndSource.readImpl(AndSource.java:115) > com.google.gerrit.server.query.change.AndSource.read(AndSource.java:99) > com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:186) > com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:123) > com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) > com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) > com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) > com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) > com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)It seems that the "hasDraftBy" predicate is widely used but the list of drafts comments isn't cached anywhere and is loaded over and over again from the DB all the times.The Gerrit query that triggers the above stack trace is typically something like:/changes/?q=has:draft&n=25&O=81The hit rate is not very high on GerritHub.io, around 10K calls/day, but the caching wouldn't occupy that much memory (most of the people don't leave draft comments opened) *and* will still save quite a few DB calls.
My first comments and ideas of improvements (for facilitating the discussion):On 17 Dec 2015, at 11:51, Luca Milanesio <Luca.Mi...@gmail.com> wrote:Stack-traces coming ... there are actuall 10 different scenarios where a Gerrit query (which isn't supposed to be resolved on the DB) triggers a Get change by ID query on the DB:#1 - First conflicts query>> com.google.gerrit.server.query.change.ChangeQueryBuilder.parseChange(ChangeQueryBuilder.java:975) >> com.google.gerrit.server.query.change.ChangeQueryBuilder.conflicts(ChangeQueryBuilder.java:479) >> sun.reflect.GeneratedMethodAccessor59.invoke(Unknown Source) >> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) >> java.lang.reflect.Method.invoke(Method.java:606) >> com.google.gerrit.server.query.QueryBuilder$ReflectionFactory.create(QueryBuilder.java:352) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:273) >> com.google.gerrit.server.query.QueryBuilder.operator(QueryBuilder.java:258) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:227) >> com.google.gerrit.server.query.QueryBuilder.children(QueryBuilder.java:311) >> com.google.gerrit.server.query.QueryBuilder.toPredicate(QueryBuilder.java:217) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:189) >> com.google.gerrit.server.query.QueryBuilder.parse(QueryBuilder.java:208) >> com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) >> com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)We could easily get the change data from the index here, without having to go to the DB.The code is actually there but it seems that we are not indexing by the change number (PATH_LEGACY_ID)?private static final Pattern PAT_LEGACY_ID = Pattern.compile("^[1-9][0-9]*$");private static final Pattern PAT_CHANGE_ID = Pattern.compile("^[iI][0-9a-f]{4,}.*$");#2 - Access control on changes>> com.google.gerrit.server.project.ChangeControl$GenericFactory.controlFor(ChangeControl.java:60) >> com.google.gerrit.server.ChangeUtil.findChanges(ChangeUtil.java:350) >> com.google.gerrit.server.change.ChangesCollection.parse(ChangesCollection.java:88) >> com.google.gerrit.server.change.ChangesCollection.parse(ChangesCollection.java:42) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:240) >> javax.servlet.http.HttpServlet.service(HttpServlet.java:729) >> com.google.inject.servlet.ServletDefinition.doServiceImpl(ServletDefinition.java:287) >> com.google.inject.servlet.ServletDefinition.doService(ServletDefinition.java:277) >> com.google.inject.servlet.ServletDefinition.service(ServletDefinition.java:182)This is the one I have already found by code-inspection: again I can't see any reason why we couldn't get the same info from the Index without having to go to the DB.
Another stack-trace coming ...#4 - Is starredcom.google.gerrit.server.query.change.IsStarredByPredicate.read(IsStarredByPredicate.java:70) >> com.google.gerrit.server.query.change.AndSource.readImpl(AndSource.java:115) >> com.google.gerrit.server.query.change.AndSource.read(AndSource.java:99) >> com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:186) >> com.google.gerrit.server.query.change.QueryProcessor.queryChanges(QueryProcessor.java:123) >> com.google.gerrit.server.query.change.QueryChanges.query0(QueryChanges.java:144) >> com.google.gerrit.server.query.change.QueryChanges.query(QueryChanges.java:133) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:99) >> com.google.gerrit.server.query.change.QueryChanges.apply(QueryChanges.java:40) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:329)
#5 - Changes by project (when calculating the e-tag?)
com.google.gerrit.server.query.change.ChangeData.reloadChange(ChangeData.java:581) >> com.google.gerrit.server.query.change.ChangeData.change(ChangeData.java:571) >> com.google.gerrit.server.git.ChangeSet.changesByProject(ChangeSet.java:89) >> com.google.gerrit.server.git.MergeSuperSet.completeChangeSetWithoutTopic(MergeSuperSet.java:100) >> com.google.gerrit.server.git.MergeSuperSet.completeChangeSet(MergeSuperSet.java:91) >> com.google.gerrit.server.change.GetRevisionActions.getETag(GetRevisionActions.java:71) >> com.google.gerrit.server.change.GetRevisionActions.getETag(GetRevisionActions.java:39) >> com.google.gerrit.httpd.restapi.RestApiServlet.addResourceStateHeaders(RestApiServlet.java:489) >> com.google.gerrit.httpd.restapi.RestApiServlet.configureCaching(RestApiServlet.java:469) >> com.google.gerrit.httpd.restapi.RestApiServlet.service(RestApiServlet.java:345)
To unsubscribe, email repo-discuss...@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
Hi Dave,thanks for clarifying this :-) this helps a lot in deciding which direction to take to improve the DB performance.Can we just then introduce some extra caching for the worst hit queries?... again, it impacts over the 80% of our servers load and many times we are making the same exact queries over and over again, thousands of times :-(
The problem of extra-caching is the memory footprint and potentially a further slowdown of the server because of GCs :-(That's why I was thinking about trusting the index as much as possible, but I see the point of the fact that index is an index, isn't a data-store or a cache.There are definitely three top queries (see the monthly numbers associated):#1 - 1.5M calls / month => select * from changes where change_id=?#2 - 750K calls / month => select * from patch_sets where change_id=? order by patch_set_id#3 - 600K calls / month => select * from patch_set_approvals where change_id=?
I can work out the stack traces starting from #1 and *most* of them are pointing to the same directions: stack #1 and #2.
I've seen regular use-cases of the search (invoked as well on the change-screen multiple times) causing the fetch of the same change over and over again, up to 5 times for the same screen.Even very short-lived cache (let's say only 5 to 10 minutes)
Hi Dave,The problem is not the total number of queries but the way they are distributed.There are peaks of thousands of queries without any specific reason, mostly associated with some specific search patterns.
This is a symptom of a bug IMHO.
If I search for change X I am expecting 1x query for this change, not dozens or hundreds for the same key.
Yes, server performance could still be bearable, but this isn't the point. I am aiming on founding and fixing problems that are not impacting only GerritHub.io but potentially other people using Gerrit.I saw the same peaks at some of our clients installations and I need to understand and focuses gin resolving them.With regards to response times of the search page, we are talking abounds seconds (up to 5-10 sometimes) not msec :-(
I'll start to make some of the instrumentation permanent in production with the reference of the incoming HTTP Url and time stamp, so that I can get a more accurate picture over time.
--
Hi David,Thanks for the input: I've rolled out to prod the instrumented patch and will have some feedback by mid next week.The change you suggested should ease a bit the traffic, maybe by raising to 5 minutes the refresh interval, assuming that is the cause of the overload.I doubt however that it could generate the peaks I was showing in the graphs, as you should have thousands of users having their browsers opened on a specific change exactly at the same time: possible but unlikely IMHO.
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
@Override
public void run() {
if (!screen.isAttached()) {
// screen should have cancelled this timer.
cancel();
return;
} else if (running) {
return;
}
running = true;
screen.loadChangeInfo(false, new AsyncCallback<ChangeInfo>() {
@Override
public void onSuccess(ChangeInfo info) {
running = false;
screen.showUpdates(info);
int d = UserActivityMonitor.isActive()
? POLL_PERIOD
: IDLE_PERIOD;
if (d != delay) {
delay = d;
schedule();
}
}
Idle period is 2h.
Something isn't quite working as I see the polling going on for hours for some users.
Will try to reproduce the problem locally as there is possibly some bug somewhere ...
Luca
private static final long TIMEOUT = 10 * 60 * 1000;
@Override
public boolean execute() {
long now = System.currentTimeMillis();
if (recent) {
if (!active) {
ValueChangeEvent.fire(this, active);
}
recent = false;
active = true;
last = now;
} else if (active && (now - last) > TIMEOUT) {
active = false;
ValueChangeEvent.fire(this, false);
}
return true;
}
It actually works: after 10' of user's inactivity, the polling stops.
The background noise generated by the polling is thus negligible, as quite unlikely 7K users will have a single change opened all the time for hours and keep on interacting with it once every 10'.I can see the pattern of the polls and exclude them from my analysis as well as it wasn't a query after all :-)
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
On 21 Dec 2015, at 10:47, David Ostrovsky <david.o...@gmail.com> wrote:
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss...@googlegroups.com.
I was wondering, even in this scenario: imagine you have change Nr. 123 opened and you've already been notified that there is something new available.From the first notification, you you know that your screen is outdated: why on earth does the client keep on polling? Even if there are even more new updates available, is your UX going to change because of that?Once the screen has been notified of being outdated, we should automatically stop polling IMHO.Any disagreement on that?
On Mon, Dec 21, 2015 at 4:26 AM, Luca Milanesio <luca.mi...@gmail.com> wrote:I was wondering, even in this scenario: imagine you have change Nr. 123 opened and you've already been notified that there is something new available.From the first notification, you you know that your screen is outdated: why on earth does the client keep on polling? Even if there are even more new updates available, is your UX going to change because of that?Once the screen has been notified of being outdated, we should automatically stop polling IMHO.Any disagreement on that?No disagreement here.
An additional potential feature on top of that might be to actually reload the change screen if the user is inactive. That is, don't surprise them by reloading in the middle of doing something, but if they haven't looked in a while, it's ok to reload behind their back. (This assumes the code to detect inactivity is working of course.)
On 21 Dec 2015, at 20:18, Shawn Pearce <s...@google.com> wrote:On Mon, Dec 21, 2015 at 10:56 AM, 'Dave Borowitz' via Repo and Gerrit Discussion <repo-d...@googlegroups.com> wrote:On Mon, Dec 21, 2015 at 4:26 AM, Luca Milanesio <luca.mi...@gmail.com> wrote:I was wondering, even in this scenario: imagine you have change Nr. 123 opened and you've already been notified that there is something new available.From the first notification, you you know that your screen is outdated: why on earth does the client keep on polling? Even if there are even more new updates available, is your UX going to change because of that?Once the screen has been notified of being outdated, we should automatically stop polling IMHO.Any disagreement on that?No disagreement here.It keeps polling to get more names to show updates from. So just "Update from Jenkins" may not be interesting, but "Update from Jekins, Dave Borowitz" now has more of my interest because a human has replied.
An additional potential feature on top of that might be to actually reload the change screen if the user is inactive. That is, don't surprise them by reloading in the middle of doing something, but if they haven't looked in a while, it's ok to reload behind their back. (This assumes the code to detect inactivity is working of course.)True, I've thought about this and kind of wanted it, but it the loss of context may be confusing if I switch tabs to research something (making this tab idle), but I come back thinking I'm going to navigate to a file so I can add a comment or delete a draft. Refreshing just because Jenkins voted or there is a new patch set could be undesirable.
ChangeAccess.get(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
PatchLineCommentAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
PatchSetAccess.byChange(256052)
ChangeAccess.get(256052)
ChangeAccess.get(256052)
... that sounds a bug to me :-)
Luca.
To unsubscribe, email repo-discuss+unsubscribe@googlegroups.com
More info at http://groups.google.com/group/repo-discuss?hl=en
---
You received this message because you are subscribed to the Google Groups "Repo and Gerrit Discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to repo-discuss+unsubscribe@googlegroups.com.
The total call took around 0.6 seconds to execute (still quite fast :-O) but regarding peak, it generated a 86 TPS because of a single REST call!If we are unlucky, and we get ten users doing the same thing at the same time (with around 7K users on the platform, it may happen), then a peak of DB queries is quite likely to happen.
In *this particular case*, do we need to reload the same change (and the list of patches) over 40 times in a single call?Even a very simple thread-local temporary cache on changes would save *hundreds* of TPS and ease the load on the DB by a couple of order of magnitudes!
On 23 Dec 2015, at 10:35, David Ostrovsky <david.o...@gmail.com> wrote:Thanks, Luca. You picked really interesting REST handler case,adding reviewers as a group. The code, wasn't optimized foraccepting a group, and what happens there is N-queries antipattern for one single database record.
Am Dienstag, 22. Dezember 2015 11:59:17 UTC+1 schrieb lucamilanesio:The total call took around 0.6 seconds to execute (still quite fast :-O) but regarding peak, it generated a 86 TPS because of a single REST call!If we are unlucky, and we get ten users doing the same thing at the same time (with around 7K users on the platform, it may happen), then a peak of DB queries is quite likely to happen.This is even worse: the amount of SQL queries isn't constant with some upper limit N,but depends on the member number in the group: 1k members: 1k queries for singleREST call.
Very naive approach to optimize for adding a group as reviewer use case would be to exposenew method in ChangeHooks interface doReviewersAddedHook:void doReviewersAddedHook(Change change, Collection<Account> account,PatchSet patchSet, ReviewDb db) throws OrmException;Even more annoying in the hooks/event triggering code above is the fact, that all those Ndifferent ChangeData retrievals were in vain, at least on my test instance, on most recentmaster with a couple plugins installed. There are no hooks deployed at all, and only reviewersplugin and core MetricListener contribute Change listeners, but the reviewers plugin onlycares about PatchSetCreatedEvent:@Overridepublic void onEvent(Event event) {if (!(event instanceof PatchSetCreatedEvent)) {return;}[...]And MetricListener only counts and increments the type of the event, without actually consumingthe event itself. So i wonder if we could use some smart guava Suppliers approach here, that onlyretrieves the data, when it is actually used and not only to keep the database, Git and GC busy.