Exemple #1
0
    def CollectProfile(self):
        if ('renderer' in self._output_file and not self._is_android
                and not self._platform_backend.GetCommandLine(self._pid)):
            logging.warning('Renderer was swapped out during profiling. '
                            'To collect a full profile rerun with '
                            '"--extra-browser-args=--single-process"')
        if self._is_android:
            device = self._browser_backend.device
            try:
                binary_name = os.path.basename(self._perf_binary)
                device.KillAll(binary_name,
                               signum=signal.SIGINT,
                               blocking=True,
                               quiet=True)
            except device_errors.CommandFailedError:
                logging.warning(
                    'The perf process could not be killed on the device.')
        self._proc.send_signal(signal.SIGINT)
        exit_code = self._proc.wait()
        try:
            if exit_code == 128:
                raise Exception("""perf failed with exit code 128.
Try rerunning this script under sudo or setting
/proc/sys/kernel/perf_event_paranoid to "-1".\nOutput:\n%s""" %
                                self._GetStdOut())
            elif exit_code not in (0, -2):
                raise Exception('perf failed with exit code %d. Output:\n%s' %
                                (exit_code, self._GetStdOut()))
        finally:
            self._tmp_output_file.close()
        cmd = '%s report -n -i %s' % (_NicePath(
            self._perfhost_binary), self._output_file)
        if self._is_android:
            device = self._browser_backend.device
            device.PullFile(self._device_output_file, self._output_file)
            required_libs = \
                android_profiling_helper.GetRequiredLibrariesForPerfProfile(
                    self._output_file)
            symfs_root = os.path.join(os.path.dirname(self._output_file),
                                      'symfs')
            if not os.path.exists(symfs_root):
                os.makedirs(symfs_root)
            kallsyms = android_profiling_helper.CreateSymFs(device,
                                                            symfs_root,
                                                            required_libs,
                                                            use_symlinks=True)
            cmd += ' --symfs %s --kallsyms %s' % (symfs_root, kallsyms)
            for lib in required_libs:
                lib = os.path.join(symfs_root, lib[1:])
                if not os.path.exists(lib):
                    continue
                objdump_path = android_profiling_helper.GetToolchainBinaryPath(
                    lib, 'objdump')
                if objdump_path:
                    cmd += ' --objdump %s' % _NicePath(objdump_path)
                    break

        print 'To view the profile, run:'
        print ' ', cmd
        return self._output_file
    def testCreateSymFs(self):
        # pylint: disable=protected-access
        browser_pid = self._browser._browser_backend.pid
        pids = ([browser_pid] +
                self._browser._platform_backend.GetChildPids(browser_pid))
        libs = _GetLibrariesMappedIntoProcesses(self._device, pids)
        assert libs

        symfs_dir = tempfile.mkdtemp()
        try:
            kallsyms = android_profiling_helper.CreateSymFs(
                self._device, symfs_dir, libs)

            # Check that we have kernel symbols.
            assert os.path.exists(kallsyms)

            is_unstripped = re.compile(r'^/data/app(-lib)?/.*\.so$')
            has_unstripped = False

            # Check that all requested libraries are present.
            for lib in libs:
                has_unstripped = has_unstripped or is_unstripped.match(lib)
                assert os.path.exists(os.path.join(symfs_dir, lib[1:])), \
                    '%s not found in symfs' % lib

            # Make sure we found at least one unstripped library.
            assert has_unstripped
        finally:
            shutil.rmtree(symfs_dir)
Exemple #3
0
    def CollectProfile(self):
        if 'renderer' in self._output_file:
            try:
                self._platform_backend.GetCommandLine(self._pid)
            except exceptions.ProcessGoneException:
                logging.warning('Renderer was swapped out during profiling. '
                                'To collect a full profile rerun with '
                                '"--extra-browser-args=--single-process"')
        subprocess.call(
            ['amplxe-cl', '-command', 'stop', '-r', self._output_file])

        exit_code = self._proc.wait()
        try:
            # 1: amplxe: Error: Cannot find a running process with the specified ID.
            #    Provide a valid PID.
            if exit_code not in (0, 1):
                raise Exception(
                    'amplxe-cl failed with exit code %d. Output:\n%s' %
                    (exit_code, self._GetStdOut()))
        finally:
            self._tmp_output_file.close()

        if exit_code:
            # The renderer process was swapped out. Now that we made sure VTune has
            # stopped, return without further processing the invalid profile.
            return self._output_file

        if self._is_android:
            required_libs = \
                android_profiling_helper.GetRequiredLibrariesForVTuneProfile(
                    self._output_file)

            device = self._browser_backend.device
            symfs_root = os.path.join(os.path.dirname(self._output_file),
                                      'symfs')
            if not os.path.exists(symfs_root):
                os.makedirs(symfs_root)
            android_profiling_helper.CreateSymFs(device,
                                                 symfs_root,
                                                 required_libs,
                                                 use_symlinks=True)
            logging.info('Resolving symbols in profile.')
            subprocess.call([
                'amplxe-cl', '-finalize', '-r', self._output_file,
                '-search-dir', symfs_root
            ])

        print 'To view the profile, run:'
        print '  amplxe-gui %s' % self._output_file

        return self._output_file
Exemple #4
0
    def PullTrace(self):
        symfs_dir = os.path.join(tempfile.gettempdir(),
                                 os.path.expandvars('$USER-perf-symfs'))
        if not os.path.exists(symfs_dir):
            os.makedirs(symfs_dir)
        required_libs = set()

        # Download the recorded perf profile.
        perf_profile = self._perf_instance.PullResult(symfs_dir)
        required_libs = \
            android_profiling_helper.GetRequiredLibrariesForPerfProfile(
                perf_profile)
        if not required_libs:
            logging.warning(
                'No libraries required by perf trace. Most likely there '
                'are no samples in the trace.')

        # Build a symfs with all the necessary libraries.
        kallsyms = android_profiling_helper.CreateSymFs(self._device,
                                                        symfs_dir,
                                                        required_libs,
                                                        use_symlinks=False)
        perfhost_path = binary_manager.FetchPath(
            android_profiling_helper.GetPerfhostName(), 'x86_64', 'linux')

        ui.PrintMessage('\nNote: to view the profile in perf, run:')
        ui.PrintMessage('  ' + self._GetInteractivePerfCommand(
            perfhost_path, perf_profile, symfs_dir, required_libs, kallsyms))

        # Convert the perf profile into JSON.
        perf_script_path = os.path.join(
            os.path.dirname(os.path.abspath(__file__)), 'third_party',
            'perf_to_tracing.py')
        json_file_name = os.path.basename(perf_profile)
        with open(os.devnull, 'w') as dev_null, \
            open(json_file_name, 'w') as json_file:
            cmd = [
                perfhost_path, 'script', '-s', perf_script_path, '-i',
                perf_profile, '--symfs', symfs_dir, '--kallsyms', kallsyms
            ]
            if subprocess.call(cmd, stdout=json_file, stderr=dev_null):
                logging.warning(
                    'Perf data to JSON conversion failed. The result will '
                    'not contain any perf samples. You can still view the '
                    'perf data manually as shown above.')
                return None

        return json_file_name