Answers: <p>I checked out the Jenkins source code, and I believe Jenkins uses the last 3 <em>successful</em> or <em>unstable</em> builds for its estimation. If it out of the last 6 builds it can't find 3 <em>successful</em> or <em>unstable</em> builds, it uses 1 or more of the last <em>completed</em> (not aborted) builds. It then takes the total duration time of the "candidates" and simply divides it by the number of candidates (i.e. mean of the durations). Here is the code I based this off of that can be found in the Job.java file in the <a href="https://github.com/jenkinsci/jenkins" rel="nofollow noreferrer">Jenkins repo</a>:</p>
  
  <pre><code>    /**
       * Returns candidate build for calculating the estimated duration of the current run.
       * 
       * Returns the 3 last successful (stable or unstable) builds, if there are any.
       * Failing to find 3 of those, it will return up to 3 last unsuccessful builds.
       * 
       * In any case it will not go more than 6 builds into the past to avoid costly build loading.
       */
      @SuppressWarnings("unchecked")
      protected List&lt;RunT&gt; getEstimatedDurationCandidates() {
          List&lt;RunT&gt; candidates = new ArrayList&lt;RunT&gt;(3);
          RunT lastSuccessful = getLastSuccessfulBuild();
          int lastSuccessfulNumber = -1;
          if (lastSuccessful != null) {
              candidates.add(lastSuccessful);
              lastSuccessfulNumber = lastSuccessful.getNumber();
          }
  
          int i = 0;
          RunT r = getLastBuild();
          List&lt;RunT&gt; fallbackCandidates = new ArrayList&lt;RunT&gt;(3);
          while (r != null &amp;&amp; candidates.size() &lt; 3 &amp;&amp; i &lt; 6) {
              if (!r.isBuilding() &amp;&amp; r.getResult() != null &amp;&amp; r.getNumber() != lastSuccessfulNumber) {
                  Result result = r.getResult();
                  if (result.isBetterOrEqualTo(Result.UNSTABLE)) {
                      candidates.add(r);
                  } else if (result.isCompleteBuild()) {
                      fallbackCandidates.add(r);
                  }
              }
              i++;
              r = r.getPreviousBuild();
          }
  
          while (candidates.size() &lt; 3) {
              if (fallbackCandidates.isEmpty())
                  break;
              RunT run = fallbackCandidates.remove(0);
              candidates.add(run);
          }
  
          return candidates;
      }
  
      public long getEstimatedDuration() {
          List&lt;RunT&gt; builds = getEstimatedDurationCandidates();
  
          if(builds.isEmpty())     return -1;
  
          long totalDuration = 0;
          for (RunT b : builds) {
              totalDuration += b.getDuration();
          }
          if(totalDuration==0) return -1;
  
          return Math.round((double)totalDuration / builds.size());
      }
  </code></pre>
  
Answers: CC BY-SA 3.0
Answers: 2018-03-29T15:17:01.403Z
Answers: That clears things up nicely, thank you! Still odd that the bars aren't resolving when they've already run 2-3+ times on the new Jenkins, but at least I know how the behavior is expected to work. Something to keep an eye on I guess
Answers: Alex
Answers: CC BY-SA 3.0
Answers: 2018-03-29T15:26:59.553Z
Answers: Glad I could help! I have always wondered how Jenkins derives these estimates. Your question gave me an excuse to look into it :) As for why you are seeing the wrong estimation, I always check plugin compatibility whenever I update Jenkins. Seemingly unrelated plugins can sometimes cause compatibility issues with other Jenkins components.
Answers: Preston Martin
Answers: CC BY-SA 3.0
Answers: 2018-03-29T15:32:17.003Z
Answers: Very true. 030 had a good point about Blue Ocean, it seems like they're always to blame when we get weird gui errors. I'll have to do some testing and find out!
Answers: Alex
Answers: CC BY-SA 3.0
Answers: 2018-03-29T15:12:42.347Z
Answers: 2018-04-02T13:27:51.740Z
Answers: 2018-04-02T13:27:51.740Z
Answers: Preston Martin
Body: <p>We just updated our Jenkins to v2.207.1 and our build estimation times on pipeline jobs have stopped showing up. Rather than a blue bar that when hovered over shows an estimate, we are now seeing the blue-and-white striped barber pole and an estimation of N/A. </p>
  
  <p>I believe this behavior might be only on pipeline jobs - we have so few freestyle jobs that I haven't seen them run yet.</p>
  
  <p>What logic does Jenkins use to calculate those estimations? How many builds will we need before those times fill back in?</p>
  
Comments: CC BY-SA 3.0
Comments: 2018-03-29T14:35:32.217Z
Comments: For freestyle or pipelines? Do you use bleuocean?
Comments: 030
Comments: CC BY-SA 3.0
Comments: 2018-03-29T14:39:56.327Z
Comments: @030 Pipelines, as said. And yes we do use blueocean but this is not in the BO interface, but in regular jenkins.
Comments: Alex
Tags: <jenkins>
Title: How many builds does jenkins need to run before it has estimated times?
UserDisplayName: Alex
ThreadText: # How many builds does jenkins need to run before it has estimated times?
  
  (Asked by: username_0 on 2018-03-29)
  
  We just updated our Jenkins to v2.207.1 and our build estimation times on pipeline jobs have stopped showing up. Rather than a blue bar that when hovered over shows an estimate, we are now seeing the blue-and-white striped barber pole and an estimation of N/A.
  
  I believe this behavior might be only on pipeline jobs - we have so few freestyle jobs that I haven't seen them run yet.
  
  What logic does Jenkins use to calculate those estimations? How many builds will we need before those times fill back in?
  
  **Tags:** jenkins
  
  > **Comments:**
  > **username_1**: For freestyle or pipelines? Do you use bleuocean?  
  > **username_0**: @username_1 Pipelines, as said. And yes we do use blueocean but this is not in the BO interface, but in regular jenkins.  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_2 on 2018-03-29. Score: 5 | Accepted answer
  
  I checked out the Jenkins source code, and I believe Jenkins uses the last 3 *successful* or *unstable* builds for its estimation. If it out of the last 6 builds it can't find 3 *successful* or *unstable* builds, it uses 1 or more of the last *completed* (not aborted) builds. It then takes the total duration time of the "candidates" and simply divides it by the number of candidates (i.e. mean of the durations). Here is the code I based this off of that can be found in the Job.java file in the [Jenkins repo](https://github.com/jenkinsci/jenkins):
  
  ```
      /**
       * Returns candidate build for calculating the estimated duration of the current run.
       * 
       * Returns the 3 last successful (stable or unstable) builds, if there are any.
       * Failing to find 3 of those, it will return up to 3 last unsuccessful builds.
       * 
       * In any case it will not go more than 6 builds into the past to avoid costly build loading.
       */
      @SuppressWarnings("unchecked")
      protected List<RunT> getEstimatedDurationCandidates() {
          List<RunT> candidates = new ArrayList<RunT>(3);
          RunT lastSuccessful = getLastSuccessfulBuild();
          int lastSuccessfulNumber = -1;
          if (lastSuccessful != null) {
              candidates.add(lastSuccessful);
              lastSuccessfulNumber = lastSuccessful.getNumber();
          }
  
          int i = 0;
          RunT r = getLastBuild();
          List<RunT> fallbackCandidates = new ArrayList<RunT>(3);
          while (r != null && candidates.size() < 3 && i < 6) {
              if (!r.isBuilding() && r.getResult() != null && r.getNumber() != lastSuccessfulNumber) {
                  Result result = r.getResult();
                  if (result.isBetterOrEqualTo(Result.UNSTABLE)) {
                      candidates.add(r);
                  } else if (result.isCompleteBuild()) {
                      fallbackCandidates.add(r);
                  }
              }
              i++;
              r = r.getPreviousBuild();
          }
  
          while (candidates.size() < 3) {
              if (fallbackCandidates.isEmpty())
                  break;
              RunT run = fallbackCandidates.remove(0);
              candidates.add(run);
          }
  
          return candidates;
      }
  
      public long getEstimatedDuration() {
          List<RunT> builds = getEstimatedDurationCandidates();
  
          if(builds.isEmpty())     return -1;
  
          long totalDuration = 0;
          for (RunT b : builds) {
              totalDuration += b.getDuration();
          }
          if(totalDuration==0) return -1;
  
          return Math.round((double)totalDuration / builds.size());
      }
  
  ```
  
  > **Comments:**
  > **username_0**: That clears things up nicely, thank you! Still odd that the bars aren't resolving when they've already run 2-3+ times on the new Jenkins, but at least I know how the behavior is expected to work. Something to keep an eye on I guess  
  > **username_2**: Glad I could help! I have always wondered how Jenkins derives these estimates. Your question gave me an excuse to look into it :) As for why you are seeing the wrong estimation, I always check plugin compatibility whenever I update Jenkins. Seemingly unrelated plugins can sometimes cause compatibility issues with other Jenkins components.  
  > **username_0**: Very true. 030 had a good point about Blue Ocean, it seems like they're always to blame when we get weird gui errors. I'll have to do some testing and find out!  
  
  ---
  
  