Esempio n. 1
0
    def _process_without_pandas(self, measurements_csv):
        per_frame_fps = []
        start_vsync, end_vsync = None, None
        frame_count = 0

        for frame_data in measurements_csv.iter_values():
            if frame_data.Flags_flags != 0:
                continue
            frame_count += 1

            if start_vsync is None:
                start_vsync = frame_data.Vsync_time_ns
            end_vsync = frame_data.Vsync_time_ns

            frame_time = frame_data.FrameCompleted_time_ns - frame_data.IntendedVsync_time_ns
            pff = 1e9 / frame_time
            if pff > self.drop_threshold:
                per_frame_fps.append([pff])

        if frame_count:
            duration = end_vsync - start_vsync
            fps = (1e9 * frame_count) / float(duration)
        else:
            duration = 0
            fps = 0

        csv_file = self._get_csv_file_name(measurements_csv.path)
        with csvwriter(csv_file) as writer:
            writer.writerow(['fps'])
            writer.writerows(per_frame_fps)

        return [DerivedMetric('fps', fps, 'fps'),
                DerivedMetric('total_frames', frame_count, 'frames'),
                MeasurementsCsv(csv_file)]
Esempio n. 2
0
 def process_raw(filepath, *args):
     metrics = []
     dump = gfxinfo_get_last_dump(filepath)
     seen_stats = False
     for line in dump.split('\n'):
         if seen_stats and not line.strip():
             break
         elif line.startswith('Janky frames:'):
             text = line.split(': ')[-1]
             val_text, pc_text = text.split('(')
             metrics.append(DerivedMetric('janks', numeric(val_text.strip()), 'count'))
             metrics.append(DerivedMetric('janks_pc', numeric(pc_text[:-3]), 'percent'))
         elif ' percentile: ' in line:
             ptile, val_text = line.split(' percentile: ')
             name = 'render_time_{}_ptile'.format(ptile)
             value = numeric(val_text.strip()[:-2])
             metrics.append(DerivedMetric(name, value, 'time_ms'))
         elif line.startswith('Number '):
             name_text, val_text = line.strip().split(': ')
             name = name_text[7:].lower().replace(' ', '_')
             value = numeric(val_text)
             metrics.append(DerivedMetric(name, value, 'count'))
         else:
             continue
         seen_stats = True
     return metrics
Esempio n. 3
0
    def _process_with_pandas(self, measurements_csv):
        data = pd.read_csv(measurements_csv.path)

        # fiter out bogus frames.
        bogus_frames_filter = data.actual_present_time_us != 0x7fffffffffffffff
        actual_present_times = data.actual_present_time_us[bogus_frames_filter]
        actual_present_time_deltas = actual_present_times.diff().dropna()

        vsyncs_to_compose = actual_present_time_deltas.div(VSYNC_INTERVAL)
        vsyncs_to_compose.apply(lambda x: int(round(x, 0)))

        # drop values lower than drop_threshold FPS as real in-game frame
        # rate is unlikely to drop below that (except on loading screens
        # etc, which should not be factored in frame rate calculation).
        per_frame_fps = (1.0 / (vsyncs_to_compose.multiply(VSYNC_INTERVAL / 1e9)))
        keep_filter = per_frame_fps > self.drop_threshold
        filtered_vsyncs_to_compose = vsyncs_to_compose[keep_filter]
        per_frame_fps.name = 'fps'

        csv_file = self._get_csv_file_name(measurements_csv.path)
        per_frame_fps.to_csv(csv_file, index=False, header=True)

        if not filtered_vsyncs_to_compose.empty:
            fps = 0
            total_vsyncs = filtered_vsyncs_to_compose.sum()
            frame_count = filtered_vsyncs_to_compose.size

            if total_vsyncs:
                fps = 1e9 * frame_count / (VSYNC_INTERVAL * total_vsyncs)

            janks = self._calc_janks(filtered_vsyncs_to_compose)
            not_at_vsync = self._calc_not_at_vsync(vsyncs_to_compose)
        else:
            fps = 0
            frame_count = 0
            janks = 0
            not_at_vsync = 0

        janks_pc = 0 if frame_count == 0 else janks * 100 / frame_count

        return [DerivedMetric('fps', fps, 'fps'),
                DerivedMetric('total_frames', frame_count, 'frames'),
                MeasurementsCsv(csv_file),
                DerivedMetric('janks', janks, 'count'),
                DerivedMetric('janks_pc', janks_pc, 'percent'),
                DerivedMetric('missed_vsync', not_at_vsync, 'count')]
Esempio n. 4
0
    def _process_with_pandas(self, measurements_csv):
        data = pd.read_csv(measurements_csv.path)
        data = data[data.Flags_flags == 0]
        frame_time = data.FrameCompleted_time_ns - data.IntendedVsync_time_ns
        per_frame_fps = (1e9 / frame_time)
        keep_filter = per_frame_fps > self.drop_threshold
        per_frame_fps = per_frame_fps[keep_filter]
        per_frame_fps.name = 'fps'

        frame_count = data.index.size
        if frame_count > 1:
            duration = data.Vsync_time_ns.iloc[-1] - data.Vsync_time_ns.iloc[0]
            fps = (1e9 * frame_count) / float(duration)
        else:
            duration = 0
            fps = 0

        csv_file = self._get_csv_file_name(measurements_csv.path)
        per_frame_fps.to_csv(csv_file, index=False, header=True)

        return [DerivedMetric('fps', fps, 'fps'),
                DerivedMetric('total_frames', frame_count, 'frames'),
                MeasurementsCsv(csv_file)]
Esempio n. 5
0
    def process(measurements_csv):

        should_calculate_energy = []
        use_timestamp = False

        # Determine sites to calculate energy for
        channel_map = defaultdict(list)
        for channel in measurements_csv.channels:
            channel_map[channel.site].append(channel.kind)
            if channel.site == 'timestamp':
                use_timestamp = True
                time_measurment = channel.measurement_type
        for site, kinds in channel_map.items():
            if 'power' in kinds and not 'energy' in kinds:
                should_calculate_energy.append(site)

        if measurements_csv.sample_rate_hz is None and not use_timestamp:
            msg = 'Timestamp data is unavailable, please provide a sample rate'
            raise ValueError(msg)

        if use_timestamp:
            # Find index of timestamp column
            ts_index = [
                i for i, chan in enumerate(measurements_csv.channels)
                if chan.site == 'timestamp'
            ]
            if len(ts_index) > 1:
                raise ValueError('Multiple timestamps detected')
            ts_index = ts_index[0]

        row_ts = 0
        last_ts = 0
        energy_results = defaultdict(dict)
        power_results = defaultdict(float)

        # Process data
        for count, row in enumerate(measurements_csv.iter_measurements()):
            if use_timestamp:
                last_ts = row_ts
                row_ts = time_measurment.convert(float(row[ts_index].value),
                                                 'time')
            for entry in row:
                channel = entry.channel
                site = channel.site
                if channel.kind == 'energy':
                    if count == 0:
                        energy_results[site]['start'] = entry.value
                    else:
                        energy_results[site]['end'] = entry.value

                if channel.kind == 'power':
                    power_results[site] += entry.value

                    if site in should_calculate_energy:
                        if count == 0:
                            energy_results[site]['start'] = 0
                            energy_results[site]['end'] = 0
                        elif use_timestamp:
                            energy_results[site]['end'] += entry.value * (
                                row_ts - last_ts)
                        else:
                            energy_results[site]['end'] += entry.value * (
                                1 / measurements_csv.sample_rate_hz)

        # Calculate final measurements
        derived_measurements = []
        for site in energy_results:
            total_energy = energy_results[site]['end'] - energy_results[site][
                'start']
            name = '{}_total_energy'.format(site)
            derived_measurements.append(
                DerivedMetric(name, total_energy, MEASUREMENT_TYPES['energy']))

        for site in power_results:
            power = power_results[site] / (count + 1)  #pylint: disable=undefined-loop-variable
            name = '{}_average_power'.format(site)
            derived_measurements.append(
                DerivedMetric(name, power, MEASUREMENT_TYPES['power']))

        return derived_measurements