File: benchmark-upload

package info (click to toggle)
python-s3transfer 0.11.4-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 1,428 kB
  • sloc: python: 15,560; makefile: 9
file content (144 lines) | stat: -rwxr-xr-x 4,104 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
#!/usr/bin/env python
"""
Benchmark the uploading of a file using s3transfer. You can also chose how
type of file that is uploaded (i.e. filename, seekable, nonseekable).

Usage
=====

NOTE: Make sure you run ``pip install -r requirements-dev.txt`` before running.

To benchmark with using a temporary file that is generated for you::

    ./benchmark-upload --file-size 10MB --file-type filename \\
        --s3-bucket mybucket

To benchmark with your own local file::

    ./benchmark-upload --source-file myfile --file-type filename \\
        --s3-bucket mybucket

"""

import argparse
import os
import shutil
import subprocess
import tempfile

from botocore.session import get_session

TEMP_FILE = 'temp'
TEMP_KEY = 'temp'
KB = 1024
SIZE_SUFFIX = {
    'kb': 1024,
    'mb': 1024**2,
    'gb': 1024**3,
    'tb': 1024**4,
    'kib': 1024,
    'mib': 1024**2,
    'gib': 1024**3,
    'tib': 1024**4,
}


def human_readable_to_bytes(value):
    """Converts a human readable size to bytes.
    :param value: A string such as "10MB".  If a suffix is not included,
        then the value is assumed to be an integer representing the size
        in bytes.
    :returns: The converted value in bytes as an integer
    """
    value = value.lower()
    if value[-2:] == 'ib':
        # Assume IEC suffix.
        suffix = value[-3:].lower()
    else:
        suffix = value[-2:].lower()
    has_size_identifier = len(value) >= 2 and suffix in SIZE_SUFFIX
    if not has_size_identifier:
        try:
            return int(value)
        except ValueError:
            raise ValueError(f"Invalid size value: {value}")
    else:
        multiplier = SIZE_SUFFIX[suffix]
        return int(value[: -len(suffix)]) * multiplier


def create_file(filename, file_size):
    with open(filename, 'wb') as f:
        for i in range(0, file_size, KB):
            f.write(b'a' * i)


def benchmark_upload(args):
    source_file = args.source_file
    session = get_session()
    client = session.create_client('s3')
    tempdir = None
    try:
        # If a source file was not specified, then create a temporary file of
        # that size for the user.
        if not source_file:
            tempdir = tempfile.mkdtemp()
            source_file = os.path.join(tempdir, TEMP_FILE)
            create_file(source_file, args.file_size)

        upload_file_script = (
            f'./upload-file --file-name {source_file} --file-type {args.file_type} --s3-bucket {args.s3_bucket} '
            f'--s3-key {TEMP_KEY}'
        )
        benchmark_args = ['./benchmark', upload_file_script]
        if args.output_file:
            benchmark_args.extend(['--output-file', args.output_file])
        subprocess.check_call(benchmark_args)
    finally:
        if tempdir:
            shutil.rmtree(tempdir)
    client.delete_object(Bucket=args.s3_bucket, Key=TEMP_KEY)


def main():
    parser = argparse.ArgumentParser(usage=__doc__)
    source_file_group = parser.add_mutually_exclusive_group(required=True)
    source_file_group.add_argument(
        '--source-file',
        help=(
            'The local file to upload. Note this is optional. You can also '
            'use --file-size which will create a temporary file for you.'
        ),
    )
    source_file_group.add_argument(
        '--file-size',
        type=human_readable_to_bytes,
        help=(
            'The size of the temporary file to create. You can also specify '
            'your own file with --source-file'
        ),
    )
    parser.add_argument(
        '--file-type',
        choices=['filename', 'seekable', 'nonseekable'],
        required=True,
        help='The way to represent the file when uploading',
    )
    parser.add_argument(
        '--s3-bucket',
        required=True,
        help='The S3 bucket to upload the file to',
    )
    parser.add_argument(
        '--output-file',
        help=(
            'The file to output the data collected to. The default '
            'location performance.csv'
        ),
    )
    args = parser.parse_args()
    benchmark_upload(args)


if __name__ == '__main__':
    main()