<?xml version="1.0" encoding="utf-8"?>
<rss xmlns:atom="https://www.w3.org/2005/Atom" xmlns:sy="https://purl.org/rss/1.0/modules/syndication/" xmlns:dc="https://purl.org/dc/elements/1.1/" xmlns:content="https://purl.org/rss/1.0/modules/content/" xmlns:wfw="https://wellformedweb.org/CommentAPI/" xmlns:slash="https://purl.org/rss/1.0/modules/slash/"
  version="2.0">
  <channel>
    <title>yingqin</title>
    <atom:link
      href="https://docs.microsoft.com/archive/blogs/yingqin/feed.xml"
      rel="self"
      type="application/rss+xml" />
    <link>https://docs.microsoft.com/archive/blogs/yingqin/feed.xml</link>
    <description />
    <lastBuildDate>Wed, 17 Apr 2019 03:27:16 GMT</lastBuildDate>
    <language>en-US</language>
    <sy:updatePeriod>hourly</sy:updatePeriod>
    <sy:updateFrequency>1</sy:updateFrequency>
    <item>
      <title>Load data to Azure Data Lake Store with high throughput</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/load-data-to-azure-data-lake-store-with-high-throughput</link>
      <pubDate>Mon, 28 Dec 2015 22:32:00 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2015/12/28/load-data-to-azure-data-lake-store-with-high-throughput/</guid>
      <description><![CDATA[In general, a suggested way is to leverage Azure Data Factory to copy data from/to Azure Data Lake...]]></description>
      <content:encoded><![CDATA[<p>In general, a suggested way is to leverage Azure Data Factory to copy data from/to Azure Data Lake Store to/from many data sources like Azure Blob, SQL Sever, Azure SQL DW, etc. It is code-free, and it handles performance optimization, resilience handling and scheduling for you. You could even leverage multiple VMs to have an extreme good perfomrance. Refer to this article for more details: <a href="https://azure.microsoft.com/en-us/documentation/articles/data-factory-azure-datalake-connector/">https://azure.microsoft.com/en-us/documentation/articles/data-factory-azure-datalake-connector/</a>.</p>
<p>&nbsp;</p>
<p>On the other hand, if you want to develop a custom application to load data to Azure Data Lake Store, you could leverage the Data Lake Store .Net SDK to load data. Refer to this article for more details: <a href="https://azure.microsoft.com/en-us/documentation/articles/data-lake-store-get-started-net-sdk/">https://azure.microsoft.com/en-us/documentation/articles/data-lake-store-get-started-net-sdk/</a>.&nbsp;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Column mappings in SqlBulkCopy are case sensitive</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/column-mappings-in-sqlbulkcopy-are-case-sensitive</link>
      <pubDate>Wed, 15 Jul 2015 00:56:49 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2015/07/15/column-mappings-in-sqlbulkcopy-are-case-sensitive/</guid>
      <description><![CDATA[When you use SqlBulkCopy and set the&nbsp;ColumnMappings property, the column names are case...]]></description>
      <content:encoded><![CDATA[<p>When you use SqlBulkCopy and set the&nbsp;ColumnMappings property, the column names are case sensitive regardless of the case sensitivity setting in target DB. A general error message "The given ColumnMapping does not match up with any column in the source or destination"&nbsp;would be thrown in such case, whch is very hard to identify what column is not matched. Refer to this article which also discusses this issue: <a href="https://stackoverflow.com/questions/438587/sqlbulkcopy-not-working">https://stackoverflow.com/questions/438587/sqlbulkcopy-not-working</a>.</p>]]></content:encoded>
    </item>
    <item>
      <title>Be Careful when using Table-Valued Parameter</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/be-careful-when-using-table-valued-parameter</link>
      <pubDate>Wed, 27 May 2015 01:31:11 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2015/05/27/be-careful-when-using-table-valued-parameter/</guid>
      <description><![CDATA[Recently we found two implicit traps when using Table-Valued Parameter, which may easily lead to...]]></description>
      <content:encoded><![CDATA[<p>Recently we found two implicit traps when using Table-Valued Parameter, which may easily lead to unexpected behaviors.</p>
<p>First is that it needs additional precision/scale information when passing decimal type data, otherwise the decimal data would be rounded like long type value. It is very hidden as there is no exception thrown, and we can only find it by manually checking the data. In the meantime, as ADO.Net DataTable class doesn't contain precision/scale information, it means you cannot directly pass the DataTable as the parameter. You may either use IEnumerator&lt;SqlDataRecord&gt;&nbsp;or use DbDataReader created from DataTable and reset the schema table. Refer to this <a href="https://social.msdn.microsoft.com/Forums/sqlserver/en-US/a88ad5d5-3286-47cf-ba40-df1445253814/tablevalued-parameters-containing-decimals?forum=sqldataaccess">article</a> which also discusses such issue.</p>
<p>Second is that the data is populated by position instead of column names, although you have column names defined in DataTable/DbDataReader and column names defined in table type. As there is no exception thrown, it is hard to realize if the data is corrupted for incorrect orders. Refer to this <a href="https://social.msdn.microsoft.com/Forums/sqlserver/en-US/103abb3a-2f02-45c4-a4ba-392652c71f70/tvp-from-c-datatable-is-populated-by-position-and-not-by-column-name-bug?forum=transactsql">article</a> which also discusses this issue.</p>]]></content:encoded>
    </item>
    <item>
      <title>Build warning msb3247 and msb3276 and msb3277</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/build-warning-msb3247-and-msb3276-and-msb3277</link>
      <pubDate>Fri, 13 Feb 2015 03:53:00 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2015/02/13/build-warning-msb3247-and-msb3276-and-msb3277/</guid>
      <description><![CDATA[Frequently we may meet build warnings if&nbsp;a project indirectly&nbsp;reference same assembly with...]]></description>
      <content:encoded><![CDATA[<p>Frequently we may meet build warnings if&nbsp;a project indirectly&nbsp;reference same assembly with different versions. Recently I just noticed that such conflict version assembly may cause three similar/different build warnings: msb3247, msb3276&nbsp;and msb3277. The error messages are very similar, all contains words like "Found conflicts between different versions of the same dependent assembly". However, the solution to resolve the build warnings are quite different.</p>
<p>When meet such warning, the first thing is to identify which assembly has conflicts. To do that, you just need to add a property in msbuild, e.g. "msbuild /fileLoggerParameters:LogFile=MyLog.log;<strong>Verbosity=detailed</strong>". The detailed build logs would be written to the file, which contains a log like "There was a conflict between "&lt;assembly&gt;, Version=&lt;version1&gt;" and "&lt;assembly&gt;, Version=&lt;version2&gt;"." to tell you the conflict assembly.</p>
<p>For msb3276, I can repro the build warning in Visual Studio 2013.&nbsp;You could add an assembly binding "&lt;bindingRedirect oldVersion="0.0.0.0 - 2.0.0.0" newVersion="<strong>2.0.0.0</strong>"/&gt;"&nbsp;in app.config/web.config to resolve the warning. Refer to <a href="https://msdn.microsoft.com/en-us/library/eftw1fys(v=vs.110).aspx">https://msdn.microsoft.com/en-us/library/eftw1fys(v=vs.110).aspx</a>. Or&nbsp;set the "AutoGenerateBindingRedirects" property to true in the project file. For more information, see <a href="https://go.microsoft.com/fwlink/?LinkId=294190">https://go.microsoft.com/fwlink/?LinkId=294190</a>. This warning can be reproed with the following dependencies trees:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V1.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Project B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V2.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Executable Project A</p>
<p>&nbsp;</p>
<p>For&nbsp;msb3277, I can repro the build warning in Visual Studio 2013. I found two kinds of situations could cause this warning.&nbsp;One case can be resolved by assembly binding, but the second one cannot.</p>
<p>(1)&nbsp; The first case can be resolved by adding an assembly binding "&lt;bindingRedirect oldVersion="0.0.0.0 - 2.0.0.0" newVersion="<strong>1.0.0.0</strong>" /&gt;", but cannot be resolved by setting the "AutoGenerateBindingRedirects" property.&nbsp;This case can be reproed with the following dependencies trees:</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V2.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Project B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V1.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Executable Project A</p>
<p>&nbsp;(2) For the second case, it seems no easy way to resolve the warning but to use the same version of assembly instead. This case can be reproed with the following dependencies trees:</p>
<p>Assembly C V2.0.0.0&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>Assembly D&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V1.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Project B&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Assembly C V1.0.0.0</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Executable Project A</p>
<p>&nbsp;</p>
<p>For msb3247, I can repro the build warning in Visual Studio 2012 &lt;lower version may also repro&gt;. The above three kinds of dependencies trees would cause the same warning msb3247 in VS2012, so such warning code cannot tell you whether you can resolve it with assembly binding. However, there is a difference that if the warning messages contain a hint like "Consider app.config remapping of assembly... ", it is like the msb3276 in VS2013 and you could resolve it by assembly binding. Otherwise, it is like the msb3277 in VS2013 and there are two&nbsp;situations/solutions.</p>]]></content:encoded>
    </item>
    <item>
      <title>Use PsTools to view certificate installed by System account</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/use-pstools-to-view-certificate-installed-by-system-account</link>
      <pubDate>Mon, 26 Jan 2015 19:35:50 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2015/01/26/use-pstools-to-view-certificate-installed-by-system-account/</guid>
      <description><![CDATA[If you want to view certificates installed by System account in an Azure VM, directly remote to the...]]></description>
      <content:encoded><![CDATA[<p>If you want to view certificates installed by System account in an Azure VM, directly remote to the VM cannot view the certificates as you are login in as a remote account. I just found an easy way to accomplish this purpose by using PsTools.</p>
<ol>
<li>Download PsTools from <a href="https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx">https://technet.microsoft.com/en-us/sysinternals/bb897553.aspx</a>.</li>
<li>Copy the bits to the VM.</li>
<li>Run command "psexec -i -s mmc" to view the wanted certificates.</li>
</ol>
<p>PsTools is also a convenient way to let you run your program as System account. Just run "psexec -i -s cmd.exe", and do anything as System account in the popup command line.</p>]]></content:encoded>
    </item>
    <item>
      <title>Use Data-Driven Test for Parameterized Tests</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/use-data-driven-test-for-parameterized-tests</link>
      <pubDate>Thu, 06 Nov 2014 01:19:41 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2014/11/06/use-data-driven-test-for-parameterized-tests/</guid>
      <description><![CDATA[In daily development, we usually have a requirement to write paramterized test cases. I used to use...]]></description>
      <content:encoded><![CDATA[<p>In daily development, we usually have a requirement to write paramterized test cases. I used to use the following two simple methods Method 1 and Method 2&nbsp;to accomplish such requirments, but their short comings are obvious. The first method works for few variations, but it is ineffient if there are too many parameters. The second method need additional logics for error handlings, otherwise the former failed case would break the entire case. But it is still hard to trouble shoot such cases as all messages are huddled into the same case.</p>
<p>This article aims to introduce the third way, which takes advantage of Data-Driven Test for such requirement.</p>
<p>The following Method 3&nbsp;is a sample to use Data-Driven Test. It would logically split a test case into several sub test cases. To some extend, such method doesn't have the short comings in the former two methods.</p>
<p>But I think&nbsp;there still exists&nbsp;some open issues for Method 3. Would further investigate whether there is a better solution.</p>
<ul>
<li>The first issue is the test case display name. With method 3, the sub test cases' names would be like "TestTransfer (Data Row 0)" and "TestTransfer (Data Row 1)", which are not informative.</li>
<li>The second issue is that the xml file may be also duplicate, if I have several kinds of parameters and want to test all combinations of them.</li>
<ul>
<li>E.g. if there is another parameter "DataType", the xml file would be like "1024, txt", "1048576, txt", "1024, jpg", "1048576, jpg".</li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>Method 1</strong>: Create new test methods for each variation. E.g.</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [TestMethod()]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void TestTransfer_1KB()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestTransfer(1 * 1024);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [TestMethod()]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void TestTransfer_1MB()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestTransfer(1 * 1024 * 1024);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; private void TestTransfer(long dataSize)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // ...<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p><strong>Method 2</strong>: Put all variations into a single method. E.g.</p>
<p>&nbsp;</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [TestMethod()]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void TestTransfer()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var allDataSize = new long[] { 1 * 1024, 1 * 1024 * 1024 };<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; foreach (var dataSize in allDataSize)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestTransfer(dataSize);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p><strong>Method 3</strong>: Data-Driven Test. E.g.</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public TestContext TestContext { get; set; }</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [TestMethod()]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; [DataSource("Microsoft.VisualStudio.TestTools.DataSource.XML", "TransferTest.xml", "Transfer", DataAccessMethod.Sequential)]<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; public void TestTransfer()<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; TestTransfer(long.Parse(TestContext.DataRow["DataSize"].ToString()));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</p>
<p>&nbsp;</p>
<p>TransferTest.xml:</p>
<p>&nbsp;&lt;Settings&gt;<br />&nbsp; &lt;Transfer&gt;<br />&nbsp;&nbsp;&nbsp; &lt;DataSize&gt;1024&lt;/DataSize&gt;<br />&nbsp; &lt;/Transfer&gt;<br />&nbsp; &lt;Transfer&gt;<br />&nbsp;&nbsp;&nbsp; &lt;DataSize&gt;1048576&lt;/DataSize&gt;<br />&nbsp; &lt;/Transfer&gt;<br />&lt;/Settings&gt;</p>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>A quite efficient compression algorithm: Blosc</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/a-quite-efficient-compression-algorithm-blosc</link>
      <pubDate>Thu, 29 May 2014 02:38:00 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2014/05/29/a-quite-efficient-compression-algorithm-blosc/</guid>
      <description><![CDATA[Recently I&nbsp;just learnt about a new compression algorithm Blosc (https://www.blosc.org/trac). It...]]></description>
      <content:encoded><![CDATA[<p>Recently I&nbsp;just learnt about a new compression algorithm Blosc (<a href="https://www.blosc.org/trac">https://www.blosc.org/trac</a>). It has amazing performance, but with poor compression ratio (by design).</p>
<p>I have done a performance comparison between the Blosc and the .Net built in Deflate compression algorithm.</p>
<p>Here is my PC environment:</p>
<ul>
<li>CPU: Intel Xeon CPU E5-1620 3.6 GHz</li>
<li>RAM: 16.0 GB</li>
</ul>
<p>For Blosc, I use the following settings:</p>
<ul>
<li>Number of threads: 1</li>
<ul>
<li>Set as single thread for fair comparison. Using multi-threads will improve the throughput a lot.</li>
</ul>
<li>
<p>Compression level: 9</p>
</li>
<ul>
<li>It is the desired compression level and must be a number between 0 (no<br />compression) and 9 (maximum compression).</li>
</ul>
<li>
<p>Whether do shuffle: No</p>
</li>
<li>
<p>Type size: 8</p>
</li>
</ul>
<p>&nbsp;</p>
<table style="width: 599px; height: 360px;" border="0" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td nowrap="nowrap" width="133">
<p>DataSet</p>
</td>
<td nowrap="nowrap" width="92">
<p>Blosc&nbsp;&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p>Compression</p>
<p>Throughput (MB/S)&nbsp;&nbsp;</p>
</td>
<td nowrap="nowrap" width="125">
<p>Compression&nbsp;&nbsp;</p>
<p>Ratio</p>
</td>
<td nowrap="nowrap" width="92">
<p>Deflate&nbsp;&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p>Compression</p>
<p>Throughput (MB/S)&nbsp;&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p>Compression</p>
<p>&nbsp;Ratio</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[advwks_cust.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">220.3</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">2.8</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">33.7</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">4.4</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[advwks_fact.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">451.1</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">4.9</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">58.4</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">14.5</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[experian_fact.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">285.0</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">3.0</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">26.7</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">6.2</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[jitb_fact.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">290.7</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">2.2</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">16.9</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">3.9</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[mssales_fact.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">501.9</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">6.0</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">41.7</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">10.4</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[mssales_prod.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">530.0</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">5.8</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">50.5</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">10.1</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[skype_fact.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">213.0</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">2.1</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">15.9</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">4.0</p>
</td>
</tr>
<tr>
<td nowrap="nowrap" width="133">
<p>[synthetic_int.dat]</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="115">
<p align="right">359.4</p>
</td>
<td nowrap="nowrap" width="125">
<p align="right">3.9</p>
</td>
<td valign="bottom" nowrap="nowrap" width="92">
<p>&nbsp;</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">15.7</p>
</td>
<td nowrap="nowrap" width="94">
<p align="right">5.7</p>
</td>
</tr>
</tbody>
</table>
<p>&nbsp;</p>]]></content:encoded>
    </item>
    <item>
      <title>Preliminary findings to get good performance of SqlBulkCopy</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/preliminary-findings-to-get-good-performance-of-sqlbulkcopy</link>
      <pubDate>Thu, 27 Feb 2014 23:34:13 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2014/02/27/preliminary-findings-to-get-good-performance-of-sqlbulkcopy/</guid>
      <description><![CDATA[We want to develop a C# application which needs load data into local DB quickly, and found the...]]></description>
      <content:encoded><![CDATA[<p>We want to develop a C# application which needs load data into local DB quickly, and found the initially implemented SqlBulkCopy has poor performance (only 14 MB/S). Here are the findings when I try to improve the performance.</p>
<p>&nbsp;</p>
<p><strong>Test BaseLine:</strong></p>
<ul>
<li>Implement a mock data reader. The pure read throughput is several GB/S, which won&rsquo;t be the bottleneck for DB insertion.</li>
<ul>
<li>The schema is 4 columns of string, and each field is a Guid.</li>
<li>The data size is set as 1.6 GB with around 10 million rows.</li>
</ul>
<li>Use SqlBulkCopy.WriteToServerAsync(reader, token) to insert data, and hard code BatchSize as 1000.</li>
<li>The throughput is <strong>14 MB/S</strong>.&nbsp;</li>
</ul>
<p>&nbsp;</p>
<p><strong>Improvement 1:</strong></p>
<ul>
<li>Use the sync API in SqlBulkCopy instead of the async API.</li>
<li>The improved throughput is <strong>30 MB/S</strong>.</li>
<ul>
<li>The performance of sync API is better than the async one, which is same as my previous finding in SqlDataReader.</li>
</ul>
</ul>
<p>&nbsp;</p>
<p><strong>Improvement 2:</strong></p>
<ul>
<li>Use an adaptive BatchSize logic based on row size, instead of a hard coded value.</li>
<ul>
<li>My logic is to set the BatchSize as (8 MB)/(row size), where the row size can be estimated in our application.</li>
</ul>
<li>The further&nbsp;improved throughput is <strong>42 MB/S</strong>.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Improvement 3:</strong></p>
<ul>
<li>Set the target database as bulk-logged recovery mode, and use table lock for SqlBulkCopy. Refer to this article: <a href="https://msdn.microsoft.com/en-us/library/ms190422%28v=sql.105%29.aspx">https://msdn.microsoft.com/en-us/library/ms190422%28v=sql.105%29.aspx</a></li>
<li>The further improved throughput is <strong>60 MB/S</strong>.</li>
</ul>
<p>&nbsp;</p>
<p><strong>Row size and Performance:</strong></p>
<ul>
<li>Did some tests based on different schema. The performance can reach to <strong>60 MB/S</strong> if the row size is larger than 100 bytes.</li>
<li>For those very small rows (e.g. only contain 4 int value),&nbsp;the performance will be downgraded to <strong>35 MB/S</strong>.</li>
</ul>]]></content:encoded>
    </item>
    <item>
      <title>Study Notes of "Pattern-Oriented Design"</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/study-notes-of-pattern-oriented-design</link>
      <pubDate>Sun, 22 Dec 2013 05:28:59 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2013/12/22/study-notes-of-pattern-oriented-design/</guid>
      <description><![CDATA[Here are the study notes of my recently attended training "Pattern-Oriented Design". The lecturer is...]]></description>
      <content:encoded><![CDATA[<p>Here are the study notes of my recently attended training "Pattern-Oriented Design". The lecturer is Amir Kolsky.</p>
<ol>
<li value="1">Six Do's</li>
<ol>
<li value="1">Do the right thing&nbsp;&nbsp;</li>
<ol>
<li value="1">Process/PMs</li>
</ol>
<li>Do it right</li>
<ol>
<li value="1">Understanding</li>
</ol>
<li>Do it efficiently</li>
<li>Do it safely</li>
<li>Do it predictably (in estimated time)</li>
<ol>
<li value="1">The above three items is about design, which is developer's responsibility.</li>
</ol>
<li>Do it sustainably</li>
<ol>
<li value="1">Manager</li>
</ol></ol>
<li>Discussion: possible issues in a project</li>
<ol>
<li value="1">External dependencies</li>
<ol>
<li value="1">The dependencies change.</li>
</ol>
<li>Tight schedule</li>
<ol>
<li value="1">Scope change</li>
</ol>
<li>Requirement change/add</li>
<li>Quality problems</li>
<li>Overly complex design</li>
<li>Conclusion: most are caused by design change</li>
</ol>
<li>Discussion: the difference between procedural design and object oriented design</li>
<ol>
<li value="1">Procedure consider two concepts: behavior (procedure) and data</li>
<li>OO consider two concepts: entities and relationship, where each entity contains behavior and status&nbsp;(data).</li>
</ol>
<li>Three magic questions to know whether a design is good</li>
<ol>
<li value="1">How can I test it?&nbsp;</li>
<ol>
<li value="1">The easier the better</li>
</ol>
<li>What do I need to know (if change it)?</li>
<ol>
<li value="1">The less the better</li>
</ol>
<li>What do I need to do?</li>
<ol>
<li value="1">The less the better</li>
</ol></ol>
<li>Two questions to know whether an interface is good.</li>
<ol>
<li value="1">Assertive or Inquisitive?</li>
<li>Stable or Unstable?</li>
</ol>
<li>Most comments are not needed.&nbsp; Here is the six kinds of comments and only the sixth is valuable.</li>
<ol>
<li value="1">Not a comment.&nbsp;&nbsp;</li>
<ol>
<li value="1">e.g. author, time (version controller need to cover such information instead of comments)</li>
</ol>
<li>Useless&nbsp;&nbsp;</li>
<ol>
<li value="1">e.g. repeat the method name</li>
</ol>
<li>Fear&nbsp;&nbsp;</li>
<ol>
<li value="1">Comment the legacy code instead of deleting it.</li>
</ol>
<li>What</li>
<ol>
<li value="1">Explain what the code do. The good method name should explain.</li>
</ol>
<li>How</li>
<ol>
<li value="1">Explain how the code do. The clear code implementations should explain.</li>
</ol>
<li>Why</li>
<ol>
<li value="1">Only this is valuable as the code cannot show it.</li>
</ol></ol>
<li>Three steps to look into a design diagram</li>
<ol>
<li value="1">Look for relationship</li>
<ol>
<li value="1">Static:&nbsp;inheritance</li>
<li>Dynamic: interface</li>
</ol>
<li>Abstract class: variation</li>
<li>Interface</li>
<ol>
<li value="1">Stable or unstable</li>
</ol></ol>
<li>Three essential skills of a &nbsp;developer</li>
<ol>
<li value="1">Programming&nbsp;&nbsp; = &nbsp;Design&nbsp;&nbsp;&nbsp; -&gt; Implementation</li>
<li>Design&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Problem -&gt; Design</li>
<li>Refactor&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; = Design&nbsp;&nbsp;&nbsp; -&gt; Another Design</li>
</ol>
<li>The "Constants.cs" &nbsp;file is a bad thing</li>
<ol>
<li value="1">It has poor cohesion.</li>
<ol>
<li value="1">Break the second magic question: need to know the whole design of the system if need to change the file.</li>
</ol></ol>
<li>Criterions to measure code quality</li>
<ol>
<li value="1">Clarity&nbsp;&nbsp;</li>
<ol>
<li value="1">Good names. No need to explain code with comments.</li>
</ol>
<li>No Redundancy</li>
<ol>
<li value="1">Redundancy: A change to one thing would necessitate a similar change to all the redundant ones.</li>
</ol>
<li>Strong Cohesion</li>
<ol>
<li value="1">"One&nbsp;Responsibility in One Place"</li>
</ol>
<li>Intentional Coupling</li>
<ol>
<li value="1">The technical nature of the relationship between two entities.</li>
<li>Good coupling: intentional. Vs. Bad coupling: accidental.</li>
<li>Encapsulation aims to&nbsp;improve coupling and cohesion&nbsp;&nbsp;&nbsp;</li>
<ol>
<li value="1">Hidden things cannot be coupled to.&nbsp;</li>
<li>Cohesive issues are easier to hide.</li>
<li>Need a balance between encapsulation and redundancy.</li>
</ol></ol>
<li>Focus</li>
<ol>
<li value="1">The locality of responsibility.</li>
<li>Need a balance between focus and cohesion.</li>
</ol></ol>
<li>Context of a design:</li>
</ol>
<div>
<table border="1" cellspacing="0" cellpadding="0">
<tbody>
<tr>
<td>
<p>&nbsp;</p>
</td>
<td>
<p>Now</p>
</td>
<td>
<p>Future</p>
</td>
</tr>
<tr>
<td>
<p>Requirement</p>
</td>
<td>
<ul>
<ul>&nbsp;</ul>
<li>Functionality&nbsp;&nbsp;</li>
<li>Non-Functionality&nbsp;&nbsp;&nbsp;&nbsp;</li>
<ul>
<li>Performance&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>Usability&nbsp;&nbsp;&nbsp;&nbsp;</li>
<li>Security&nbsp;&nbsp;</li>
</ul>
</ul>
<p><span style="color: #008080;">Pay 100% work</span></p>
</td>
<td>
<ul>
<ul>&nbsp;&nbsp;&nbsp;</ul>
<li>Scalability</li>
<li>Extensibility&nbsp;&nbsp;&nbsp;</li>
<li>Reuse</li>
<ul>
<ul>&nbsp;&nbsp;</ul>
&nbsp;&nbsp;</ul>
</ul>
<p><span style="color: #008080;">Pay 100% work</span></p>
</td>
</tr>
<tr>
<td>
<p>Developer</p>
</td>
<td>
<ul>
<ul>&nbsp;&nbsp;
<ul>&nbsp;&nbsp;&nbsp;</ul>
</ul>
<li>Maintainability</li>
<ul>
<ul>&nbsp;&nbsp;&nbsp;&nbsp;</ul>
</ul>
</ul>
<p><span style="color: #008080;">Pay 100% work</span></p>
</td>
<td>
<ul>
<ul>&nbsp;&nbsp;
<ul>&nbsp;&nbsp;&nbsp;</ul>
</ul>
<li>Reuse</li>
<li>Extensibility</li>
<ul>
<ul>&nbsp;&nbsp;&nbsp;&nbsp;</ul>
</ul>
</ul>
<p><span style="color: #008080;">Pay 0% work (just need simple refactor if they become required, </span></p>
<p><span style="color: #008080;">as the code is well maintainable)</span></p>
</td>
</tr>
</tbody>
</table>
</div>
<ol>
<li value="12">There are two separated aspects to design a system. Never mixing the two aspects when doing design.</li>
<ol>
<li value="1">How the system runs?</li>
<ol>
<li value="1">Design the interface/relationship between objects.</li>
</ol>
<li>How to construct the system?</li>
<ol>
<li value="1">Factory is responsible for construction.</li>
</ol></ol>
<li>Design is about the problem, not the implementation.</li>
<li>Advice from the Gang of Four</li>
<ol>
<li value="1">Design to interfaces</li>
<li>Favor object delegation over class inheritance</li>
<li>Consider what should be variable in your design &hellip; and "encapsulate the concept that varies"</li>
</ol>
<li>The Strategy Pattern</li>
<ol>
<li value="1">We need a different behavior (variation) at different times (dynamic) for different clients (reuse) requesting the service.</li>
<li>GoF Intent: Define a family of algorithms, encapsulate each one, and make them interchangeable. Strategy lets the algorithm vary independently from clients that use it.</li>
</ol>
<li>Commonality-Variability Analysis</li>
<ol>
<li value="1">Commonality analysis is the search for common elements that helps us understand how family members are the same.</li>
<li>Those things that are found by commonality analysis can often become the abstract types.</li>
</ol>
<li>The Template Method Pattern</li>
<ol>
<li value="1">GoF Intent: Define the skeleton of an algorithm in an operation, deferring some steps to subclasses. Template Method lets subclasses redefine certain steps of an algorithm without changing the algorithm's structure.</li>
<li>E.g. Commonality: the steps of several algorithms. Variation: each specific algorithm</li>
</ol>
<li>The Bridge Pattern</li>
<ol>
<li value="1">GoF Intent: De-couple an abstraction from its implementation so that the two can vary independently.</li>
</ol>
<li>The Adapter Pattern</li>
<ol>
<li value="1">We need to change the interface of a class that has the right stuff but has the wrong interface.</li>
<li>GoF Intent: Convert the&nbsp;interface of a class into another interface clients expect. Adapter lets classes work together that couldn't otherwise because of incompatible interfaces.</li>
</ol>
<li>The Fa&ccedil;ade</li>
<ol>
<li value="1">We want to use a subset of the functionality of a complex system, or to simplify its interface, or to improve how it is used, or to provide OO access to a non-OO system.</li>
<li>GoF Intent: Provide a unified interface to a set of interfaces in a subsystem. Fa&ccedil;ade defines a higher-level interface that makes the subsystem easier to use.</li>
</ol>
<li>The Analysis Matrix</li>
<ol>
<li value="1">Motivation: Information overload:</li>
<ol>
<li value="1">More information than you need.</li>
<li>No good way to organize it.</li>
<li>No way to tell what is important.</li>
<li>No way to see what the cases are.</li>
</ol>
<li>Each column represents a given case, Each row is used to represent the concept that case is an example of. Build the matrix as we go.</li>
</ol>
<li>The Abstract Factory</li>
<ol>
<li value="1">We need to create families of objects for particular situations. That is, particular clients need particular sets of instantiations.</li>
<li>GoF Intent: Provide an interface for creating families of related or dependent objects without specifying their concrete classes.</li>
</ol>
<li>The Singleton Pattern</li>
<ol>
<li value="1">GoF Intent: Ensure a class only has one instance, and provide a global point of access to it.</li>
</ol>
<li>The Family of Proxy Patterns</li>
<ol>
<li value="1">We need to add functionality before or after accessing an object in such a way that the client object doesn't know it is talking to a different object.</li>
<li>GoF Intent: Provide a surrogate or placeholder for another object to control access to it.</li>
<li>Different kinds of proxy patterns</li>
<ol>
<li value="1">The Protection &nbsp;Proxy Pattern</li>
<li>The Cache Proxy Pattern</li>
<li>The Virtual Proxy Pattern</li>
<li>The Remote Proxy Pattern</li>
</ol></ol>
<li>The Decorator Pattern</li>
<ol>
<li value="1">GoF Intent: Attach additional responsibilities to an object dynamically. Decorators provide a flexible alternative to sub-classing for extending functionality.</li>
<li>A common example of decorator pattern is the Streaming IO: FileStream, MemoryStream, CompressionStream&hellip;</li>
</ol>
<li>Chain of Responsibility</li>
<ol>
<li value="1">Have a set of objects that can perform a task but the requester of the task does not want to know which one actually does it.</li>
</ol></ol>]]></content:encoded>
    </item>
    <item>
      <title>Azure Storage Blobs: the API DownloadToStream is always faster than OpenRead</title>
      <link>https://docs.microsoft.com/archive/blogs/yingqin/azure-storage-blobs-the-api-downloadtostream-is-always-faster-than-openread</link>
      <pubDate>Thu, 19 Dec 2013 02:04:14 GMT</pubDate>
      <dc:creator><![CDATA[Yingqin]]></dc:creator>
      <guid
        isPermaLink="false">https://blogs.msdn.microsoft.com/yingqin/2013/12/19/azure-storage-blobs-the-api-downloadtostream-is-always-faster-than-openread/</guid>
      <description><![CDATA[An interesting finding when using the Azure Storage is that the API ICloudBlob.DownloadToStream is...]]></description>
      <content:encoded><![CDATA[<p>An interesting finding when using the Azure Storage is that the API ICloudBlob.DownloadToStream is always&nbsp;over 35% faster than ICloudBlob.OpenRead, no matter the Blob is page Blob or block Blob. The Storage Client Library we&nbsp;use&nbsp;is 2.0.0.</p>
<p>Here is the different codes for the two APIs:</p>
<ul>
<li>DownloadToStream: blob.DownloadToStream(stream);</li>
<li>OpenRead:&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; var blobStream = blob.OpenRead();&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; blobStream.CopyTo(stream);</li>
</ul>
<p>The following table gives the test result of different APIs. The duration is the average of 10 times' running.</p>
<table style="width: 340px; height: 132px;" border="0" cellspacing="0" cellpadding="0"><colgroup><col width="132" /></colgroup><colgroup><col span="2" width="134" /></colgroup><colgroup><col width="64" /></colgroup>
<tbody>
<tr>
<td width="132" height="20">Data Size</td>
<td width="134">Open Read Stream (ms)</td>
<td width="134">Download To Stream (ms)</td>
<td width="64">Faster Ratio</td>
</tr>
<tr>
<td height="20">10 KB</td>
<td align="right">44.1</td>
<td align="right">26.5</td>
<td class="xl65" align="right">66.42%</td>
</tr>
<tr>
<td height="20">100 KB</td>
<td align="right">47.9</td>
<td align="right">24.3</td>
<td class="xl65" align="right">97.12%</td>
</tr>
<tr>
<td height="20">1 MB</td>
<td align="right">146.8</td>
<td align="right">106.1</td>
<td class="xl65" align="right">38.36%</td>
</tr>
<tr>
<td height="20">10 MB</td>
<td align="right">1088.5</td>
<td align="right">754.7</td>
<td class="xl65" align="right">44.23%</td>
</tr>
<tr>
<td height="20">100 MB</td>
<td align="right">11752.6</td>
<td align="right">7892.2</td>
<td class="xl65" align="right">48.91%</td>
</tr>
</tbody>
</table>]]></content:encoded>
    </item>
  </channel>
</rss>