constructor(samples, testName, sampleName) {
    if (samples.length < 1) {
      throw new Error(`BenchmarkStats for ${testName} has no samples. SampleName: ${sampleName}`)
    }

    let sortedSamples = samples.slice().sort((a, b) => a - b)

    // Throw out the top 0.1% to cut down on very large anomalies
    sortedSamples = sortedSamples.slice(0, Math.floor(samples.length * 0.999))

    this.numSamples = sortedSamples.length
    let sum = 0
    let sumOfSquares = 0
    sortedSamples.forEach((sample) => {
      sum += sample
      sumOfSquares += sample * sample
    })

    this.mean = sum / this.numSamples
    this.stdDev = Math.sqrt(sumOfSquares / this.numSamples - this.mean * this.mean)
    this.max = sortedSamples[sortedSamples.length - 1]
    this.min = sortedSamples[0]
    this['5thPercentile'] = sortedSamples[Math.floor(samples.length * 0.05)]
    this['95thPercentile'] = sortedSamples[Math.floor(samples.length * 0.95)]
    this.median = sortedSamples[Math.floor(samples.length * 0.5)]
  }
Class representing the statistical analysis of the benchmark test runs
@class
@param {Array} samples Array of deltas of CPU performances
@param {string} testName Name of this test
@param {string} sampleName Name of the kind of test sample being run. This is displayed only if
  the test produces no samples--likely an indicator of a benchmark test returning before tests
  have finished.