Profiling Python applications

This page describes how to modify your Python application to capture profiling data and have that data sent to your Google Cloud Platform (GCP) project. For general information about profiling, see Profiling concepts.

Profile types for Python:

  • CPU time
  • Wall time (main thread, requires Python 3.6 or higher)

Supported Python language versions:

  • Python 3.2 or higher.

Supported operating systems:

  • Linux versions whose standard C library is implemented with glibc.

Supported environments:

Enabling the Profiler API

Before you use the profiling agent, ensure that the underlying Profiler API is enabled. You can check the status of the API and enable it if necessary by using either the Cloud SDK gcloud command-line tool or the Cloud Console:

Cloud SDK

  1. If you have not already installed the Cloud SDK on your workstation, see Google Cloud SDK.

  2. Run the following command:

    gcloud services enable cloudprofiler.googleapis.com
    

For more information, see gcloud services.

Cloud Console

  1. Go to the APIs & Services dashboard:

    Go to APIs & services

  2. Select the project you will use to access the API.

  3. Click the Add APIs and Services button.

    Add APIs and Services

  4. Search for Profiler API.

  5. In the search results, select Stackdriver Profiler API.

  6. If API enabled is displayed, then the API is already enabled. If not, click the Enable button.

Using Stackdriver Profiler

For best practices using Python, go to Setting up a Python development environment.

Compute Engine

For Compute Engine, do the following:

  1. Install the C/C++ compiler and development tools:

    sudo apt-get install -y build-essential
    
  2. Install pip:

    sudo apt-get install -y python3-pip
    
  3. Install the Profiler package:

    pip3 install google-cloud-profiler
    
  4. Import the googlecloudprofiler package and call the googlecloudprofiler.start function as early as possible in your initialization code:

    import googlecloudprofiler
    
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service='hello-profiler',
                service_version='1.0.1',
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    You must specify the service parameter in your start function. To filter by the application version in the Profiler interface, specify the service_version parameter. For troubleshooting and exception information, see Troubleshooting.

GKE

For GKE, do the following:

  1. Modify your Dockerfile to install the Profiler package:

    FROM python:3
    ...
    RUN apt-get update && apt-get install -y build-essential python3-pip
    RUN pip3 install google-cloud-profiler
    
  2. Import the googlecloudprofiler package and call the googlecloudprofiler.start function as early as possible in your initialization code:

    import googlecloudprofiler
    
    
    def main():
        # Profiler initialization. It starts a daemon thread which continuously
        # collects and uploads profiles. Best done as early as possible.
        try:
            googlecloudprofiler.start(
                service='hello-profiler',
                service_version='1.0.1',
                # verbose is the logging level. 0-error, 1-warning, 2-info,
                # 3-debug. It defaults to 0 (error) if not set.
                verbose=3,
                # project_id must be set if not running on GCP.
                # project_id='my-project-id',
            )
        except (ValueError, NotImplementedError) as exc:
            print(exc)  # Handle errors here

    You must specify the service parameter in your start function. To filter by the application version in the Profiler interface, specify the service_version parameter. For troubleshooting and exception information, see Troubleshooting.

flexible environment

For App Engine flexible environment, do the following:

  1. Add google-cloud-profiler to your requirements.txt file.

  2. Import the googlecloudprofiler package and call the googlecloudprofiler.start function as early as possible in your initialization code:

    import googlecloudprofiler
    
    # Profiler initialization. It starts a daemon thread which continuously
    # collects and uploads profiles. Best done as early as possible.
    try:
        # service and service_version can be automatically inferred when
        # running on App Engine. project_id must be set if not running
        # on GCP.
        googlecloudprofiler.start(verbose=3)
    except (ValueError, NotImplementedError) as exc:
        print(exc)  # Handle errors here
    

For App Engine, the service and service_version are derived from your operating environment. For troubleshooting and exception information, see Troubleshooting.

standard environment

For App Engine standard environment, which requires that you use the Python 3 runtime environment, do the following:

  1. Add google-cloud-profiler to your requirements.txt file.

  2. Import the googlecloudprofiler package and call the googlecloudprofiler.start function as early as possible in your initialization code:

    import googlecloudprofiler
    
    # Profiler initialization. It starts a daemon thread which continuously
    # collects and uploads profiles. Best done as early as possible.
    try:
        # service and service_version can be automatically inferred when
        # running on App Engine. project_id must be set if not running
        # on GCP.
        googlecloudprofiler.start(verbose=3)
    except (ValueError, NotImplementedError) as exc:
        print(exc)  # Handle errors here
    

For App Engine, the service and service_version are derived from your operating environment. For troubleshooting and exception information, see Troubleshooting.

start function

The googlecloudprofiler.start function creates a daemon thread which continuously collects and uploads profiles. You should call start one time, and as early as possible in your application.

Parameter Description
service1 (Required) The name for the service being profiled. For restrictions on the service name, see Service name and version arguments.
service_version1 (Optional) The version of the service being profiled. For restrictions on the service version, see Service name and version arguments.
verbose (Optional) The logging level. For details on the logging levels, see Agent logging.

Default value is 0 (Error).
project_id2 (Optional) Your GCP project ID.
disable_cpu_profiling (Optional) To disable CPU time profiling, set disable_cpu_profiling=True.

This parameter is supported only for Python version 3.2 and higher. For all other Python versions, CPU time profiling isn't supported and this parameter is ignored.

Default value is False.
disable_wall_profiling (Optional) To disable Wall profiling, set disable_wall_profiling=True.

This parameter is supported for Python 2, and for Python 3.6 and higher. For all other Python versions, Wall profiling isn't supported and this parameter is ignored.

For restrictions on the start function when Wall profiling is enabled, see Limitations.

Default value is False.

1 For only Compute Engine and GKE. For App Engine, the value is derived from the environment.
2 For GCP, the value is derived from the environment. For non-GCP environments, you must provide a value. For information, see Profiling applications running outside Google Cloud Platform.

Analyzing data

After Profiler has collected data, you can view and analyze this data using the Profiler interface. To get started using this interface, see Opening the Profiler interface.

Service name and version arguments

When you load the Profiler agent, you specify a service-name argument and an optional service-version argument to configure it.

The service name lets Profiler collect profiling data for all replicas of that service. The profiler service ensures a collection rate of one profile per minute, on average, for each service name across each combination service versions and zones.

For example, if you have a service with two versions running across replicas in three zones, the profiler will create an average of 6 profiles per minute for that service.

If you use different service names for your replicas, then your service will be profiled more often than necessary, with a correspondingly higher overhead.

When selecting a service name:

  • Choose a name that clearly represents the service in your application architecture. The choice of service name is less important if you only run a single service or application. It is more important if your application runs as a set of micro-services, for example.

  • Make sure to not use any process-specific values, like a process ID, in the service-name string.

  • The service-name string must match this regular expression:

    ^[a-z]([-a-z0-9_.]{0,253}[a-z0-9])?$

A good guideline is to use a static string like imageproc-service as the service name.

The service version is optional. If you specify the service version, Profiler can aggregate profiling information from multiple instances and display it correctly. It can be used to mark different versions of your services as they get deployed. The Profiler UI lets you filter the data by service version; this way, you can compare the performance of older and newer versions of the code.

The value of the service-version argument is a free-form string, but values for this argument typically look like version numbers, for example, 1.0.0 or 2.1.2.

Agent logging

By default, the profiling agent logs messages with a severity level of error. To configure the agent to log messages with lower severity levels, specify the verbose parameter when starting the agent. There are four supported values for verbose:

  • 0 : Error
  • 1 : Warning
  • 2 : Informational
  • 3 : Debug

If you set the verbose parameter to 1 in your call to start, then messages with a severity level of Warning or Error are logged, while Informational and Debug messages are ignored.

To log all messages, set verbose to 3 when starting the agent:

googlecloudprofiler.start(service='service_name', verbose=3)

Troubleshooting

This section lists limitations, exceptions, and known issues.

Limitations

Profile type Restrictions and limitations
CPU time
  • Supported for Python 3.2 and higher.
Wall time
  • Supported for Python 3.6 and higher.
  • Not available for Python 3.0 to 3.5.
  • Available, but not supported, for Python 2.
  • Main-thread profiling only.
  • The profile start function must be called from the main thread.
  • The Profiler signal handler executes only on the main thread. If the main thread cannot execute, no profiling data is captured.

Exceptions

Error Cause Solution
NotImplementedError thrown during start Application executed in a non-Linux environment.
  • Execute your application in a Linux environment.
ValueError thrown during start The start function arguments are invalid, necessary information can't be determined from the environment variables and arguments, or profiling if both CPU time profiling and Wall time profiling are disabled.
  • Ensure the service name and version meet the requirements defined in Service name and version arguments.
  • If Wall profiling is enabled, make sure start is called from the main thread.
  • Ensure that you are using a supported version of Python and that CPU time or Wall time profiling is enabled. For more information, see start function.
  • Check that you have specified the project_id parameter to start if you are running outside of GCP. For more information, see start function.

Known issues

Behavior Cause Solution
System calls fail with Python 3.4 or earlier applications, when profiling CPU time or Wall time. Python, version 3.4 and earlier, fails system calls interrupted by a signal with EINTR. Your application must handle this scenario. For more detailed information, see PEP 475.
  • Use Python 3.5 or later.
  • Have the application handle the EINTR response code.
Your Python 3.5 or earlier application isn't responding to signals when Wall profiling is enabled. Python 3.5 and earlier contains a race condition in its signal handling. The effect is that applications stop responding to signals, including the kill signal Ctrl-C.
  • Use Python 3.6 or later.

What's next

To learn about the Profiler graph and controls, go to Using the Stackdriver Profiler Interface. For advanced information, go to the following:

¿Te ha resultado útil esta página? Enviar comentarios:

Enviar comentarios sobre...

Stackdriver Profiler
Si necesitas ayuda, visita nuestra página de asistencia.