Viewing eviction rates for spot virtual machines in the Azure Portal

At any one time Microsoft can have huge amounts of unused computing capacity in their Azure global data centres. In order to monetize this they offer customers ‘Spot’ virtual machines. Spot Virtual machines are those offered to customers at significant cost discount (sometimes up to 90%) but which have no high availability SLAs and from which the customer can be evicted (VM deallocated) as soon as Microsoft needs the capacity back for higher paying customers.

Due to the lack of high availability SLAs spot machines are not suitable for many scenarios. According to Microsoft…

Assuming you have workloads which can deal with and recover from occasional expected downtime the two big considerations when choosing to use spot VMs or not are..

Price Discount – how much are you going to save compared to regular VMs of the same spec in the same region. Does the saving % justify the hassle of potential eviction? With discounts of 60%-90% the hassle is almost certainly justified. Note the spot price is not fixed and can change depending on demand etc.

and

Eviction Rate – how often is the machine going to be deallocated. If your getting kicked out of the VM so often sure you won’t be charged but neither will your workloads complete.

The ideal combination is obviously high % discount and low eviction rate. Pricing information has been available in the portal for a while  (and more recently the pricing API) but eviction rate information is only available (in preview) since October 2020.

Viewing spot virtual machine eviction rates in Azure portal

First open up the ‘Create a virtual machine’ page and select the checkbox next to ‘Azure Spot Instance’.

In the instance above you can see I’m creating a DS2_v2 (general purpose spec) Ubuntu Linux machine in the East US region. The two options to see eviction rates are highlighted above and are ‘See all sizes’ and ‘View pricing history and compare prices in nearby regions’

Eviction rates for all sizes for an operating system and region combination

The see all sizes option shows you pricing and eviction rates for all sizes available for your chosen region (East US) and operating system (Ubuntu) combination. Click on the image below for a larger view.

You can see eviction rate information highlighted in red. I’m not sure what data range the eviction rate covers but the original post on the Azure updates page from October 2020 mentions the rate applies to the last 28 days. And in the case of the VM I selected above (DS2_v2) we have an eviction rate of 0-5% and savings of 78% (current estimated discount, remember spot rates are not fixed) which is great.

By default the ‘See all sizes’ page is ‘Grouped by Series’ but in the screenshot I’ve changed that to ‘No Grouping’ via the top right hand side dropdown. This way I can sort by eviction rates.

Combining eviction rate sort with the min ram and vCPUs filters at the top of the page gives me an easy way to find suitable spot VMs which have the most discount with the least amount of interruption.

From trying a few combinations of operating systems and regions I’m not really seeing any pattern to which VM sizes/types get evicted more or less than others. For example machines which have higher specs aren’t always the ones that get evicted most.

Comparing eviction rates (and prices) across nearby regions

In the above ‘See all sizes’ view there is no comparison with other regions. Comparing rates across nearby regions is useful as we know various Azure services can differ in price from region to region depending on things like demand and infrastructure costs.

To compare eviction rates in regions nearby we can click ‘View pricing history and compare prices in nearby regions’ and a view similar to below (click on the image for a larger view) will open.

We can see the eviction rate for both East US and Canada Central is 0-5%, while East US 2 is significantly higher at 15-20%.

Both East US and East US 2 are based in Virginia so why the big difference in eviction rate? Well judging from the below chart (credit to azureprice.net/Region), on average VMs are cheaper in East US 2. Its just speculation but this might mean East US 2 is more popular and has less unused capacity meaning more evictions and thus lower spot rate.

We can see from the three regions shown above that while Canada Central also has a low eviction rate of 0-5% to match East US it is significantly cheaper meaning it might be a viable spot VM region for development machines (for example) for a team based somewhere in East coast USA (as an alternative to East US / East US 2).

From an architectural point of view yes ideally you’d keep your Azure resources in the same region as whatever/whoever will be using them for latency reasons but everything is a trade off. In this case the teams development boxes will be 1) a lot cheaper and 2) experience less interruptions but might have extra latency. Going by the December 2020 region – region latency figures below latency between East US/East US 2 and Canada Central is around 26-30ms which is still pretty fast.

Looking back at the portal below.. interestingly from a historical pricing point of view we can see that spot prices were highest in East US and East US 2 on November 30th which was Cyber Monday.

Ecommerce shops would have have been a lot busier around this time and thus CPU demand would increase hence higher spot prices. It’s quite possible that eviction rates on Cyber Monday increased in line with spot prices but we can’t know that for sure.

A great future addition to this page would be if we could get a line chart plotting historical eviction rate too so we could see the direct relationship between regions, dates (and possibly times) and eviction rates. Its likely eviction rates are lower during the night so this information could help reduce costs further.

Summary

Spot VMs are relatively new on Azure having only been released into GA (general availability) in May 2020 but there’s huge savings to be made if you have appropriate workloads. Now that eviction rates are available on the portal its easier to find high discount/low interruption VMs. Depending on your workload consider hosting your spot VMs in regions other than those closest and just like normal VMs don’t forget to turn your spot machines off when not using them to reduce costs further.

Easier immutability with Init only properties in C# 9

C# 9 shipped with .NET 5 in November. One change included is init only properties which allow us to have immutable (non-changeable) classes without some of the downsides associated with pre C# 9 approaches.

As can be seen below in C# 8 we’d typically have getters with no setters which gives us immutability…great.. but it means we need a constructor and we can’t use the more shorthand object initializer (C# 3.0) syntax which many developers prefer.

In C# 9 we can use the init keyword which means we can get rid of the constructor and use shorthand object initialization.

This is a small but nice addition to the language and means developers don’t have to choose between ease of use and immutability.

Links

C# 9 Language Features | On .NET | Channel 9 (msdn.com)

What’s new in C# 9.0 – C# Guide | Microsoft Docs

Use SQL Server Sparse columns to optimize storage for columns with mostly NULL values

If your SQL Server database has nullable columns which contain mostly null values consider setting these columns to sparse. Sparse columns are ordinary columns that have been optimized for storing null values. Not all columns can be set to sparse and a number of restrictions apply.

How to set sparse

Columns set to sparse require more storage space for nonnull values (4 additional bytes) than the space required for identical data in a column that is not marked sparse. This means it only makes sense to use sparse when the percentage of nulls is above a certain threshold. The threshold is different for each data type.

An except from Microsofts Estimated Space Savings by Data Type table is below. The red highlight shows how many bytes are needed for normal non sparse columns, this is regardless if they are null or not.

The blue highlight shows bytes required for non null values in sparse columns. Note null values take up 0 space in sparse columns.

The final column shows what percentage of nulls is needed for space saving of 40%. Microsoft recommends using sparse columns when savings are at least 20 – 40%. We can see in yellow that to save 40% space for int columns we need 64% of values to be null, while the corresponding percentage for datetime columns is 52%.

Sparse fixed data types

Determining percentage of null values in a column manually

Pretty simple..

SELECT 100.0 * SUM(CASE WHEN Address4 IS NULL THEN 1 ELSE 0 END) / COUNT(*) from Address AS Address4NullPercent

where Address4 is your column and Address is your table name.

Determining percentage of null values in all columns in all tables dynamically

If you have a large DB and wish to check for sparse candidates across your entire database you can use the script on this page which uses temporary tables and cursors to do this dynamically.

Note the script referenced above might take a while to run so to prevent performance issues for your existing prod processes its best to run it either after hours or on a production clone. It will produce a table similar to below.

sparse-candidates

You’ll get the biggest space savings from using sparse columns with fixed-length columns having a high null percentage in tables with large amounts of records.

Finding which columns are already sparse

SELECT so.name [Table Name], sc.name [Column Name]
FROM sys.columns sc
JOIN sys.objects so
ON so.OBJECT_ID = sc.OBJECT_ID
WHERE is_sparse = 1

 

Introduction to the Azure Pricing API including examples

Microsoft have released (Sept 2020) an unauthenticated API for getting price information for all Azure services into public preview. Previously you could only get prices from the pricing calculator or the portal.

The availability of the API opens up a lot of possibilities for pricing analysis and comparison tools. As we know pricing for Azure services can vary from region to region, so apps which support comparing prices across regions provide at least one use case for the new API.

The endpoint is https://prices.azure.com/api/retail/prices and below I’ll compare API output to a few examples from the pricing calculator.

Virtual Machines

Below we see from the pricing calculator that a standard Linux F4 VM based in North Europe costs $0.226 per hour.

Price Calculator Example

and the output from the Azure pricing API for the same VM is below.

Azure pricing API output

We can see the prices match, both being $0.226 per hour (see line 2, 4 and 18 above). Note the Azure Pricing API currently only supports USD.

The type highlighted on line 19, is Consumption which is the equivalent of pay as you go option in the price calculator. Other possible types are Reservation and DevTestConsumption.

The JSON for the same VM on Windows is very similar but we can see that ‘Windows’ is appended into the productName field (line 13).

Azure windows VM API Pricing

Lets take a look a what reservation prices look like. Reservation pricing if you don’t know allows you to get a discount on your VM compute costs by buying compute time in advance in 1 or 3 year blocks. Reservation pricing can be a great way to reduce your VM cost footprint if you have steady and predictable workloads.

Here’s the Linux VM from above but with 1 year reserved pricing.

Azure pricing API Reserved Pricing API

We can see a price of $0.1542 per hour and here’s the equivalent entry in the Azure price API.

Azure Reservation Prices in API

Note the reservation term is 1 year as shown on line 4. The price on line 5 in this case is $1351, this is the per year cost. The calculation is 8760 (hours per year) * $0.1542 = 1350.792 and then rounded up. The unitOfMeasure on line 19 says 1 hour but the price given is per year so watch out for this.

Cosmos DB

Cosmos DB pricing can be confusing at the best of time and I did find a number of entries in the price API that I couldn’t link back to the pricing calculator and vice versa. This could be a consequence of the API being in preview or more likely I just missed something on my side.

Below shows the pricing calculator for a standard provisioned Cosmos DB in North Europe with the multiple region write option set.

Cosmos DB pricing example from Price Calculator

And the equivalent in the pricing API is below. Note the meterName and skuName fields which are the main differentiators to single write region provisioned Cosmos databases.

cosmos-example-api

Storage

As a final example, shown below is the pricing calculator for cool blob storage with geo-zone-redundant storage (GZRS) redundancy based in the North Europe region. We can see the estimated price is $0.2 per 10,000 write operations.

storage-account-eg

And here’s the corresponding entry in the Azure price API… Notice meterName explicitly calling out that this entry is for cool gzrs write operations. Also note the unitOfMeasure field (line 18) which shows 10k.

storage-api-example

Price details for operations such as read and list and create container are contained in their own line item so to get an all in view of blob storage prices you’ll need to examine multiple entries.

Let’s now look at how we can pull out only specific prices we care about.

Filtering the Azure Price API

Unfiltered the base API URL just returns all prices for all services across all regions in batches of 100. Thankfully a number of filters can be applied using OData filter expressions. According to Microsoft…

Azure Price API filters supported

This is most of the fields returned in the response and gives us a good bit of query power. Microsoft doesn’t give examples of using these filters but if you’ve used OData you might be able to figure things out.

Not all OData expressions will be supported on the pricing API but some examples which do work are below. Note, while the filter names are case insensitive the values to search for are case sensitive.

Equals filter (single)

The basic syntax to match on a single filter is $filter=FILTER eq ‘FILTERVALUE’. For example to only return services for the northeurope region we can query the following URL:

https://prices.azure.com/api/retail/prices?$filter=ArmRegionName%20eq%20%27northeurope%27

Equals filter (multiple)

If we want to search on multiple filters we just use the and/or operators. Eg. $filter=FILTER1 eq ‘FILTER1VALUE’ and FILTER2 eq ‘FILTER2VALUE’. For example to only return virtual machine pricing in northeurope we can hit the following URL:

https://prices.azure.com/api/retail/prices?$filter=ArmRegionName%20eq%20%27northeurope%27%20and%20serviceName%20eq%20%27Virtual%20Machines%27

Not equals

To return entries not equal to a value use the ne operator eg. $filter=FILTER ne ‘FILTERVALUE’. For example to get prices for all services except virtual machines we can use the following URL:

https://prices.azure.com/api/retail/prices?$filter=serviceName%20ne%20%27Virtual%20Machines%27

Startwith/Endswith filter

Find prices for all services whose region ends with ‘europe’

https://prices.azure.com/api/retail/prices?$filter=endswith(armRegionName,%20%27europe%27)

Running framework-dependent .NET 5.0 apps in Azure App Service before RTM

.NET 5 Release Candidate 1 (of 2) has just dropped. Prior to its full release and availability as a built in runtime stack in Azure App Service if your looking to try it out you can of course deploy your .NET 5.0 apps as self-contained. This means you don’t need the framework installed, this is the beauty of .NET Core after all…

BUT…

If you prefer framework-dependent deployments, perhaps due to their much smaller size and quicker deploy time you can install an extension into your App Service to enable the 5.0 RC1 runtime.

The extension option is available if you navigate to your app service and click Development Tools -> Extensions. Restart your app afterwards.

Using .Net 5 in Azure App Service