英文:
My extension method can get better? BlockBlobClient GetBlockById dotnet
问题
我已经为BlockBlobClient
创建了一个扩展方法,用于根据块ID获取特定块,并且我想知道是否可以调整此代码片段以提高性能或其他方面的优化。
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
var blockList = blockListResponse.Value.CommittedBlocks.ToList();
var currentBlock = blockList.FirstOrDefault(a => a.Name == blockId);
if (currentBlock.Name == null)
{
throw new InvalidOperationException($"Could not find BlockId {blockId}");
}
var length = currentBlock.SizeLong;
var index = blockList.FindIndex(a => a.Name == blockId);
var offset = 0L;
for (var i = 0; i < index; i++)
{
offset += blockList[i].SizeLong;
}
var options = new BlobDownloadOptions()
{
Range = new HttpRange(offset, length)
};
var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);
return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
英文:
I've made an extension method for the BlockBlobClient, to get a specific block by block id, and I want to know if this code snippet can be tweaked to increase performance/other things
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
var blockList = blockListResponse.Value.CommittedBlocks.ToList();
var currentBlock = blockList.FirstOrDefault(a => a.Name == blockId);
if (currentBlock.Name == null)
{
throw new InvalidOperationException($"Could not find BlockId {blockId}");
}
var length = currentBlock.SizeLong;
var index = blockList.FindIndex(a => a.Name == blockId);
var offset = 0L;
for (var i = 0; i < index; i++)
{
offset += blockList[i].SizeLong;
}
var options = new BlobDownloadOptions()
{
Range = new HttpRange(offset, length)
};
var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);
return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
答案1
得分: 2
以下是代码部分的翻译:
-
blockList.FirstOrDefault(a => a.Name == blockId)
- 用第一个满足条件的元素,其Name等于blockId的元素。
-
blockList.FindIndex(a => a.Name == blockId)
- 找到第一个满足条件的元素索引,其Name等于blockId的元素。
-
for (var i = 0; i < index; i++)
- 使用循环,从0遍历到index。
这是你提供的代码的翻译:
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
var blockList = blockListResponse.Value.CommittedBlocks.ToList();
var length = 0L;
var offset = 0L;
// 遍历所有块,直到找到所需的块。
foreach (var block in blockList){
if (block.Name == blockId){
length = block.SizeLong;
break;
}
// 如果尚未找到所需的块,则更新偏移量。
offset += block.SizeLong;
}
// 检查是否找到了所需的块。
if (length == 0)
{
throw new InvalidOperationException($"无法找到块标识 {blockId}");
}
var options = new BlobDownloadOptions()
{
Range = new HttpRange(offset, length)
};
var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);
return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
“CAVEAT”部分表示注意事项,提醒可能存在代码错误但思路正确。在“UPDATE”部分中,作者提到可能进一步提高效率的方法。
英文:
The only thing that really stands out is the multiple iteration (3 times) of blockList
.
blockList.FirstOrDefault(a => a.Name == blockId)
blockList.FindIndex(a => a.Name == blockId)
for (var i = 0; i < index; i++)
You can do this with a single iteration, something like this.
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
var blockList = blockListResponse.Value.CommittedBlocks.ToList();
var length = 0L;
var offset = 0L;
// iterate over all blocks until we find the block we want.
foreach (var block in blockList){
if (block.Name == blockId){
length = block.SizeLong;
break;
}
// We haven't found the block we want yet so update the offset.
offset += block.SizeLong;
}
// Check if we found the block we were looking for.
if (length == 0)
{
throw new InvalidOperationException($"Could not find BlockId {blockId}");
}
var options = new BlobDownloadOptions()
{
Range = new HttpRange(offset, length)
};
var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);
return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
CAVEAT I haven't run this code locally or even tried to compile it so there may be errors but the idea is sound.
UPDATE There was an iteration that I missed: blockListResponse.Value.CommittedBlocks.ToList();
Granted, calling to list prevents any repeated calls to CommittedBlocks
but this could be even more efficient.
Assuming blockListResponse.Value.CommittedBlocks
returns IEnumerable<T>` you could even remove this...
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken)
{
var blockListResponse = await blockBlobClient.GetBlockListAsync(cancellationToken: cancellationToken);
var blockList = blockListResponse.Value.CommittedBlocks;
var length = 0L;
var offset = 0L;
// iterate over all blocks until we find the block we want.
var blockListEnumerator = blockList.GetEnumerator();
while (blockListEnumerator.MoveNext())
{
var block = blockListEnumerator.Current as BlobBlock;
if (block.Name == blockId){
length = block.SizeLong;
break;
}
// We haven't found the block we want yet so update the offset.
offset += block.SizeLong;
}
// Check if we found the block we were looking for.
if (length == 0)
{
throw new InvalidOperationException($"Could not find BlockId {blockId}");
}
var options = new BlobDownloadOptions()
{
Range = new HttpRange(offset, length)
};
var blockInfo = await blockBlobClient.DownloadStreamingAsync(options, cancellationToken);
return JsonSerializer.Deserialize<T>(blockInfo.Value.Content);
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论