Uploaded image for project: 'Jira Software Data Center'
  1. Jira Software Data Center
  2. JSWSERVER-24980

Performance issue with childIssuesOf() function because createLuceneQuery takes a lot of time due to excesive database calls

    XMLWordPrintable

Details

    • 8.17
    • 23
    • Severity 2 - Major
    • 69
    • Hide
      Atlassian Update – 21 Feb 2024

      Dear Customers,
      Thank you for reporting this issue. In the last weeks, we have been working on fixing it.

      After this change, you can observe a time reduction in the childIssuesOf() function.

      However, the performance issue for this function is composed of many root causes and requires us to solve also JSWSERVER-25535. Please follow JSWSERVER-25535 for further updates.

      The fix is ready, and we’re moving the status of this ticket to Waiting for release with Fix Version 9.15.

      Best regards,

      Daniel Dudziak
      Senior Software Engineer

      Show
      Atlassian Update – 21 Feb 2024 Dear Customers, Thank you for reporting this issue. In the last weeks, we have been working on fixing it. After this change, you can observe a time reduction in the childIssuesOf() function. However, the performance issue for this function is composed of many root causes and requires us to solve also  JSWSERVER-25535 . Please follow JSWSERVER-25535 for further updates. The fix is ready, and we’re moving the status of this ticket to Waiting for release with Fix Version 9.15. Best regards, Daniel Dudziak Senior Software Engineer

    Description

      Issue Summary

      When the number of children gets large(you have wide and deep tree dependency), the childIssuesOf() function could take a long time to return results. Or even cause an out-of-memory error for more see this JSWSERVER-25535.
      When this is used as the plan's source, it could be slow when loading.

      To recognise the problem find out JProfilej, JFR flame graphs or stack traces that point that Jira make a lot of database calls because it wants to create a JQL function. See below the stack trace and JProfiler output.  

       

      java.net.SocketInputStream.socketRead0(java.base@11.0.20/Native Method)
      java.net.SocketInputStream.socketRead(java.base@11.0.20/SocketInputStream.java:115)
      java.net.SocketInputStream.read(java.base@11.0.20/SocketInputStream.java:168)
      java.net.SocketInputStream.read(java.base@11.0.20/SocketInputStream.java:140)
      <---- some prepared statments specific to database ----->
      org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
      org.apache.commons.dbcp2.DelegatingPreparedStatement.executeQuery(DelegatingPreparedStatement.java:122)
      com.atlassian.jira.ofbiz.sql.PreparedStatementWrapper.executeQuery(PreparedStatementWrapper.java:42)
      com.atlassian.jira.diagnostic.connection.DiagnosticPreparedStatement.lambda$executeQuery$5(DiagnosticPreparedStatement.java:59)
      com.atlassian.jira.diagnostic.connection.DiagnosticPreparedStatement$$Lambda$3590/0x0000000803d9e440.execute(Unknown Source)
      com.atlassian.diagnostics.internal.platform.monitor.db.DefaultDatabaseDiagnosticsCollector.recordExecutionTime(DefaultDatabaseDiagnosticsCollector.java:91)
      com.atlassian.jira.diagnostic.connection.DatabaseDiagnosticsCollectorDelegate.recordExecutionTime(DatabaseDiagnosticsCollectorDelegate.java:62)
      com.atlassian.jira.diagnostic.connection.DiagnosticPreparedStatement.executeQuery(DiagnosticPreparedStatement.java:59)
      org.ofbiz.core.entity.jdbc.SQLProcessor.executeQuery(SQLProcessor.java:548)
      org.ofbiz.core.entity.GenericDAO.createEntityListIterator(GenericDAO.java:882)
      org.ofbiz.core.entity.GenericDAO.selectListIteratorByCondition(GenericDAO.java:862)
      org.ofbiz.core.entity.GenericHelperDAO.findListIteratorByCondition(GenericHelperDAO.java:216)
      org.ofbiz.core.entity.GenericDelegator.findListIteratorByCondition(GenericDelegator.java:1247)
      <---- hidden not relevant paths ----->
      com.atlassian.rm.common.bridges.jira.issue.IssueServiceBridgeImpl.getIssue(IssueServiceBridgeImpl.java:57)
      com.atlassian.rm.jpo.env.issues.JiraIssueService.getSimpleIssueAttributes(JiraIssueService.java:502)
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory.getIssueId(AbstractParentCustomFieldQueryFactory.java:122)
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory.access$000(AbstractParentCustomFieldQueryFactory.java:22)
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory$1.apply(AbstractParentCustomFieldQueryFactory.java:99)
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory$1.apply(AbstractParentCustomFieldQueryFactory.java:89)
      <---- hidden not relevant paths ----->
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory.toIssueIds(AbstractParentCustomFieldQueryFactory.java:86)
      com.atlassian.rm.jpo.customfields.parent.searcher.AbstractParentCustomFieldQueryFactory.getConfiguration(AbstractParentCustomFieldQueryFactory.java:54)
      com.atlassian.rm.jpo.customfields.lucene.parent.searcher.ParentCustomFieldClauseQueryFactory.getQuery(ParentCustomFieldClauseQueryFactory.java:80)
      com.atlassian.jira.jql.query.ContextAwareQueryVisitor.visit(ContextAwareQueryVisitor.java:98)
      com.atlassian.jira.jql.query.ContextAwareQueryVisitor.visit(ContextAwareQueryVisitor.java:27)
      com.atlassian.query.clause.TerminalClauseImpl.accept(TerminalClauseImpl.java:143)
      com.atlassian.jira.jql.query.QueryVisitor.createQuery(QueryVisitor.java:51)
      com.atlassian.jira.jql.query.DefaultLuceneQueryBuilder.createLuceneQuery(DefaultLuceneQueryBuilder.java:29)
      com.atlassian.jira.issue.search.providers.LuceneSearchProvider.createLuceneQuery(LuceneSearchProvider.java:343)
      com.atlassian.jira.issue.search.providers.LuceneSearchProvider.getHits(LuceneSearchProvider.java:229)
      com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:375)
      com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:138)
      com.atlassian.jira.issue.search.providers.LuceneSearchProvider.search(LuceneSearchProvider.java:143)
      com.atlassian.jira.bc.issue.search.DefaultSearchService.search(DefaultSearchService.java:118)
      <---- hidden not relevant paths ----->
      com.atlassian.rm.common.bridges.jira.issue.search.SearchServiceBridgeImpl.search(SearchServiceBridgeImpl.java:39)
      com.atlassian.rm.jpo.env.issues.JiraIssueService.findIssues(JiraIssueService.java:351)
      com.atlassian.rm.jpo.env.issues.JiraIssueService.findIssuesWhereFieldInList(JiraIssueService.java:325)
      com.atlassian.rm.jpo.jql.functions.ChildIssuesOfFunction.childIssuesOf(ChildIssuesOfFunction.java:84)
      com.atlassian.rm.jpo.jql.functions.ChildIssuesOfFunction.getValues(ChildIssuesOfFunction.java:58)
      com.atlassian.rm.jpo.jql.functions.base.BaseJqlFunction.getValues(BaseJqlFunction.java:65)
      com.atlassian.jira.jql.operand.FunctionOperandHandler$3.call(FunctionOperandHandler.java:61)
      com.atlassian.jira.jql.operand.FunctionOperandHandler$3.call(FunctionOperandHandler.java:58)

      Steps to Reproduce

      1. Create +4 hierarchy levels above epic.
      2. Create 64k~ issues(dependency tree) that are connected together via Parent Link, Epic Link and Parent fields:
        each parent should have ~6 children, except Epic that have around ~40 task issues. Additionally, ~1000 tasks should have 10 subtasks. = ~64k issues
      3. Search by JQL
      issuekey in childIssuesOf(<parent-issue-key>) 

      Expected Results

      It takes around 4s(or faster) to perform a search.

      Actual Results

      It takes around 10-15s(or more for bigger datasets) to perform a search.

      Workaround

      Users may want to write new JQLs using a combination of ScriptRunner functions:

      The Jira administrator may choose to prevent the usage of this JQL function by disabling the following module of the Advanced Roadmaps plans plugin:

      • Child issues of (jpo-jql-function-recursive-children-lookup)

       
      If you'd like to follow that route, you can follow the steps below:

      1. Go to Jira administration (gear icon) > Manage Apps > Manage Apps
      2. Change the filter to "All apps".
      3. Locate and expand the "Advanced Roadmaps plans" section.
      4. Locate and turn off the "Child issues of (jpo-jql-function-recursive-children-lookup)" module.

      This is a choice between stability and feature that an admin might want to take if the childIssuesOf JQL function becomes a major problem to an instance.

      Attachments

        Issue Links

          Activity

            People

              Unassigned Unassigned
              azuhra Aqqiela
              Votes:
              18 Vote for this issue
              Watchers:
              31 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: