Skip to content

Commit

Permalink
API to get list of pre optimized systems (#521)
Browse files Browse the repository at this point in the history
Co-authored-by: Michael Graeb <[email protected]>
  • Loading branch information
waahm7 and graebm authored Nov 10, 2023
1 parent 2e4397c commit cc5af86
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 4 deletions.
15 changes: 13 additions & 2 deletions awscrt/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -624,15 +624,26 @@ def is_optimized_for_system():
return _awscrt.s3_is_crt_s3_optimized_for_system()


def get_optimized_platforms():
"""
Returns:
A list[str] of platform identifiers, such as EC2 instance types, for which S3 client is pre-optimized
and have a recommended throughput_target_gbps. You can use `get_recommended_throughput_target_gbps()`
to obtain the recommended throughput_target_gbps for those platforms.
"""
return _awscrt.s3_get_optimized_platforms()


def get_recommended_throughput_target_gbps() -> Optional[float]:
"""
Returns:
Recommended throughput, in gigabits per second, based on detected system configuration.
If the best throughput configuration is unknown, returns None.
Use this as the S3Client's `throughput_target_gbps`.
"""
# Currently the CRT returns 0 if it was unable to make a good guess on configuration. Pre-known configs, have this value set.
# Eventually, the CRT will make a full calculation based on NIC and CPU configuration, but until then handle 0.
# Currently the CRT returns 0 if it was unable to make a good guess on configuration. Pre-known configs,
# have this value set. Eventually, the CRT will make a full calculation based on NIC and CPU configuration,
# but until then handle 0.
max_value = _awscrt.s3_get_recommended_throughput_target_gbps()
if max_value > 0:
return max_value
Expand Down
1 change: 1 addition & 0 deletions source/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -802,6 +802,7 @@ static PyMethodDef s_module_methods[] = {
AWS_PY_METHOD_DEF(s3_get_ec2_instance_type, METH_NOARGS),
AWS_PY_METHOD_DEF(s3_is_crt_s3_optimized_for_system, METH_NOARGS),
AWS_PY_METHOD_DEF(s3_get_recommended_throughput_target_gbps, METH_NOARGS),
AWS_PY_METHOD_DEF(s3_get_optimized_platforms, METH_NOARGS),
AWS_PY_METHOD_DEF(s3_cross_process_lock_new, METH_VARARGS),
AWS_PY_METHOD_DEF(s3_cross_process_lock_acquire, METH_VARARGS),
AWS_PY_METHOD_DEF(s3_cross_process_lock_release, METH_VARARGS),
Expand Down
1 change: 1 addition & 0 deletions source/s3.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
PyObject *aws_py_s3_get_ec2_instance_type(PyObject *self, PyObject *args);
PyObject *aws_py_s3_is_crt_s3_optimized_for_system(PyObject *self, PyObject *args);
PyObject *aws_py_s3_get_recommended_throughput_target_gbps(PyObject *self, PyObject *args);
PyObject *aws_py_s3_get_optimized_platforms(PyObject *self, PyObject *args);

PyObject *aws_py_s3_client_new(PyObject *self, PyObject *args);
PyObject *aws_py_s3_client_make_meta_request(PyObject *self, PyObject *args);
Expand Down
33 changes: 32 additions & 1 deletion source/s3_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,38 @@ PyObject *aws_py_s3_get_recommended_throughput_target_gbps(PyObject *self, PyObj
return PyFloat_FromDouble(platform_info->max_throughput_gbps);
}

PyObject *aws_py_s3_get_optimized_platforms(PyObject *self, PyObject *args) {
(void)self;
(void)args;

bool success = false;
struct aws_array_list platform_list = aws_s3_get_platforms_with_recommended_config();

size_t list_length = aws_array_list_length(&platform_list);

PyObject *py_list = PyList_New(list_length);
if (!py_list) {
goto clean_up;
}

for (size_t i = 0; i < list_length; ++i) {
struct aws_byte_cursor cursor;
if (aws_array_list_get_at(&platform_list, &cursor, i) == AWS_OP_SUCCESS) {
PyObject *platform_str = PyUnicode_FromAwsByteCursor(&cursor);
if (!platform_str) {
Py_DECREF(py_list);
goto clean_up;
}
PyList_SetItem(py_list, i, platform_str); /* Steals a Reference */
}
}
success = true;

clean_up:
aws_array_list_clean_up(&platform_list);
return success ? py_list : NULL;
}

struct cross_process_lock_binding {
struct aws_cross_process_lock *lock;
struct aws_string *name;
Expand Down Expand Up @@ -126,7 +158,6 @@ PyObject *aws_py_s3_cross_process_lock_acquire(PyObject *self, PyObject *args) {

PyObject *aws_py_s3_cross_process_lock_release(PyObject *self, PyObject *args) {
(void)self;

PyObject *lock_capsule; /* O */

if (!PyArg_ParseTuple(args, "O", &lock_capsule)) {
Expand Down
6 changes: 6 additions & 0 deletions test/test_s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
S3ResponseError,
CrossProcessLock,
create_default_s3_signing_config,
get_optimized_platforms,
)
from awscrt.io import (
ClientBootstrap,
Expand Down Expand Up @@ -216,6 +217,11 @@ def test_wait_shutdown(self):
del s3_client
self.assertTrue(shutdown_event.wait(self.timeout))

def test_get_optimized_platforms(self):
platform_list = get_optimized_platforms()
self.assertTrue(len(platform_list) > 0)
self.assertTrue("p4d.24xlarge" in platform_list)


@unittest.skipUnless(os.environ.get('AWS_TEST_S3'), 'set env var to run test: AWS_TEST_S3')
class S3RequestTest(NativeResourceTest):
Expand Down

0 comments on commit cc5af86

Please sign in to comment.