{"id":1175,"date":"2020-08-04T15:40:07","date_gmt":"2020-08-04T22:40:07","guid":{"rendered":"http:\/\/blog.nillsf.com\/?p=1175"},"modified":"2020-08-10T11:04:42","modified_gmt":"2020-08-10T18:04:42","slug":"using-nfs-on-azure-blob-and-some-performance-tests","status":"publish","type":"post","link":"https:\/\/nillsf.com\/index.php\/2020\/08\/04\/using-nfs-on-azure-blob-and-some-performance-tests\/","title":{"rendered":"Using NFS on Azure blob and some performance tests"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">Recently, <a href=\"https:\/\/azure.microsoft.com\/en-us\/blog\/nfs-30-support-for-azure-blob-storage-is-now-in-preview\/\">Microsoft announced<\/a> that they&#8217;re enabling the NFS protocol on top of blob storage. This is growing the strategy that started with ADLS gen 2, which put the HDFS protocol on top of blob storage. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I am working on a number of projects where this support would be helpful for customers. It&#8217;s still early days for the NFS support, so it&#8217;s not an immediate help, but I wanted to give it a try.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In this post, I&#8217;ll explain how to set it up, and then I&#8217;ll take you through some intensive performance testing I did. This blog post might be updated in the future, <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Some technical details<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">NFS on blob uses the NFS v3 protocol. This has one impact: NFS v3 is not encrypted. The Azure storage team knows about this, and will &#8211; to protect users &#8211; only allow NFS access over either a <a href=\"https:\/\/blog.nillsf.com\/index.php\/2017\/11\/14\/vnet-service-endpoints\/\">service endpoint<\/a> or <a href=\"https:\/\/blog.nillsf.com\/index.php\/2019\/11\/17\/privately-connecting-to-paas-services-using-azure-private-link\/\">private link<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Right now, the access to NFS is either NFS or blob on a storage account. This means you can&#8217;t (like ADLS gen 2) use blob and NFS on the same account. Based on the Azure documentation, it seems like the plan is to support this multi-protocol write. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"656\" height=\"358\" src=\"\/wp-content\/uploads\/2020\/07\/image-17.png\" alt=\"\" class=\"wp-image-1176\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-17.png 656w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-17-300x164.png 300w\" sizes=\"auto, (max-width: 656px) 100vw, 656px\" \/><figcaption>Some of the features not yet supported.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">For now, it&#8217;s also important to note that you cannot enable\/disable NFS on an existing storage account. Which means you&#8217;ll have to create a new one, dedicated to NFS.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">During the preview, NFS 3.0 is available to BlockBlobStorage accounts with premium performance in the following regions: US East, US Central, and Canada Central. Support for GPV2 accounts with standard tier performance will be announced <em>soon<\/em>. <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Pre-setup<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Before we setup a new storage account, we need to register the feature. This requires three commands (using Azure PowerShell):<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Register-AzProviderFeature -FeatureName AllowNFSV3 -ProviderNamespace Microsoft.Storage \nRegister-AzProviderFeature -FeatureName PremiumHns -ProviderNamespace Microsoft.Storage  \nRegister-AzResourceProvider -ProviderNamespace Microsoft.Storage<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This registration process will take a couple of minutes. I believe that in my case it took about 10 minutes to get the provider registered.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Since I have no resources in any of the preview regions, I decided to spin up a new VNET in East US with a Linux VM.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Creating an NFS blob storage account<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">To create a new storage account, I&#8217;ll use the Azure portal. Since right now this is only support on BlockBlobStorage accounts with premium performance, we&#8217;ll create such a storage account.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"760\" height=\"895\" src=\"\/wp-content\/uploads\/2020\/07\/image-18.png\" alt=\"\" class=\"wp-image-1177\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-18.png 760w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-18-255x300.png 255w\" sizes=\"auto, (max-width: 760px) 100vw, 760px\" \/><figcaption>Creating a new storage account<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In terms of networking &#8211; remember, this is required for NFS &#8211; I&#8217;ll use regular public service endpoints. Private endpoints are also supported, but I decided to go with the public variant for my testing.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"853\" height=\"790\" src=\"\/wp-content\/uploads\/2020\/07\/image-19.png\" alt=\"\" class=\"wp-image-1178\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-19.png 853w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-19-300x278.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-19-768x711.png 768w\" sizes=\"auto, (max-width: 853px) 100vw, 853px\" \/><figcaption>Setting up networking<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">I skipped the data protection tab, and enabled the hierarchical namespace and NFS v3 support in the Advanced tab.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"787\" height=\"393\" src=\"\/wp-content\/uploads\/2020\/07\/image-20.png\" alt=\"\" class=\"wp-image-1179\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-20.png 787w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-20-300x150.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-20-768x384.png 768w\" sizes=\"auto, (max-width: 787px) 100vw, 787px\" \/><figcaption>Enabling NFS<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">And with that, we can create the storage account.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"735\" height=\"897\" src=\"\/wp-content\/uploads\/2020\/07\/image-21.png\" alt=\"\" class=\"wp-image-1180\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-21.png 735w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-21-246x300.png 246w\" sizes=\"auto, (max-width: 735px) 100vw, 735px\" \/><figcaption>Review and create<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, once the account is created, we&#8217;ll need to create a container on this account. I created a container called &#8216;nillstest&#8217; on my account.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Mounting blob via NFS in a VM<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mounting blob via NFS in a VM was very easy. First step was to install <code>nfs-common,<\/code> second step was creating a directory to mount into, final step was mounting. That was it.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>#install nfs-common\nsudo apt-get update\nsudo apt-get install nfs-common -y\n\n#create mount point\nsudo mkdir \/mnt\/blob\n\n#mount\nmount -o sec=sys,vers=3,nolock,proto=tcp nfblobnfs.blob.core.windows.net:\/nfblobnfs\/nillstest  \/mnt\/blob<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And that seemed to do the job.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I wanted to also test the performance of this new feature, so that&#8217;s what we&#8217;ll cover next.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Testing performance<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Using dd<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">Let&#8217;s start with a couple of rudimentary performance tests using the <code>dd <\/code>command. For reference, I&#8217;m running all of this on a Standard E16as_v4, which has 8Gbps of network throughput. I did a couple of regular <code>dd <\/code>tests first.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>dd if=\/dev\/zero of=\/tmp\/test-1.img bs=1G count=1\ndd if=\/dev\/zero of=\/tmp\/test-4.img bs=8k count=100k<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Both commands resulted in performance that was all over the map, anywhere between 15MB\/s and 250MB\/s. Not sure what was causing this, whether it was caching or throttling. Some of the results of these tests:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"744\" height=\"81\" src=\"\/wp-content\/uploads\/2020\/07\/image-22.png\" alt=\"\" class=\"wp-image-1183\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-22.png 744w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-22-300x33.png 300w\" sizes=\"auto, (max-width: 744px) 100vw, 744px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"739\" height=\"83\" src=\"\/wp-content\/uploads\/2020\/07\/image-23.png\" alt=\"\" class=\"wp-image-1184\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-23.png 739w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-23-300x34.png 300w\" sizes=\"auto, (max-width: 739px) 100vw, 739px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"769\" height=\"83\" src=\"\/wp-content\/uploads\/2020\/07\/image-24.png\" alt=\"\" class=\"wp-image-1185\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-24.png 769w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-24-300x32.png 300w\" sizes=\"auto, (max-width: 769px) 100vw, 769px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"772\" height=\"241\" src=\"\/wp-content\/uploads\/2020\/07\/image-25.png\" alt=\"\" class=\"wp-image-1186\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-25.png 772w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-25-300x94.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-25-768x240.png 768w\" sizes=\"auto, (max-width: 772px) 100vw, 772px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see in the screenshots above, the performance was all over the place.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I&#8217;ve seen this before, <code>dd <\/code>isn&#8217;t the most reliable way to do disk performance testing. I&#8217;ve also used <code>fio <\/code>in the past, so I decided to give that a spin to get an idea of the performance.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using fio<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">As I mentioned in the previous section, <code>dd<\/code> can deliver inconsistent test results. <code>fio <\/code>is a more full featured io testing tool. To install <code>fio<\/code>, you can run:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>sudo apt-get install fio -y<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">And we can then do a couple tests. First test is doing a sequential write test using synchronous IO (i.e. without OS level caching) with a 32k block size:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fio --name=seqwrite --rw=write --direct=1 --ioengine=libaio --bs=32k --numjobs=4 --size=1G --runtime=300 --group_reporting<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">One thing to notice when running fio is that I&#8217;m getting an IO error, which actually isn&#8217;t blocking the tests itself:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"591\" height=\"146\" src=\"\/wp-content\/uploads\/2020\/07\/image-27.png\" alt=\"\" class=\"wp-image-1188\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-27.png 591w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-27-300x74.png 300w\" sizes=\"auto, (max-width: 591px) 100vw, 591px\" \/><figcaption>Error about the native_fallocate call. This does not limit the test from running.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Ignoring that error and looking at the performance, I could see performance at about 70 to 90 IOPS initially, dropping to about 30 IOPS after about a minute. On average the IO performance was 48 write IOPS Certainly not spectacular:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"461\" src=\"\/wp-content\/uploads\/2020\/08\/image-1024x461.png\" alt=\"\" class=\"wp-image-1192\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-1024x461.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-300x135.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-768x346.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image.png 1165w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Doing a 32k direct IO write test results in an avg of 48 IOPS.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This performance can be improved by adding the <code>--iodepth<\/code> parameter to fio. This means that fio would use more parallel writers to achieve better performance. Using &#8211;iodepth=50, I was able to achieve 403IOPS using this 32k block size sequential write test.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"471\" src=\"\/wp-content\/uploads\/2020\/08\/image-1-1024x471.png\" alt=\"\" class=\"wp-image-1193\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-1-1024x471.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-1-300x138.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-1-768x353.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-1.png 1183w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Using a higher iodepth increased write performance to 403IOPS.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">To offer some comparison, I ran the same fio tests on the temporary drive of the VM (also called ephemeral drive), and was able to achieve the following results:<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Direct IO, iodepth 1: 8170 write IOPS \/ BW=255 MiB\/s (throttled by write BW of the VM, which is 255MiB\/s<\/li><li>Direct IO, iodepth 50: 8320 write IOPS \/ BW=273 MiB\/s (throttled by write BW of the VM, which is 255MiB\/s <\/li><\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">So the limit here certainly is the NFS blob storage account. Let&#8217;s have a look at non-direct IO next.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Removing the <code>--direct=1<\/code> option in fio increased performance tremendously. If <code>direct=1<\/code>, fio uses non-buffered I\/O (usually O_DIRECT). This means that the system doesn&#8217;t use any of Linux built-in caching for IO. For more info on that, check out this <a href=\"http:\/\/www.alexonlinux.com\/what-is-direct-io-anyway\">blog post<\/a>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Without the direct=1 flag, we&#8217;ll use a bit of memory to optimize write performance. To get sort of relevant numbers, I decided to use a 150G file (memory of my VM was 128G), and see how long writing this using a single iodepth would take. The command was:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>fio --name=seqwrite --rw=write --ioengine=libaio --bs=32k --numjobs=4 --size=150G --group_reporting<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">Initially, performance was incredible at about 30k IOPS. This however decreased quickly to about 5k IOPS and 150 MiB\/s. Throughout the test, IO was variable between 1k IOPS and 30MB\/s and 6k IOPS an 200MB\/s. Some of the variability is explained as well in the network out graph in the Azure portal. This shows at its lowest point 3.4GB written (per minute), which equates to 58MB\/s. Overall, the job averaged 2332 IOPS and 73MB\/s.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"493\" src=\"\/wp-content\/uploads\/2020\/08\/image-2-1024x493.png\" alt=\"\" class=\"wp-image-1194\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-2-1024x493.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-2-300x144.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-2-768x370.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-2.png 1171w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Averaging 2332 IOPS and 73MB\/s over a 150G file.<\/figcaption><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"522\" src=\"\/wp-content\/uploads\/2020\/08\/2020-08-03-18_58_39-Window-1024x522.png\" alt=\"\" class=\"wp-image-1199\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/2020-08-03-18_58_39-Window-1024x522.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/2020-08-03-18_58_39-Window-300x153.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/2020-08-03-18_58_39-Window-768x391.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/2020-08-03-18_58_39-Window-1536x783.png 1536w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/2020-08-03-18_58_39-Window.png 1658w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>The network graph (aka NFS traffic) while doing fio tests. At the low point, we had 58MB\/s.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">This performance was better than direct IO, but still not impressive. I did the same test with some different parameters, and never really got above the 80MB\/s watermark (for these large files). As it might have been an artifact of the testing tool, I decided to do a real world test downloading a large file.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using wget and downloading a file<\/h3>\n\n\n\n<p class=\"wp-block-paragraph\">To do a more real-worldy type of test, I decided to create a 20G file on blob storage (in the same region, but different account. Can&#8217;t do NFS and blob on same account yet) and download that file. <\/p>\n\n\n\n<p class=\"wp-block-paragraph\">To create a 20G file, I used <code>azcopy bench<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>azcopy bench \"https:\/\/blobnfsdiag.blob.core.windows.net\/test?*SAS TOKEN*\" --file-count 1 --size-per-file 20G --delete-test-data=false<\/code><\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">This will create the 20G file as part of a <code>azcopy bench<\/code> test, and keep it there. I then went into the portal and got a SAS token to that file. I then did a simple wget to the url of the 20G file:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"272\" src=\"\/wp-content\/uploads\/2020\/07\/image-28-1024x272.png\" alt=\"\" class=\"wp-image-1189\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-28-1024x272.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-28-300x80.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-28-768x204.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-28.png 1416w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"246\" src=\"\/wp-content\/uploads\/2020\/07\/image-29-1024x246.png\" alt=\"\" class=\"wp-image-1190\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-29-1024x246.png 1024w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-29-300x72.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-29-768x185.png 768w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/07\/image-29.png 1172w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><figcaption>Downloading a 20G file.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see from the screenshot above, I was getting roughly 80 to 100MB\/s in download speed, which was written directly to the blob\/NFS directory. I used the time command the measure the time it took, and using that for reference, I had an overall average download speed of 84.29 MB\/s.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"184\" height=\"70\" src=\"\/wp-content\/uploads\/2020\/07\/image-30.png\" alt=\"\" class=\"wp-image-1191\"\/><figcaption>Time it took to download a 20G file.<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">So, that confirmed that a single threaded write using wget could achieve about 85MB\/s. Then I tried out multithreading this, by doing the same download 5 times. Why 5? 5 times downloading 80MB\/s and writing 80MB\/s over NFS comes close to the 8Gbps NIC limit on this VM.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I put the screenshot of the result below. Doing the math, this equates to an average download speed across the 5 files of 221.645MB\/s. <\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"805\" height=\"225\" src=\"\/wp-content\/uploads\/2020\/08\/image-3.png\" alt=\"\" class=\"wp-image-1196\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-3.png 805w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-3-300x84.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-3-768x215.png 768w\" sizes=\"auto, (max-width: 805px) 100vw, 805px\" \/><figcaption>Downloading\/writing 5 files concurrently at an average of 220MB\/s.<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">File copying<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Finally, I did some testing moving files around. First I tried moving files from the temporary drive to NFS. This moved at 240MB\/s (throttled at the write throughput of the VM itself).<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"868\" height=\"40\" src=\"\/wp-content\/uploads\/2020\/08\/image-4.png\" alt=\"\" class=\"wp-image-1197\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-4.png 868w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-4-300x14.png 300w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-4-768x35.png 768w\" sizes=\"auto, (max-width: 868px) 100vw, 868px\" \/><figcaption>Moving from temporary drive to NFS at 240MB\/s<\/figcaption><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Then as a final test, I decided to do a simple copy to copy a file on blob NFS to blob NFS. This means reading and writing over that blob NFS connection at the same time. This moved at 119MB\/s.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"625\" height=\"106\" src=\"\/wp-content\/uploads\/2020\/08\/image-5.png\" alt=\"\" class=\"wp-image-1198\" srcset=\"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-5.png 625w, https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-5-300x51.png 300w\" sizes=\"auto, (max-width: 625px) 100vw, 625px\" \/><figcaption>Copying 20GB in 2min52 seconds means reading\/writing at 119MB\/s<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Mounting blob in a VM using NFS was super easy. Measuring the performance however was a bit of a mixed experience. Depending on how we measured experience, we saw experience be as low as a couple 10s of IOPS and kb of throughput (synchronous IO) to a couple thousand IOPS and about 100MB\/s of throughput.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">As an employee of Microsoft, I am passing that feedback to our product team, and trying to figure out if I should adapt my tests to better reflect the product truth. I&#8217;ll update this post when more info is available.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, Microsoft announced that they&#8217;re enabling the NFS protocol on top of blob storage. This is growing the strategy that started with ADLS gen 2, which put the HDFS protocol on top of blob storage. I am working on a number of projects where this support would be helpful for customers. It&#8217;s still early days [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":1194,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[2],"tags":[8,68,75,139],"class_list":["post-1175","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-azure","tag-azure","tag-blob","tag-blob-storage","tag-nfs"],"jetpack_featured_media_url":"https:\/\/nillsfblog.blob.core.windows.net\/media\/2020\/08\/image-2.png","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1175","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/comments?post=1175"}],"version-history":[{"count":5,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1175\/revisions"}],"predecessor-version":[{"id":1228,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/posts\/1175\/revisions\/1228"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/media\/1194"}],"wp:attachment":[{"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/media?parent=1175"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/categories?post=1175"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/nillsf.com\/index.php\/wp-json\/wp\/v2\/tags?post=1175"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}