Uploaded image for project: 'Jira Server and Data Center'
  1. Jira Server and Data Center
  2. JRASERVER-72089

Autocomplete suggestions of sprint while doing a JQL search for sprints causing very high CPU utilization.

    XMLWordPrintable

Details

    Description

      Issue Summary

      Users, while searching for sprints in the advance search, Triggers rest API calls like below which are (nothing but autocomplete suggestions) and these are causing very HIGH CPU utilisation and load.

      GET /rest/api/2/jql/autocompletedata/suggestions?fieldName=Sprint&fieldValue=A&_=1609757846274 
      

      And this is the referrer

      https://<JIRA>/issues/?jql=Status%20not%20in%20(closed%2Cdone)%20and%20Sprint%20is%20not%20EMPTY%20"
      

      All these are browser sessions.

      Steps to Reproduce

      N/A
      Can be reproduced with more than 30k+ sprints and going to advance search and search for sprints.

      Expected Results

      The autocomplete shouldn't spike CPU and the response of the request should be quicker

      Actual Results

      CPU utlization shoots up and with an increasing number of threads going into Sprint autocomplete code, higher the spike and CPU load average.

      Here is the snippet of the thread causing high CPU
      The code that is invoked with the above call is

      	at org.apache.lucene.util.FixedBitSet.<init>(FixedBitSet.java:115)
      	at org.apache.lucene.util.DocIdSetBuilder.upgradeToBitSet(DocIdSetBuilder.java:235)
      	at org.apache.lucene.util.DocIdSetBuilder.grow(DocIdSetBuilder.java:178)
      	at org.apache.lucene.util.DocIdSetBuilder.add(DocIdSetBuilder.java:156)
      	at org.apache.lucene.search.TermInSetQuery$1.rewrite(TermInSetQuery.java:261)
      	at org.apache.lucene.search.TermInSetQuery$1.scorer(TermInSetQuery.java:313)
      	at org.apache.lucene.search.Weight.scorerSupplier(Weight.java:113)
      	at org.apache.lucene.search.LRUQueryCache$CachingWrapperWeight.scorerSupplier(LRUQueryCache.java:714)
      	at org.apache.lucene.search.BooleanWeight.scorerSupplier(BooleanWeight.java:329)
      	at org.apache.lucene.search.LRUQueryCache$CachingWrapperWeight.scorerSupplier(LRUQueryCache.java:714)
      	at org.apache.lucene.search.BooleanWeight.scorerSupplier(BooleanWeight.java:329)
      	at org.apache.lucene.search.BooleanWeight.scorer(BooleanWeight.java:295)
      	at org.apache.lucene.search.Weight.bulkScorer(Weight.java:147)
      	at org.apache.lucene.search.BooleanWeight.bulkScorer(BooleanWeight.java:289)
      	at org.apache.lucene.search.LRUQueryCache$CachingWrapperWeight.bulkScorer(LRUQueryCache.java:795)
      	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:657)
      	at org.apache.lucene.search.IndexSearcher.search(IndexSearcher.java:462)
      	at com.atlassian.jira.index.DelegateSearcher.search(DelegateSearcher.java:169)
      	at com.atlassian.jira.index.DelegateSearcher.search(DelegateSearcher.java:169)
      	at com.atlassian.jira.index.UnmanagedIndexSearcher.search(UnmanagedIndexSearcher.java:9)
      	at com.atlassian.jira.index.DelegateSearcher.search(DelegateSearcher.java:169)
      	at com.atlassian.jira.index.ManagedIndexSearcher.search(ManagedIndexSearcher.java:15)
      	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getHitCount(LuceneSearchProvider.java:178)
      	at com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getHitCount(LuceneSearchProvider.java:145)
      	at com.atlassian.jira.bc.issue.search.DefaultSearchService.searchCount(DefaultSearchService.java:130)
      	at sun.reflect.GeneratedMethodAccessor1742.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.atlassian.plugin.util.ContextClassLoaderSettingInvocationHandler.invoke(ContextClassLoaderSettingInvocationHandler.java:26)
      	at com.sun.proxy.$Proxy439.searchCount(Unknown Source)
      	at sun.reflect.GeneratedMethodAccessor1742.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
      	at java.lang.reflect.Method.invoke(Method.java:498)
      	at com.atlassian.plugin.osgi.bridge.external.HostComponentFactoryBean$DynamicServiceInvocationHandler.invoke(HostComponentFactoryBean.java:131)
      	at com.sun.proxy.$Proxy439.searchCount(Unknown Source)
      	at com.atlassian.greenhopper.service.sprint.SprintPermissionServiceImpl.getIssueCountForSprint(SprintPermissionServiceImpl.java:250)
      	at com.atlassian.greenhopper.service.sprint.SprintPermissionServiceImpl.canViewSprint(SprintPermissionServiceImpl.java:90)
      	at com.atlassian.greenhopper.customfield.sprint.SprintResolver.checkSprintAccessible(SprintResolver.java:31)
      	at com.atlassian.greenhopper.customfield.sprint.SprintResolver$SprintAccessible.apply(SprintResolver.java:139)
      	at com.atlassian.greenhopper.customfield.sprint.SprintResolver$SprintAccessible.apply(SprintResolver.java:125)
      	at com.google.common.base.Predicates$AndPredicate.apply(Predicates.java:353)
      	at com.google.common.collect.Iterators$5.computeNext(Iterators.java:639)
      	at com.google.common.collect.AbstractIterator.tryToComputeNext(AbstractIterator.java:141)
      	at com.google.common.collect.AbstractIterator.hasNext(AbstractIterator.java:136)
      	at com.google.common.collect.Iterators.addAll(Iterators.java:357)
      	at com.google.common.collect.Lists.newArrayList(Lists.java:147)
      	at com.google.common.collect.Lists.newArrayList(Lists.java:133)
      	at com.atlassian.greenhopper.customfield.sprint.SprintResolver.findSprintByPredicate(SprintResolver.java:78)
      	at com.atlassian.greenhopper.customfield.sprint.SprintResolver.findSprintByPredicate(SprintResolver.java:97)
      	at com.atlassian.greenhopper.customfield.sprint.SprintClauseValueGenerator.getPossibleValues(SprintClauseValueGenerator.java:40)
      

      Workaround

      • One workaround could be to disable the autocomplete (which is not so pleasant workaround.)
      • Another effective workaround could be to delay the requests which are sending the autocomplete suggestion. That is, adding the below JS in the announcement Banner
        <script type='text/javascript'>
        	jQuery().ready(function() {
        
        		$('textarea[id="advanced-search"]').focusin( function f() {	
        			if (!window.dirtypatch){ // trying avoid adding same event listener more than once 
        				setTimeout(
        					function() {
        						console.log("patching AutoComplete delay");
        						JIRA.AutoComplete.delay =  function delay(callback, l) {
        							if (delay.t) {
        								clearTimeout(delay.t);
        								delay.t = undefined;
        							}
        							delay.t = setTimeout(callback, 1 * 1000); // default is 0.3 * 1000
        						};
        					}, 1000); // patch is applied a second after search text are is focused, 
        							  // to give time for other initialization 
        				window.dirtypatch = 1;
        			}	
        		})
        	});
        </script>
        

      Attachments

        Issue Links

          Activity

            People

              szarazinski Sławomir Zaraziński
              amukkamala Aditya M
              Votes:
              2 Vote for this issue
              Watchers:
              13 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: