-
Notifications
You must be signed in to change notification settings - Fork 68
Refactor py-spy & pyperf to separate ProfilerInterface. #805
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from 4 commits
53bec68
5d3b189
c11b6a1
36f81aa
e0a79a7
43f6628
0536112
918f4e6
b3c7e0c
3a7b9af
4438b49
002ec0c
6a4b9ae
b41f5ec
3a8bbc4
eb44786
94a8010
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,18 @@ | ||
# NOTE: Make sure to import any new process profilers to load it | ||
from gprofiler.platform import is_linux | ||
from gprofiler.profilers.dotnet import DotnetProfiler | ||
from gprofiler.profilers.python import PythonProfiler | ||
from gprofiler.profilers.python import PySpyProfiler | ||
|
||
if is_linux(): | ||
from gprofiler.profilers.java import JavaProfiler | ||
from gprofiler.profilers.perf import SystemProfiler | ||
from gprofiler.profilers.php import PHPSpyProfiler | ||
from gprofiler.profilers.python_ebpf import PythonEbpfProfiler | ||
from gprofiler.profilers.ruby import RbSpyProfiler | ||
|
||
__all__ = ["PythonProfiler", "DotnetProfiler"] | ||
__all__ = ["PySpyProfiler", "DotnetProfiler"] | ||
|
||
if is_linux(): | ||
__all__ += ["JavaProfiler", "PHPSpyProfiler", "RbSpyProfiler", "SystemProfiler"] | ||
__all__ += ["JavaProfiler", "PHPSpyProfiler", "RbSpyProfiler", "SystemProfiler", "PythonEbpfProfiler"] | ||
|
||
del is_linux |
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -3,10 +3,14 @@ | |||||
|
||||||
from gprofiler.log import get_logger_adapter | ||||||
from gprofiler.metadata.system_metadata import get_arch | ||||||
from gprofiler.platform import is_windows | ||||||
from gprofiler.profilers.perf import SystemProfiler | ||||||
from gprofiler.profilers.profiler_base import NoopProfiler | ||||||
from gprofiler.profilers.registry import get_profilers_registry | ||||||
from gprofiler.profilers.registry import ( | ||||||
ProfilerConfig, | ||||||
get_profiler_arguments, | ||||||
get_profilers_registry, | ||||||
get_sorted_profilers, | ||||||
) | ||||||
|
||||||
if TYPE_CHECKING: | ||||||
from gprofiler.gprofiler_types import UserArgs | ||||||
|
@@ -24,44 +28,67 @@ def get_profilers( | |||||
process_profilers_instances: List["ProcessProfilerBase"] = [] | ||||||
system_profiler: Union["SystemProfiler", "NoopProfiler"] = NoopProfiler() | ||||||
|
||||||
if profiling_mode != "none": | ||||||
arch = get_arch() | ||||||
for profiler_name, profiler_config in get_profilers_registry().items(): | ||||||
lower_profiler_name = profiler_name.lower() | ||||||
profiler_mode = user_args.get(f"{lower_profiler_name}_mode") | ||||||
if profiler_mode in ("none", "disabled"): | ||||||
continue | ||||||
|
||||||
supported_archs = ( | ||||||
profiler_config.supported_windows_archs if is_windows() else profiler_config.supported_archs | ||||||
) | ||||||
if arch not in supported_archs: | ||||||
if profiling_mode == "none": | ||||||
return system_profiler, process_profilers_instances | ||||||
arch = get_arch() | ||||||
for runtime in get_profilers_registry(): | ||||||
runtime_args_prefix = runtime.lower().replace("-", "_") | ||||||
runtime_mode = user_args.get(f"{runtime_args_prefix}_mode") | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not needed now. Was used when exploring different approaches. |
||||||
if runtime_mode in ProfilerConfig.DISABLED_MODES: | ||||||
continue | ||||||
# select configs supporting requested runtime_mode or all configs in order of preference | ||||||
requested_configs: List[ProfilerConfig] = get_sorted_profilers(runtime) | ||||||
if runtime_mode != ProfilerConfig.ENABLED_MODE: | ||||||
requested_configs = [c for c in requested_configs if runtime_mode in c.get_active_modes()] | ||||||
# select profilers that support this architecture and profiling mode | ||||||
selected_configs: List[ProfilerConfig] = [] | ||||||
for config in requested_configs: | ||||||
profiler_name = config.profiler_name | ||||||
if arch not in config.get_supported_archs() and len(requested_configs) == 1: | ||||||
logger.warning(f"Disabling {profiler_name} because it doesn't support this architecture ({arch})") | ||||||
continue | ||||||
|
||||||
Jongy marked this conversation as resolved.
Show resolved
Hide resolved
|
||||||
if profiling_mode not in profiler_config.supported_profiling_modes: | ||||||
if profiling_mode not in config.supported_profiling_modes: | ||||||
logger.warning( | ||||||
f"Disabling {profiler_name} because it doesn't support profiling mode {profiling_mode!r}" | ||||||
) | ||||||
continue | ||||||
|
||||||
selected_configs.append(config) | ||||||
if not selected_configs: | ||||||
logger.warning(f"Disabling {runtime} profiling because no profilers were selected") | ||||||
continue | ||||||
# create instances of selected profilers one by one, select first that is ready | ||||||
ready_profiler = None | ||||||
runtime_arg_names = [arg.dest for config in get_profilers_registry()[runtime] for arg in config.profiler_args] | ||||||
for profiler_config in selected_configs: | ||||||
profiler_name = profiler_config.profiler_name | ||||||
profiler_kwargs = profiler_init_kwargs.copy() | ||||||
profiler_arg_names = [arg.dest for arg in get_profiler_arguments(runtime, profiler_name)] | ||||||
for key, value in user_args.items(): | ||||||
if key.startswith(lower_profiler_name) or key in COMMON_PROFILER_ARGUMENT_NAMES: | ||||||
if ( | ||||||
key in profiler_arg_names | ||||||
or key in COMMON_PROFILER_ARGUMENT_NAMES | ||||||
or key.startswith(runtime_args_prefix) | ||||||
and key not in runtime_arg_names | ||||||
): | ||||||
profiler_kwargs[key] = value | ||||||
try: | ||||||
profiler_instance = profiler_config.profiler_class(**profiler_kwargs) | ||||||
if profiler_instance.check_readiness(): | ||||||
ready_profiler = profiler_instance | ||||||
break | ||||||
except Exception: | ||||||
logger.critical( | ||||||
f"Couldn't create the {profiler_name} profiler, not continuing." | ||||||
f" Run with --no-{profiler_name.lower()} to disable this profiler", | ||||||
exc_info=True, | ||||||
) | ||||||
sys.exit(1) | ||||||
else: | ||||||
if isinstance(profiler_instance, SystemProfiler): | ||||||
system_profiler = profiler_instance | ||||||
else: | ||||||
process_profilers_instances.append(profiler_instance) | ||||||
|
||||||
if len(requested_configs) == 1: | ||||||
logger.critical( | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a new fatal error. In which situations can it happen? When I force There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, that's the case. Now the test is wrapped in |
||||||
f"Couldn't create the {profiler_name} profiler for runtime {runtime}, not continuing." | ||||||
f" Request different profiler for runtime with --{runtime_args_prefix}-mode, or disable" | ||||||
f" {runtime} profiling with --no-{runtime_args_prefix} to disable this profiler", | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
I prefer this way of expressing it ( There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Okay. |
||||||
exc_info=True, | ||||||
) | ||||||
sys.exit(1) | ||||||
if isinstance(ready_profiler, SystemProfiler): | ||||||
system_profiler = ready_profiler | ||||||
elif ready_profiler is not None: | ||||||
process_profilers_instances.append(ready_profiler) | ||||||
else: | ||||||
logger.warning(f"Disabling {runtime} profiling because no profilers were ready") | ||||||
return system_profiler, process_profilers_instances |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add a blank line between these 2 lines for clarity
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
👍