def optimal_part_info(length, part_size):
    """
    Calculate optimal part size for multipart uploads.

    :param length: Input length to calculate part size of.
    :return: Optimal part size.
    """
    # object size is '-1' set it to 5TiB.
    if length == -1:
        length = MAX_MULTIPART_OBJECT_SIZE
    if length > MAX_MULTIPART_OBJECT_SIZE:
        raise InvalidArgumentError('Input content size is bigger '
                                   ' than allowed maximum of 5TiB.')

    # honor user configured size
    if part_size != MIN_PART_SIZE:
        part_size_float = float(part_size)
    else:
        # Use floats for part size for all calculations to avoid
        # overflows during float64 to int64 conversions.
        part_size_float = math.ceil(length/MAX_MULTIPART_COUNT)
        part_size_float = (math.ceil(part_size_float/part_size)
                        * part_size)
    # Total parts count.
    total_parts_count = int(math.ceil(length/part_size_float))
    # Part size.
    part_size = int(part_size_float)
    # Last part size.
    last_part_size = length - int(total_parts_count-1)*part_size
    return total_parts_count, part_size, last_part_size
Calculate optimal part size for multipart uploads.

    :param length: Input length to calculate part size of.
    :return: Optimal part size.