当前位置: 首页 > news >正文

C# 中使用ValueTask优化异步方法

概要

我们在开发过程中,经常使用async的异步方法,但是有些时候,异步的方法中,可能包含一些同步的处理。本文主要介绍通过ValueTask这个struct,优化异步处理的方法性能。

代码及实现

有些时候我们会缓存一些数据在内存中,这些数据因为不经常改变,所以并不需要每次都要从后台数据库中获取。

例如下面的代码:

 private static List<Branch> _branches;public async Task<List<Branch>> getBranches(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();}   }return _branches;
}

在一个银行App相关的系统中,我们将分行的基本信息缓存在内存中,方便其它方法调用。

上面的代码有一个问题,无论我们的缓存是否命中,都会以Task<List>的形式返回。也就是说Runtime需要为返回Task相关的内容分配内存空间;如果缓存命中,意味着该方法仅仅是执行同步操作,实际上只是一个同步操作。

如果以Task<List>作为返回值,对于同步操作而言,完全是在浪费系统资源。Task是一个类,这就意味着只要我们要使用该类,就必须创建对象,然后在通过GC收集。

对于一些高吞吐量,高并发的站点,如果可以对其进行适当优化,可以节约大量资源。

ValueTask 解决方法

在.Net Core .2.0中,引入一个结构体类型 ValueTask, 用于处理async方法中,同步和异步返回并存的情况。

因为其只是一个结构体,它并不需要像Task那样去创建对象,再被GC收集。但是它却可以包裹TResult或Task,作为async方法的返回值。

我们将上面的代码进行修改,将Task替换成ValueTask即可

private static List<Branch> _branches;
public async ValueTask<List<Branch>> getBranchesByTaskValue(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();return _branches;}                 }return _branches;
}

我们用Benchmark测试上述两个方法的性能。
在这里插入图片描述

从测试结果上看,ValueTask作为返回值,消耗时间增加了约27%,但是内存消耗几乎可以忽略不计。

全部代码请参考附录

附录

Programs.cs

using System.Diagnostics;
using System.Globalization;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Net.Mail;
using System.ComponentModel.Design.Serialization;
using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.EntityFrameworkCore;
using System.Linq;
using System.Collections.Generic;
using BenchmarkDotNet.Running;
using BenchmarkDotNet.Attributes;
using BenchmarkDotNet.Diagnosers;
namespace IQueryableIEnumerable
{[MemoryDiagnoser]public class Programs{[Benchmark]public async Task getBranches(){TaskValueTest task = new TaskValueTest();for(var i=0;i<5;++i){await task.getBranches();}}[Benchmark]public async Task getBranchesByValueTask(){TaskValueTest task = new TaskValueTest();for(var i=0;i<5;++i){await task.getBranchesByTaskValue();}}public static void Main(string[] args){var summary = BenchmarkRunner.Run<Programs>();  }  }
}

TaskValueTest.cs

namespace IQueryableIEnumerable
{using System;using System.Threading;using System.Threading.Tasks;using Microsoft.EntityFrameworkCore;using System.Linq;using System.Collections.Generic;using BenchmarkDotNet.Running;using BenchmarkDotNet.Attributes;using BenchmarkDotNet.Diagnosers;public class TaskValueTest{private static List<Branch> _branches;private static List<Branch> _branches2;public async ValueTask<List<Branch>> getBranchesByTaskValue(){if (_branches is null){using (var context = new BankContext()){_branches = await context.Branches.ToListAsync();}                 }return _branches;}public async Task<List<Branch>> getBranches(){if (_branches2 is null){using (var context = new BankContext()){_branches2 = await context.Branches.ToListAsync();}   }return _branches2;}}
}

相关文章:

C# 中使用ValueTask优化异步方法

概要 我们在开发过程中&#xff0c;经常使用async的异步方法&#xff0c;但是有些时候&#xff0c;异步的方法中&#xff0c;可能包含一些同步的处理。本文主要介绍通过ValueTask这个struct&#xff0c;优化异步处理的方法性能。 代码及实现 有些时候我们会缓存一些数据在内…...

KVM创建新的虚拟机(图形化)

1.启动kvm管理器 [rootlocalhost ~]# virt-manager2.点击创建虚拟机 3.选择所需os安装镜像 4.选择合适的内存大小和CPU 5.创建所需磁盘 6.命名创建的虚拟机...

正则表达式在格式校验中的应用以及包装类的重要性

文章目录 正则表达式&#xff1a;做格式校验包装类&#xff1a;在基本数据类型与引用数据类型间的桥梁总结 在现代IT技术岗位的面试中&#xff0c;掌握正则表达式的应用以及理解包装类的重要性是非常有益的。这篇博客将围绕这两个主题展开&#xff0c;帮助读者更好地面对面试挑…...

Docker使用之java项目工程的部署

同样本文的基础建立在已在目标服务器&#xff08;以linux为示例&#xff09;上安装了docker&#xff0c;安装教程请移步度娘 若容器存在请先停止&#xff0c;在删除&#xff0c;然后删除镜像重新编译 //停止容器 sudo docker stop datatransfer//删除容器 sudo docker rm dat…...

3ds Max如何进行合成的反射光泽通道渲染

推荐&#xff1a; NSDT场景编辑器 助你快速搭建可二次开发的3D应用场景 1. 准备场景 步骤 1 打开 3ds Max。smart_phone.max打开已 随教程提供。 打开 3ds Max 步骤 2 按 M 打开材质编辑器。选择空材料 槽。单击漫射通道。它将打开材质/贴图浏览器窗口。选择位图&#xff0…...

114、Spring AOP是如何实现的?它和AspectJ有什么区别?

Spring AOP是如何实现的?它和AspectJ有什么区别? 一、AOP的理解1、spring aop:动态代理实现2、spring aop 和 AspectJ的区别3、小图一、AOP的理解 其实,AOP只是一种编程思想,表示面向切面编程,如果想实现这种思想,可以使用动态代理啊,第三方的框架 AspectJ啊等等。 1…...

正则表达式速通

简介 正则表达式&#xff0c;我们可以看作通配符的增强版&#xff0c;可以帮我们匹配指定规则的字符串&#xff0c;在计算机中应用广泛&#xff0c;比如说爬虫、网站的登录表单等。 原视频&#xff1a;https://www.bilibili.com/video/BV1da4y1p7iZ 学习正则表达式的常用工具…...

数据可视化(5)热力图及箱型图

1.热力图 #基本热力图 #imshow&#xff08;x&#xff09; #x&#xff0c;数据 x[[1,2],[3,4],[5,6],[7,8],[9,10]] plt.imshow(x) plt.show() #使用热力图分析学生的成绩 dfpd.read_excel(学生成绩表.xlsx) #:表示行号 截取数学到英语的列数 xdf.loc[:,"数学":英语].…...

React 组件通信-全面解析

父子组件通信 // 导入 import { useState } from "react";import "./App.scss"; import { defaultTodos } from "./components/module/contentData";// 子组件 const Module ({ id, done, text, onToggle, onDelData }) > {return (<div…...

“深入理解Spring Boot:快速构建微服务架构的利器“

标题&#xff1a;深入理解Spring Boot&#xff1a;快速构建微服务架构的利器 摘要&#xff1a;Spring Boot是一种基于Spring框架的开源项目&#xff0c;它通过自动化配置和约定优于配置的原则&#xff0c;使得开发者能够快速构建微服务架构。本文将深入介绍Spring Boot的特点和…...

SpringBoot超级详解

1.父工程的父工程 在父工程的父工程中的核心依赖&#xff0c;专门用来版本管理的 版本管理。 2.父工程 资源过滤问题&#xff0c;都帮解决了&#xff0c;什么配置文件&#xff0c;都已经配置好了&#xff0c;资源过滤问题是帮助&#xff0c;过滤解决让静态资源文件能够过滤到…...

手机的python怎么运行文件,python在手机上怎么运行

大家好&#xff0c;小编来为大家解答以下问题&#xff0c;手机上的python怎么运行程序&#xff0c;手机的python怎么运行文件&#xff0c;今天让我们一起来看看吧&#xff01; 1、python程序怎么在手机上运行 python语言应用很广泛&#xff0c;自己也很喜欢使用它&#xff0c;其…...

RBAC三级树状菜单实现(从前端到后端)未完待续

1、表格设计 RBAC 2、前端路由 根据不同的用户id显示不同的菜单。 根据路由 3、多级菜单 展示所有权限&#xff0c;并且根据当前用户id展示它所属的角色的所有菜单。 前端树状展示 思路&#xff1a; 后端&#xff1a;传给前端map&#xff0c;map里1个是所有菜单&am…...

牛客网Verilog刷题——VL41

牛客网Verilog刷题——VL41 题目答案 题目 请设计一个可以实现任意小数分频的时钟分频器&#xff0c;比如说8.7分频的时钟信号&#xff0c;注意rst为低电平复位。提示&#xff1a;其实本质上是一个简单的数学问题&#xff0c;即如何使用最小公倍数得到时钟周期的分别频比。设小…...

大整数截取解决方法(java代码)

大整数截取解决方法&#xff08;java代码&#xff09; 描述输入描述输出描述输入示例输出示例前置知识&#xff1a;代码 解题思路来自这个博客&#xff1a;简单^不简单 https://blog.csdn.net/younger_china/article/details/126376374 描述 花花有一个很珍贵的数字串&#xf…...

Spring Boot使用@Async实现异步调用:自定义线程池

一、定义线程池 第一步&#xff0c;先在Spring Boot主类中定义一个线程池&#xff0c;比如&#xff1a; SpringBootApplication public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}EnableAsyncConfigurat…...

GFS 分布式文件系统

目录 一、GlusterFS 概述 1.2&#xff0e;GlusterFS特点 1.3&#xff0e;GlusterFS 术语 1.4GlusterFS 的工作流程 二、GlusterFS的卷类型 2.1分布式卷&#xff08;Distribute volume&#xff09; 2.1.1特点 2.2条带卷&#xff08;Stripe volume&#xff09; 2.2.1条…...

PHP-mysql学习笔记

如题 记录发送emoji数据无法正常显示的问题PHPMysql 记录 发送emoji数据无法正常显示的问题 问题描述 前端发送关于emoji的表情数据给php,php写入mysql php接收到了数据,但无法写入写入过后返回前端无法正常显示 PHP 在对应的pdd函数中设置字符集为utf8mb4 Mysql emoji数…...

AI技术快讯:清华开源ChatGLM2双语对话语言模型

ChatGLM2-6B是一个开源项目&#xff0c;提供了ChatGLM2-6B模型的代码和资源。根据提供的搜索结果&#xff0c;以下是对该项目的介绍&#xff1a; 论文&#xff1a;https://arxiv.org/pdf/2103.10360.pdf ChatGLM2-6B是一个开源的双语对话语言模型&#xff0c;是ChatGLM-6B模…...

网络基础知识

1、什么是链接? 链接是指两个设备之间的连接。它包括用于一个设备能够与另一个设备通信的电缆类型和协议。 2、OSI 参考模型的层次是什么? 有 7 个 OSI 层&#xff1a;物理层&#xff0c;数据链路层&#xff0c;网络层&#xff0c;传输层&#xff0c;会话层&#xff0c;表…...

RestClient

什么是RestClient RestClient 是 Elasticsearch 官方提供的 Java 低级 REST 客户端&#xff0c;它允许HTTP与Elasticsearch 集群通信&#xff0c;而无需处理 JSON 序列化/反序列化等底层细节。它是 Elasticsearch Java API 客户端的基础。 RestClient 主要特点 轻量级&#xff…...

AI-调查研究-01-正念冥想有用吗?对健康的影响及科学指南

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

FastAPI 教程:从入门到实践

FastAPI 是一个现代、快速&#xff08;高性能&#xff09;的 Web 框架&#xff0c;用于构建 API&#xff0c;支持 Python 3.6。它基于标准 Python 类型提示&#xff0c;易于学习且功能强大。以下是一个完整的 FastAPI 入门教程&#xff0c;涵盖从环境搭建到创建并运行一个简单的…...

Frozen-Flask :将 Flask 应用“冻结”为静态文件

Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是&#xff1a;将一个 Flask Web 应用生成成纯静态 HTML 文件&#xff0c;从而可以部署到静态网站托管服务上&#xff0c;如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...

Psychopy音频的使用

Psychopy音频的使用 本文主要解决以下问题&#xff1a; 指定音频引擎与设备&#xff1b;播放音频文件 本文所使用的环境&#xff1a; Python3.10 numpy2.2.6 psychopy2025.1.1 psychtoolbox3.0.19.14 一、音频配置 Psychopy文档链接为Sound - for audio playback — Psy…...

JUC笔记(上)-复习 涉及死锁 volatile synchronized CAS 原子操作

一、上下文切换 即使单核CPU也可以进行多线程执行代码&#xff0c;CPU会给每个线程分配CPU时间片来实现这个机制。时间片非常短&#xff0c;所以CPU会不断地切换线程执行&#xff0c;从而让我们感觉多个线程是同时执行的。时间片一般是十几毫秒(ms)。通过时间片分配算法执行。…...

是否存在路径(FIFOBB算法)

题目描述 一个具有 n 个顶点e条边的无向图&#xff0c;该图顶点的编号依次为0到n-1且不存在顶点与自身相连的边。请使用FIFOBB算法编写程序&#xff0c;确定是否存在从顶点 source到顶点 destination的路径。 输入 第一行两个整数&#xff0c;分别表示n 和 e 的值&#xff08;1…...

在Ubuntu24上采用Wine打开SourceInsight

1. 安装wine sudo apt install wine 2. 安装32位库支持,SourceInsight是32位程序 sudo dpkg --add-architecture i386 sudo apt update sudo apt install wine32:i386 3. 验证安装 wine --version 4. 安装必要的字体和库(解决显示问题) sudo apt install fonts-wqy…...

LabVIEW双光子成像系统技术

双光子成像技术的核心特性 双光子成像通过双低能量光子协同激发机制&#xff0c;展现出显著的技术优势&#xff1a; 深层组织穿透能力&#xff1a;适用于活体组织深度成像 高分辨率观测性能&#xff1a;满足微观结构的精细研究需求 低光毒性特点&#xff1a;减少对样本的损伤…...