Uploaded image for project: 'Jenkins'
  1. Jenkins
  2. JENKINS-35098

Poor performance of AutoBrowserHolder

XMLWordPrintable

      support-core analysis of slow requests turned up a case where rendering changelog information for a (Pipeline) job was consuming a lot of time with stack traces such as

      java.lang.String$CaseInsensitiveComparator.compare(String.java:1186)
      java.lang.String.compareToIgnoreCase(String.java:1239)
      hudson.util.CaseInsensitiveComparator.compare(CaseInsensitiveComparator.java:40)
      hudson.util.CaseInsensitiveComparator.compare(CaseInsensitiveComparator.java:34)
      jenkins.model.IdStrategy$CaseInsensitive.compare(IdStrategy.java:174)
      jenkins.model.IdStrategy.equals(IdStrategy.java:89)
      nectar.plugins.rbac.groups.Group.isMatch(Group.java:473)
      nectar.plugins.rbac.groups.Group.isMatch(Group.java:425)
      nectar.plugins.rbac.groups.Group.isMatch(Group.java:362)
      nectar.plugins.rbac.groups.GroupContainerACL.hasPermission(GroupContainerACL.java:157)
      nectar.plugins.rbac.groups.GroupContainerACL._hasPermission(GroupContainerACL.java:106)
      nectar.plugins.rbac.groups.GroupContainerACL.hasPermission(GroupContainerACL.java:72)
      hudson.security.ACL.hasPermission(ACL.java:73)
      hudson.model.AbstractItem.hasPermission(AbstractItem.java:505)
      com.cloudbees.hudson.plugins.folder.AbstractFolder.getItems(AbstractFolder.java:568)
      hudson.model.Items.getAllItems(Items.java:357)
      hudson.model.Items.getAllItems(Items.java:377)
      hudson.model.Items.getAllItems(Items.java:377)
      hudson.model.Items.getAllItems(Items.java:377)
      hudson.model.Items.getAllItems(Items.java:353)
      jenkins.model.Jenkins.getAllItems(Jenkins.java:1409)
      hudson.scm.AutoBrowserHolder.infer(AutoBrowserHolder.java:77)
      hudson.scm.AutoBrowserHolder.get(AutoBrowserHolder.java:64)
      hudson.scm.SCM.getEffectiveBrowser(SCM.java:136)
      org.jenkinsci.plugins.workflow.job.WorkflowRun.getChangeSets(WorkflowRun.java:612)
      com.cloudbees.workflow.rest.external.ChangeSetExt.hasChanges(ChangeSetExt.java:139)
      com.cloudbees.workflow.rest.external.RunExt.createOld(RunExt.java:324)
      com.cloudbees.workflow.rest.external.RunExt.create(RunExt.java:303)
      com.cloudbees.workflow.rest.external.JobExt.create(JobExt.java:126)
      com.cloudbees.workflow.rest.endpoints.JobAPI.doRuns(JobAPI.java:68)
      

      The top of the stack is specific to a proprietary AuthorizationStrategy, and the bottom is specific to pipeline-stage-view, but the middle clearly shows that SCM.getEffectiveBrowser is potentially rather expensive: if no RepositoryBrowser has been explicitly configured, and guessBrowser does not offer a default, then Jenkins will search all projects in the system (not including Pipeline) for similar SCM configurations which might let it infer the browser. The performance problem lies in the fact that a permission check must be done on each candidate project, lest a user of one job gain access to a secret SCM browser configuration from a job he would not otherwise be able to see (or even know of the existence of).

      This is an especially dubious feature in light of the fact that among all the OSS SCM plugins, there seem to be only two which actually implement isBrowserReusable: subversion; and cvs, which actually does so incorrectly (would produce bogus matches). So if for example you only use Git in your Jenkins installation, all this computation will be wasted.

      I propose to just delete this feature and deprecate the associated APIs. The more recently introduced guessBrowser is a more appropriate way to reduce the configuration burden for users of public hosting services. For users of private repositories, where guessBrowser is unlikely to work (depends on the SCM), various job templating systems are a more straightforward and predictable way of reducing repetition in Jenkins configuration.

      If there is someone who really finds this feature valuable, I think it would best be done as a plugin which explicitly offers to configure your repository browser on various jobs based on known examples; and/or there could be an extension point allowing for third-party contributions to guessBrowser. Either way, isBrowserReusable is not really needed for such features anyway; getKey (introduced alongside guessBrowser) is already more widely implemented and can be used for essentially the same purpose.

            jglick Jesse Glick
            jglick Jesse Glick
            Votes:
            0 Vote for this issue
            Watchers:
            2 Start watching this issue

              Created:
              Updated:
              Resolved: