Skip to content
This repository was archived by the owner on Aug 1, 2024. It is now read-only.

Commit d11b34b

Browse files
authored
Merge pull request #581 from danielmarbach/performance-breaking
Avoid Task.Run and Factory.StartNew with async
2 parents d387767 + 20ed414 commit d11b34b

31 files changed

+1199
-1404
lines changed

Lib/AspNet/Microsoft.WindowsAzure.Storage/Extensions/StreamExtension.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ public static Stream AsStreamForWrite(this Stream stream)
7171
/// <param name="stream">input stream</param>
7272
/// <param name="buffer">buffer to write to the stream</param>
7373
/// <returns>Async task</returns>
74-
public static async Task WriteAsync(this Stream stream, byte[] buffer)
74+
public static Task WriteAsync(this Stream stream, byte[] buffer)
7575
{
76-
await stream.WriteAsync(buffer, 0, buffer.Length);
76+
return stream.WriteAsync(buffer, 0, buffer.Length);
7777
}
7878

7979
/// <summary>

Lib/ClassLibraryCommon/Table/Protocol/HttpResponseAdapterMessage.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ namespace Microsoft.WindowsAzure.Storage.Table.Protocol
2727
internal class HttpResponseAdapterMessage : IODataResponseMessage
2828
{
2929
private HttpWebResponse resp = null;
30-
private Stream str = null;
30+
private Task<Stream> strAsCachedTask = null;
3131
private string responseContentType = null;
3232

3333
public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str)
@@ -38,13 +38,13 @@ public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str)
3838
public HttpResponseAdapterMessage(HttpWebResponse resp, Stream str, string responseContentType)
3939
{
4040
this.resp = resp;
41-
this.str = str;
41+
this.strAsCachedTask = Task.FromResult(str);
4242
this.responseContentType = responseContentType;
4343
}
4444

4545
public Task<Stream> GetStreamAsync()
4646
{
47-
return Task.Factory.StartNew(() => this.str);
47+
return this.strAsCachedTask;
4848
}
4949

5050
public string GetHeader(string headerName)
@@ -73,7 +73,7 @@ public string GetHeader(string headerName)
7373

7474
public Stream GetStream()
7575
{
76-
return this.str;
76+
return this.strAsCachedTask.Result; // safe since completed task and avoids additional field for stream
7777
}
7878

7979
public IEnumerable<KeyValuePair<string, string>> Headers

Lib/Common/Core/MultiBufferMemoryStream.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -572,7 +572,7 @@ public async Task FastCopyToAsync(Stream destination, DateTime? expiryTime)
572572

573573
// Copy the block
574574
int blockReadLength = (int)Math.Min(leftToRead, currentBlock.Count);
575-
await destination.WriteAsync(currentBlock.Array, currentBlock.Offset, blockReadLength);
575+
await destination.WriteAsync(currentBlock.Array, currentBlock.Offset, blockReadLength).ConfigureAwait(false);
576576

577577
this.AdvancePosition(ref leftToRead, blockReadLength);
578578
}

Lib/Common/Core/NullType.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
// </copyright>
1616
//-----------------------------------------------------------------------
1717

18+
using System.Threading.Tasks;
19+
1820
namespace Microsoft.WindowsAzure.Storage.Core
1921
{
2022
/// <summary>
@@ -27,6 +29,11 @@ public sealed class NullType
2729
/// </summary>
2830
internal static readonly NullType Value = new NullType();
2931

32+
/// <summary>
33+
/// Represents a no-return from a task.
34+
/// </summary>
35+
internal static readonly Task<NullType> ValueTask = Task.FromResult(Value);
36+
3037
/// <summary>
3138
/// Prevents a default instance of the <see cref="NullType"/> class from being created.
3239
/// </summary>

Lib/Common/Core/Util/Exceptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ internal async static Task<StorageException> PopulateStorageExceptionFromHttpRes
6868
}
6969
else
7070
{
71-
currentResult.ExtendedErrorInformation = await StorageExtendedErrorInformation.ReadFromStreamAsync(errStream.AsInputStream());
71+
currentResult.ExtendedErrorInformation = await StorageExtendedErrorInformation.ReadFromStreamAsync(errStream.AsInputStream()).ConfigureAwait(false);
7272
}
7373
}
7474
catch (Exception)

Lib/Common/StorageExtendedErrorInformation.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,9 +77,9 @@ public static StorageExtendedErrorInformation ReadFromStream(IInputStream inputS
7777
return ReadFromStream(inputStream.AsStreamForRead());
7878
}
7979

80-
public static async Task<StorageExtendedErrorInformation> ReadFromStreamAsync(IInputStream inputStream)
80+
public static Task<StorageExtendedErrorInformation> ReadFromStreamAsync(IInputStream inputStream)
8181
{
82-
return await ReadFromStreamAsync(inputStream.AsStreamForRead());
82+
return ReadFromStreamAsync(inputStream.AsStreamForRead());
8383
}
8484
#endif
8585

@@ -139,7 +139,7 @@ public static async Task<StorageExtendedErrorInformation> ReadFromStreamAsync(St
139139

140140
using (XmlReader reader = XmlReader.Create(inputStream, settings))
141141
{
142-
await reader.ReadAsync();
142+
await reader.ReadAsync().ConfigureAwait(false);
143143
extendedErrorInfo.ReadXml(reader);
144144
}
145145

Lib/WindowsDesktop/Table/DataServices/DataServicesResponseAdapterMessage.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ namespace Microsoft.WindowsAzure.Storage.Table.DataServices
2626
internal class DataServicesResponseAdapterMessage : IODataResponseMessage
2727
{
2828
private IDictionary<string, string> responseHeaders;
29-
private Stream inputStream = null;
29+
private Task<Stream> inputStreamAsCachedTask = null;
3030
private string responseContentType = null;
3131

3232
public DataServicesResponseAdapterMessage(Dictionary<string, string> responseHeaders, Stream inputStream)
@@ -37,13 +37,13 @@ public DataServicesResponseAdapterMessage(Dictionary<string, string> responseHea
3737
public DataServicesResponseAdapterMessage(IDictionary<string, string> responseHeaders, Stream inputStream, string responseContentType)
3838
{
3939
this.responseHeaders = responseHeaders;
40-
this.inputStream = inputStream;
40+
this.inputStreamAsCachedTask = Task.FromResult(inputStream);
4141
this.responseContentType = responseContentType;
4242
}
4343

4444
public Task<Stream> GetStreamAsync()
4545
{
46-
return Task.Factory.StartNew(() => this.inputStream);
46+
return inputStreamAsCachedTask;
4747
}
4848

4949
public string GetHeader(string headerName)
@@ -77,7 +77,7 @@ public string GetHeader(string headerName)
7777

7878
public Stream GetStream()
7979
{
80-
return this.inputStream;
80+
return this.inputStreamAsCachedTask.Result; // safe since completed task and avoids additional field for stream
8181
}
8282

8383
public IEnumerable<KeyValuePair<string, string>> Headers

Lib/WindowsRuntime/Blob/BlobReadStream.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ public override int Read(byte[] buffer, int offset, int count)
9595
/// <param name="count">The maximum number of bytes to read.</param>
9696
/// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
9797
/// <returns>A task that represents the asynchronous read operation.</returns>
98-
public override async Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
98+
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
9999
{
100100
CommonUtility.AssertNotNull("buffer", buffer);
101101
CommonUtility.AssertInBounds("offset", offset, 0, buffer.Length);
@@ -108,16 +108,16 @@ public override async Task<int> ReadAsync(byte[] buffer, int offset, int count,
108108

109109
if ((this.currentOffset == this.Length) || (count == 0))
110110
{
111-
return 0;
111+
return Task.FromResult(0);
112112
}
113113

114114
int readCount = this.ConsumeBuffer(buffer, offset, count);
115115
if (readCount > 0)
116116
{
117-
return readCount;
117+
return Task.FromResult(readCount);
118118
}
119119

120-
return await this.DispatchReadAsync(buffer, offset, count);
120+
return this.DispatchReadAsync(buffer, offset, count);
121121
}
122122

123123
/// <summary>
@@ -140,7 +140,7 @@ await this.blob.DownloadRangeToStreamAsync(
140140
this.GetReadSize(),
141141
this.accessCondition,
142142
this.options,
143-
this.operationContext);
143+
this.operationContext).ConfigureAwait(false);
144144

145145
this.internalBuffer.Seek(0, SeekOrigin.Begin);
146146
return this.ConsumeBuffer(buffer, offset, count);

Lib/WindowsRuntime/Blob/BlobWriteStream.cs

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ public override async Task WriteAsync(byte[] buffer, int offset, int count, Canc
158158

159159
if (bytesToWrite == maxBytesToWrite)
160160
{
161-
await this.DispatchWriteAsync();
161+
await this.DispatchWriteAsync().ConfigureAwait(false);
162162
}
163163
}
164164
}
@@ -188,7 +188,7 @@ public override async Task FlushAsync(CancellationToken cancellationToken)
188188
throw new InvalidOperationException(SR.BlobStreamAlreadyCommitted);
189189
}
190190

191-
await this.DispatchWriteAsync();
191+
await this.DispatchWriteAsync().ConfigureAwait(false);
192192
await Task.Run(() => this.noPendingWritesEvent.Wait(), cancellationToken);
193193

194194
if (this.lastException != null)
@@ -225,7 +225,7 @@ protected override void Dispose(bool disposing)
225225
/// <returns>A task that represents the asynchronous commit operation.</returns>
226226
public override async Task CommitAsync()
227227
{
228-
await this.FlushAsync();
228+
await this.FlushAsync().ConfigureAwait(false);
229229
this.committed = true;
230230

231231
try
@@ -237,14 +237,14 @@ public override async Task CommitAsync()
237237
this.blockBlob.Properties.ContentMD5 = this.blobMD5.ComputeHash();
238238
}
239239

240-
await this.blockBlob.PutBlockListAsync(this.blockList, this.accessCondition, this.options, this.operationContext);
240+
await this.blockBlob.PutBlockListAsync(this.blockList, this.accessCondition, this.options, this.operationContext).ConfigureAwait(false);
241241
}
242242
else
243243
{
244244
if (this.blobMD5 != null)
245245
{
246246
this.Blob.Properties.ContentMD5 = this.blobMD5.ComputeHash();
247-
await this.Blob.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext);
247+
await this.Blob.SetPropertiesAsync(this.accessCondition, this.options, this.operationContext).ConfigureAwait(false);
248248
}
249249
}
250250
}
@@ -282,7 +282,7 @@ private async Task DispatchWriteAsync()
282282
{
283283
string blockId = this.GetCurrentBlockId();
284284
this.blockList.Add(blockId);
285-
await this.WriteBlockAsync(bufferToUpload, blockId, bufferMD5);
285+
await this.WriteBlockAsync(bufferToUpload, blockId, bufferMD5).ConfigureAwait(false);
286286
}
287287
else if (this.pageBlob != null)
288288
{
@@ -294,7 +294,7 @@ private async Task DispatchWriteAsync()
294294

295295
long offset = this.currentBlobOffset;
296296
this.currentBlobOffset += bufferToUpload.Length;
297-
await this.WritePagesAsync(bufferToUpload, offset, bufferMD5);
297+
await this.WritePagesAsync(bufferToUpload, offset, bufferMD5).ConfigureAwait(false);
298298
}
299299
else
300300
{
@@ -310,7 +310,7 @@ private async Task DispatchWriteAsync()
310310
throw this.lastException;
311311
}
312312

313-
await this.WriteAppendBlockAsync(bufferToUpload, offset, bufferMD5);
313+
await this.WriteAppendBlockAsync(bufferToUpload, offset, bufferMD5).ConfigureAwait(false);
314314
}
315315
}
316316

@@ -324,7 +324,7 @@ private async Task DispatchWriteAsync()
324324
private async Task WriteBlockAsync(Stream blockData, string blockId, string blockMD5)
325325
{
326326
this.noPendingWritesEvent.Increment();
327-
await this.parallelOperationSemaphore.WaitAsync();
327+
await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false);
328328
Task putBlockTask = this.blockBlob.PutBlockAsync(blockId, blockData, blockMD5, this.accessCondition, this.options, this.operationContext).ContinueWith(task =>
329329
{
330330
if (task.Exception != null)
@@ -347,7 +347,7 @@ private async Task WriteBlockAsync(Stream blockData, string blockId, string bloc
347347
private async Task WritePagesAsync(Stream pageData, long offset, string contentMD5)
348348
{
349349
this.noPendingWritesEvent.Increment();
350-
await this.parallelOperationSemaphore.WaitAsync();
350+
await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false);
351351
Task writePagesTask = this.pageBlob.WritePagesAsync(pageData, offset, contentMD5, this.accessCondition, this.options, this.operationContext).ContinueWith(task =>
352352
{
353353
if (task.Exception != null)
@@ -372,7 +372,7 @@ private async Task WritePagesAsync(Stream pageData, long offset, string contentM
372372
private async Task WriteAppendBlockAsync(Stream blockData, long offset, string blockMD5)
373373
{
374374
this.noPendingWritesEvent.Increment();
375-
await this.parallelOperationSemaphore.WaitAsync();
375+
await this.parallelOperationSemaphore.WaitAsync().ConfigureAwait(false);
376376

377377
this.accessCondition.IfAppendPositionEqual = offset;
378378

0 commit comments

Comments
 (0)