Skip to content

chore: performance tests for ESDK-python #680

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

Merged
merged 33 commits into from
Jun 5, 2024
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
c6f4065
chore: performance tests for ESDK-python
RitvikKapila May 17, 2024
64fa02d
Added README
RitvikKapila May 17, 2024
5ab94c6
return plaintext and ciphertext for ease of verification
RitvikKapila May 17, 2024
cb3b6f8
updated readme, pylintrc, plaintext sizes
RitvikKapila May 21, 2024
f25a390
update
RitvikKapila May 22, 2024
6573a46
chore(aws_kms): AWS KMS keyring / key-provider test
RitvikKapila May 23, 2024
8bfb71e
fix
RitvikKapila May 24, 2024
e62cbc2
added performance tests to CI
RitvikKapila May 24, 2024
e5f7221
adding files for aes and rsa keyring / mkp
RitvikKapila May 24, 2024
3799f18
adding pytest tests
RitvikKapila May 24, 2024
51adb33
updating tox file
RitvikKapila May 25, 2024
4b3b68a
fix
RitvikKapila May 25, 2024
ebd419a
fix tox
RitvikKapila May 28, 2024
bcdc43a
fix pylint tox
RitvikKapila May 28, 2024
e27f149
add perf test to codebuild
RitvikKapila May 28, 2024
979194b
added perf tests to buildspec.yml
RitvikKapila May 28, 2024
5299290
fix
RitvikKapila May 28, 2024
a67e80d
fix tests in ci tox
RitvikKapila May 29, 2024
0aeafa9
fix
RitvikKapila May 29, 2024
ade03c6
fix codebuild
RitvikKapila May 29, 2024
1d89d08
tox remove 312 perf tests
RitvikKapila May 29, 2024
706f915
debug
RitvikKapila May 29, 2024
9dbcb4d
fix kms keyring test
RitvikKapila May 29, 2024
fea2075
print
RitvikKapila May 29, 2024
d2b739f
print correct
RitvikKapila May 29, 2024
bd5505c
add results folder to github
RitvikKapila May 29, 2024
dc2daea
fix all except kms keyring / mkp tests
RitvikKapila May 29, 2024
457d20d
fix
RitvikKapila May 30, 2024
8fba0cc
updated README; refactoring
RitvikKapila Jun 3, 2024
71f7c0a
removed requirements_mpl.txt
RitvikKapila Jun 3, 2024
8f76e56
add requirements_mpl.txt
RitvikKapila Jun 3, 2024
f325071
add default testing n_iters for automated testing results
RitvikKapila Jun 3, 2024
4660344
refactoring and fixes
RitvikKapila Jun 5, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,12 @@ __pycache__
.pytest_cache
# Ignore key materials generated by examples or tests
test_keyrings/
# Ignore results of performance test
performance_tests/results/*
# To track the results folder, keep the __init__.py file
!performance_tests/results/__init__.py
# Ignore the memory profile logs
mprofile_*

# PyCharm
.idea/
Expand Down
8 changes: 8 additions & 0 deletions buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,10 @@ batch:
buildspec: codebuild/py311/integ_mpl.yml
env:
image: aws/codebuild/standard:7.0
- identifier: py311_performance_tests_mpl
buildspec: codebuild/py311/performance_tests_mpl.yml
env:
image: aws/codebuild/standard:7.0
- identifier: py311_examples
buildspec: codebuild/py311/examples.yml
env:
Expand Down Expand Up @@ -250,6 +254,10 @@ batch:
buildspec: codebuild/py312/integ_mpl.yml
env:
image: aws/codebuild/standard:7.0
- identifier: py312_performance_tests_mpl
buildspec: codebuild/py312/performance_tests_mpl.yml
env:
image: aws/codebuild/standard:7.0
- identifier: py312_examples
buildspec: codebuild/py312/examples.yml
env:
Expand Down
38 changes: 38 additions & 0 deletions codebuild/py311/performance_tests_mpl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Runs the performance tests for the MPL in an environment with the MPL installed
version: 0.2

env:
variables:
# No TOXENV. This runs multiple environments.
REGION: "us-west-2"
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >-
arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >-
arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >-
arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7

phases:
install:
runtime-versions:
python: 3.11
build:
commands:
- cd /root/.pyenv/plugins/python-build/../.. && git pull && cd -
- pyenv install --skip-existing 3.11.0
- pyenv local 3.11.0
- pip install --upgrade pip
- pip install setuptools
- pip install "tox < 4.0"
# Assume special role to access keystore
- TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl")
- export TMP_ROLE
- export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId')
- export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey')
- export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken')
- aws sts get-caller-identity
# Run MPL-specific tests with special role
- cd performance_tests/
- tox -e py311-performance_tests-mpl
38 changes: 38 additions & 0 deletions codebuild/py312/performance_tests_mpl.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Runs the performance tests for the MPL in an environment with the MPL installed
version: 0.2

env:
variables:
# No TOXENV. This runs multiple environments.
REGION: "us-west-2"
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID: >-
arn:aws:kms:us-west-2:658956600833:key/b3537ef1-d8dc-4780-9f5a-55776cbb2f7f
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_KEY_ID_2: >-
arn:aws:kms:eu-central-1:658956600833:key/75414c93-5285-4b57-99c9-30c1cf0a22c2
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_1: >-
arn:aws:kms:us-west-2:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7
AWS_ENCRYPTION_SDK_PYTHON_INTEGRATION_TEST_AWS_KMS_MRK_KEY_ID_2: >-
arn:aws:kms:us-east-1:658956600833:key/mrk-80bd8ecdcd4342aebd84b7dc9da498a7

phases:
install:
runtime-versions:
python: 3.12
build:
commands:
- cd /root/.pyenv/plugins/python-build/../.. && git pull && cd -
- pyenv install --skip-existing 3.12.0
- pyenv local 3.12.0
- pip install --upgrade pip
- pip install setuptools
- pip install "tox < 4.0"
# Assume special role to access keystore
- TMP_ROLE=$(aws sts assume-role --role-arn "arn:aws:iam::370957321024:role/GitHub-CI-Public-ESDK-Python-Role-us-west-2" --role-session-name "CB-Py312ExamplesMpl")
- export TMP_ROLE
- export AWS_ACCESS_KEY_ID=$(echo "${TMP_ROLE}" | jq -r '.Credentials.AccessKeyId')
- export AWS_SECRET_ACCESS_KEY=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SecretAccessKey')
- export AWS_SESSION_TOKEN=$(echo "${TMP_ROLE}" | jq -r '.Credentials.SessionToken')
- aws sts get-caller-identity
# Run MPL-specific tests with special role
- cd performance_tests/
- tox -e py312-performance_tests-mpl
135 changes: 135 additions & 0 deletions performance_tests/README.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
# aws-encryption-sdk performance tests

## License

This project is licensed under the Apache-2.0 License.

## Overview

This library tests the following keyrings / master key-providers:

1. KMS Keyring / KMS Master Key Provider
2. Raw AES Keyring / AES Master Key Provider
3. Raw RSA Keyring / RSA Master Key Provider
4. Hierarchy Keyring
5. Caching CMM

For each test on the above keyrings / master key-providers, this package measures the execution time and memory consumption.

For each keyring / master key-provider, the execution time and memory consumption time is measured for three operations:
1. Create keyring / master key-provider
2. Encrypt
3. Decrypt

The usage of the performance tests is demonstrated through an [AWS KMS Keyring](https://docs.aws.amazon.com/encryption-sdk/latest/developer-guide/use-kms-keyring.html). However, the procedure is the same for any keyring / master key-provider, with slight change in the input arguments.

The results for the performance test will be available in the results folder in the performance_tests directory.

## Usage: Execution Time

### Create Keyring
To run the performance test for execution time, please use the following commands in the performance_tests directory
```
python test/keyrings/test_aws_kms_keyring.py create
```

#### Optional Arguments
* kms_key_id: The KMS key ID you want to use
* n_iters: Number of iterations you want to run the test for. For instance, if n_iters = 100, this performance test script will run the create_keyring method 100 times and report the execution time of each of the calls.
* output_file: The output file for execution times for each function call, default='kms_keyring_create' in the results folder

#### Consolidate Results

In order to find the minimum, maximum and average times from the n_iters runs, please use the following script from the performance_tests directory:
```
python consolidate_results.py results/kms_keyring_create.csv
```

### Encrypt
To run the performance test for execution time, please use the following commands in the performance_tests directory
```
python test/keyrings/test_aws_kms_keyring.py encrypt
```

Here, you will receive a prompt on the terminal to specify the plaintext file you want to encrypt. Some example plaintext data files are present in the 'test/resources' directory.

Alternatively, if you want to provide the arguments as flags without using the interactive CLI, you can run the command in the following manner:

```
python test/keyrings/test_aws_kms_keyring.py encrypt --plaintext_data_filename test/resources/plaintext-data-medium.dat
```

You can choose to use any other plaintext file as well.

#### Arguments
* plaintext_data_filename: Filename containing plaintext data you want to encrypt

#### Optional Arguments
* kms_key_id: The KMS key ID you want to use to encrypt the data
* n_iters: Number of iterations you want to run the test for. For instance, if n_iters = 100, this performance test script will run the encrypt method 100 times and report the execution time of each of the calls.
* output_file: The output file for execution times for each function call, default='kms_keyring_encrypt'

#### Consolidate Results

In order to find the minimum, maximum and average times from the n_iters runs, please use the following script from the performance_tests directory:
```
python consolidate_results.py results/kms_keyring_encrypt.csv
```

### Decrypt
To run the performance test for execution time, please use the following commands in the performance_tests directory
```
python test/keyrings/test_aws_kms_keyring.py decrypt
```

Here, you will receive a prompt on the terminal to specify the ciphertext file you want to decrypt. Some example ciphertext data files are present in the 'test/resources' directory.

Alternatively, if you want to provide the arguments as flags without using the interactive CLI, you can run the command in the following manner:

```
python test/keyrings/test_aws_kms_keyring.py decrypt --ciphertext_data_filename test/resources/ciphertext-data-medium.ct
```

You can choose to use any other ciphertext file as well.

#### Arguments
* ciphertext_data_filename: Filename containing ciphertext data you want to decrypt

#### Optional Arguments
* kms_key_id: The KMS key ID you want to use to decrypt the data
* n_iters: Number of iterations you want to run the test for. For instance, if n_iters = 100, this performance test script will run the decrypt method 100 times and report the execution time of each of the calls.
* output_file: The output file for execution times for each function call, default='kms_keyring_decrypt'

#### Consolidate Results

In order to find the minimum, maximum and average times from the n_iters runs, please use the following script from the performance_tests directory:
```
python consolidate_results.py results/kms_keyring_decrypt.csv
```

## Usage: Memory Consumption
To get the memory consumption, simply use 'mprof run' instead of 'python' in the previously mentioned commands.

For example, if you want to calculate the memory consumption of the encrypt function of a AWS KMS Keyring, simply write:
```
mprof run test/keyrings/test_aws_kms_keyring.py encrypt --plaintext_data_filename test/resources/plaintext-data-medium.dat
```

This should generate an mprofile log file in your current directory. To plot the memory consumption with time, please use the following command from the same directory
```
mprof plot
```

This 'mprof plot' command will plot the most recent mprofile log file.

## Usage: Performance Graph
To generate a performance graph, please use the following command to generate the pstats log file by specifying the output pstats file path. Here, 'results/kms_keyring_create.pstats' is set as the default output file.

```
python -m cProfile -o results/kms_keyring_create.pstats test/keyrings/test_aws_kms_keyring.py create
```

After generating the pstats file, please run the following command to generate the performance graph. The output performance graph will be a .png file that you specify. Here, 'results/kms_keyring_create.png' is set as the default output file.
```
gprof2dot -f pstats results/kms_keyring_create.pstats | dot -Tpng -o results/kms_keyring_create.png && eog results/kms_keyring_create.png
```
3 changes: 3 additions & 0 deletions performance_tests/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Stub module indicator to make linter configuration simpler."""
48 changes: 48 additions & 0 deletions performance_tests/consolidate_results.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Script for consolidating results for execution times"""

import argparse
import csv

import numpy as np


def calculate_statistics(_csv_file):
"""Calculate average, trimmed average, minimum, maximum and p99 statistics for execution times in a CSV file."""
with open(_csv_file, 'r', encoding='utf-8') as file:
reader = csv.reader(file)
data = [float(row[0]) for row in reader]

# Calculate statistics
if data:
data = np.sort(data)
_total_entries = len(data)
_average = np.mean(data)
_trimmed_average_99_bottom = np.mean(data[0:int(0.99 * len(data))])
_minimum = min(data)
_maximum = max(data)
_perc_99 = np.percentile(data, 99)
return _total_entries, _average, _trimmed_average_99_bottom, _minimum, _maximum, _perc_99

return None


if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('csv_file',
help='csv file containing the outputs of execution times for n_iter iterations')
args = parser.parse_args()

statistics = calculate_statistics(args.csv_file)
if statistics:
total_entries, average, trimmend_average_99_bottom, minimum, maximum, perc_99 = statistics
print("CSV File:", args.csv_file)
print("Total Entries:", total_entries)
print("Average:", average)
print("Bottom 99th percentile trimmed average:", trimmend_average_99_bottom)
print("Minimum:", minimum)
print("Maximum:", maximum)
print("99th percentile:", perc_99)
else:
print("No data found in the CSV file.")
45 changes: 45 additions & 0 deletions performance_tests/pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
[MESSAGE CONTROL]
# Disabling messages that either we don't care about we intentionally break.
disable =
import-error, # ignore mpl import errors
invalid-name, # we prefer long, descriptive, names for examples
bad-continuation, # we let black handle this
ungrouped-imports, # we let isort handle this
no-member, # breaks with attrs
no-self-use, # interesting to keep in mind for later refactoring, but not blocking
useless-object-inheritance, # we need to support Python 2, so no, not useless
duplicate-code, # some examples may be similar
too-few-public-methods, # does not allow value stores
too-many-locals, # examples may sometimes have more locals defined for clarity than would be appropriate in code
no-else-return, # we omit this on purpose for brevity where it would add no value
attribute-defined-outside-init, # breaks with attrs_post_init
abstract-method, # throws false positives on io.BaseIO grandchildren
redefined-outer-name, # we do this on purpose in multiple places
consider-using-f-string # disable until 2022-05-05; 6 months after 3.5 deprecation

[BASIC]
# Allow function names up to 50 characters
function-rgx = [a-z_][a-z0-9_]{2,50}$
# Allow method names up to 50 characters
method-rgx = [a-z_][a-z0-9_]{2,50}$
# Allow class attribute names up to 50 characters
# Whitelist class attribute names: iv
class-attribute-rgx = (([A-Za-z_][A-Za-z0-9_]{2,50}|(__.*__))$)|(^iv$)
# Whitelist attribute names: iv
attr-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)
# Whitelist argument names: iv, b
argument-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$)
# Whitelist variable names: iv, b, _b, x, y, r, s
variable-rgx = ([a-z_][a-z0-9_]{2,30}$)|(^iv$)|(^b$)|(^_b$)|(^x$)|(^y$)|(^r$)|(^s$)

[VARIABLES]
additional-builtins = raw_input

[DESIGN]
max-args = 10

[FORMAT]
max-line-length = 120

[REPORTS]
msg-template = {path}:{line}: [{msg_id}({symbol}), {obj}] {msg}
5 changes: 5 additions & 0 deletions performance_tests/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
attrs >= 17.4.0
aws-encryption-sdk>=2.3.0
pytest>=3.3.1
tqdm
click
1 change: 1 addition & 0 deletions performance_tests/requirements_mpl.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
aws-cryptographic-material-providers @ git+https://github.com/aws/aws-cryptographic-material-providers-library.git@lucmcdon/python-mpl#subdirectory=AwsCryptographicMaterialProviders/runtimes/python
3 changes: 3 additions & 0 deletions performance_tests/results/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# Copyright Amazon.com Inc. or its affiliates. All Rights Reserved.
# SPDX-License-Identifier: Apache-2.0
"""Stub module indicator to make linter configuration simpler."""
Loading
Loading