Skip to content

Instantly share code, notes, and snippets.

@peterhurford
Last active August 24, 2018 18:46
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save peterhurford/a80e6b2b156c19ce9985c05af5275aa7 to your computer and use it in GitHub Desktop.
Save peterhurford/a80e6b2b156c19ce9985c05af5275aa7 to your computer and use it in GitHub Desktop.
Find the best deals in AWS spot instances across all availability zones and multiple instance types
# For every AWS availability zone and instance I care about, check the spot
# price for the last ninety days and generate stats about which spot instance
# gives the best deal.
import boto
import boto.ec2
from vowpal_platypus.utils import mean
REGIONS = {'us-east-1': ['us-east-1a', 'us-east-1b', 'us-east-1c', 'us-east-1e'],
'us-west-1': ['us-west-1a', 'us-west-1b'],
'us-west-2': ['us-west-2a', 'us-west-2b', 'us-west-2c']}
INSTANCES = {'m4.10xlarge': {'cpu': 40, 'ram': 160, 'odprice': 2},
'm4.16xlarge': {'cpu': 64, 'ram': 256, 'odprice': 3.2},
'c4.4xlarge': {'cpu': 16, 'ram': 30, 'odprice': 0.796},
'c4.8xlarge': {'cpu': 36, 'ram': 60, 'odprice': 1.591},
'x1.16xlarge': {'cpu': 64, 'ram': 976, 'odprice': 6.669},
'x1.32xlarge': {'cpu': 128, 'ram': 1952, 'odprice': 13.338},
'r4.4xlarge': {'cpu': 16, 'ram': 122, 'odprice': 1.064},
'r4.8xlarge': {'cpu': 32, 'ram': 244, 'odprice': 2.128},
'r4.16xlarge': {'cpu': 64, 'ram': 488, 'odprice': 4.256}}
def find_best(data, label, fn):
return fn(map(lambda y: (y[0], y[1][0], y[1][1][label]),
map(lambda x: (x[0], fn(x[1].items(), key=lambda x: x[1][label])),
data.items())), key=lambda z: z[2])
data = {}
for region, zones in REGIONS.iteritems():
print('REGION: ' + str(region))
ec2 = boto.ec2.connect_to_region(region)
for zone in zones:
print('...ZONE: ' + str(zone))
data[zone] = {}
for instance, instance_data in INSTANCES.iteritems():
print('... ...Instance: ' + str(instance))
prices = ec2.get_spot_price_history(start_time='2017-03-01T22:54:13',
end_time='2017-06-01T22:53:09',
instance_type=instance,
availability_zone=zone)
if len(prices) > 0:
spot_price = mean(map(lambda x: x.price, prices))
odprice = instance_data['odprice']
data[zone][instance] = {'odprice': odprice,
'spot_price': spot_price,
'diff': odprice - spot_price,
'discount': 1 - spot_price / float(odprice),
'odprice_per_core': odprice / float(instance_data['cpu']),
'odprice_per_ram': odprice / float(instance_data['ram']),
'spot_price_per_core': spot_price / float(instance_data['cpu']),
'spot_price_per_ram': spot_price / float(instance_data['ram'])}
data[zone][instance]['od_spot_per_core_diff'] = data[zone][instance]['odprice_per_core'] - data[zone][instance]['spot_price_per_core']
data[zone][instance]['od_spot_per_core_discount'] = 1 - data[zone][instance]['spot_price_per_core'] / float(data[zone][instance]['odprice_per_core'])
data[zone][instance]['od_spot_per_ram_diff'] = data[zone][instance]['odprice_per_ram'] - data[zone][instance]['spot_price_per_ram']
data[zone][instance]['od_spot_per_ram_discount'] = 1 - data[zone][instance]['spot_price_per_ram'] / float(data[zone][instance]['odprice_per_ram'])
for instance, instance_data in INSTANCES.iteritems():
print((instance, instance_data['odprice'], mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price') if x[1].get(instance) else None, data.items())))))
for instance, instance_data in INSTANCES.iteritems():
print((instance, mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price_per_core') if x[1].get(instance) else None, data.items())))))
for instance, instance_data in INSTANCES.iteritems():
print((instance, mean(filter(lambda y: y is not None, map(lambda x: x[1][instance].get('spot_price_per_ram') if x[1].get(instance) else None, data.items())))))
print('LOWEST SPOT PRICE')
print(find_best(data, 'spot_price', fn=min))
print('LARGEST OD-SPOT PRICE DISCOUNT')
print(find_best(data, 'discount', fn=max))
print('BEST OD PRICE PER CORE')
print(find_best(data, 'odprice_per_core', fn=min))
print('BEST SPOT PRICE PER CORE')
print(find_best(data, 'spot_price_per_core', fn=min))
print('BEST OD-SPOT PRICE DISCOUNT PER CORE')
print(find_best(data, 'od_spot_per_core_discount', fn=max))
print('BEST OD PRICE PER RAM')
print(find_best(data, 'odprice_per_ram', fn=min))
print('BEST SPOT PRICE PER RAM')
print(find_best(data, 'spot_price_per_ram', fn=min))
print('BEST OD-SPOT PRICE DISCOUNT PER RAM')
print(find_best(data, 'od_spot_per_ram_discount', fn=max))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment