BlockBlobClient的GetBlockById扩展方法可优化提升性能吗?
BlockBlobClient扩展方法GetBlockByIdAsync的性能优化方案
核心优化点
- 消除重复遍历:原代码两次遍历区块列表查找目标ID,优化后一次遍历同时完成目标区块定位与偏移量计算,避免冗余操作。
- 修正空值判断逻辑:直接判断目标区块是否为null,比判断
Name字段更严谨,杜绝潜在的空引用异常。 - 精准获取区块数据:调用
GetBlockListAsync时明确指定BlockListTypes.Committed,只返回已提交区块,减少不必要的数据传输。 - 简化偏移量计算:在遍历查找目标区块的过程中直接累加前置区块大小,省去单独计算索引再循环的步骤。
- 序列化性能优化:允许传入重用的
JsonSerializerOptions,避免频繁创建配置对象的开销,同时使用异步反序列化保持流程一致性。
优化后的代码
public static async Task<T> GetBlockByIdAsync<T>(this BlockBlobClient blockBlobClient, string blockId, CancellationToken cancellationToken, JsonSerializerOptions? serializerOptions = null) { // 仅获取已提交区块,减少返回数据量 var blockListResponse = await blockBlobClient.GetBlockListAsync(BlockListTypes.Committed, cancellationToken: cancellationToken); var committedBlocks = blockListResponse.Value.CommittedBlocks; BlockItem? targetBlock = null; long offset = 0; foreach (var block in committedBlocks) { if (block.Name == blockId) { targetBlock = block; break; } offset += block.SizeLong; } if (targetBlock == null) { throw new InvalidOperationException($"Could not find BlockId {blockId}"); } var downloadOptions = new BlobDownloadOptions { Range = new HttpRange(offset, targetBlock.SizeLong) }; using var downloadResponse = await blockBlobClient.DownloadStreamingAsync(downloadOptions, cancellationToken); using var contentStream = downloadResponse.Value.Content; // 优先使用传入的序列化配置,提升反序列化性能 return await JsonSerializer.DeserializeAsync<T>(contentStream, serializerOptions ?? new JsonSerializerOptions(), cancellationToken); }
额外建议
如果存在高频重复查询场景,可以将区块ID与偏移量的映射关系缓存起来(比如用MemoryCache),避免每次调用都重新获取区块列表。注意在区块更新时需要及时清空对应缓存,保证数据一致性。
内容的提问来源于stack exchange,提问作者Antonio Carlos
相关产品推荐
相关产品推荐

