code: func populatePerformanceData(testData TestToBuildData, testInfo *TestInfo, testTime *TestTime, job, build string, source Downloader) error {
  	contents, err := getDataFromFiles(job, build, "performance", source)
  	if err != nil {
  		return err
  	}
  	for _, data := range contents {
  		// Decode the data into obj.
  		var obj perftype.PerfData
  		if err := json.Unmarshal(data, &obj); err != nil {
  			return fmt.Errorf("failed to parse performance data: %v\ndata=\n%v", err, string(data))
  		}
  
  		// Ignore the metrics with unsupported versions.
  		if obj.Version != supportedMetricVersion {
  			continue
  		}
  
  		// Populate the metadata (testInfo and testTime) with the
  		// version and labels in the perf data.
  		if err := populateMetadata(testInfo, testTime, obj.Labels); err != nil {
  			return err
  		}
  
  		// Populate the result (testData) with the perf data.
  		node := formatNodeName(obj.Labels, job)
  		test := obj.Labels["test"]
  		data := testData.GetDataPerBuild(job, build, test, node)
  		data.Perf = append(data.Perf, obj.DataItems...)
  
  		removeStaledBuilds(testData, job, test, node, build)
  	}
  	return nil
  }
docs: // TODO(yguo0905): Consider extracting the common logic in
  // populatePerformanceData() and populateTimeSeriesData() into a function.
  // populatePerformanceData populates the perf data in testData and the metadata
  // in testInfo and testTime for the given test job at the given build using the
  // data fetched from source.