2024年6月

前言

RocketMQ 是阿里巴巴在 2012 年开源的分布式消息中间件,目前已经捐赠给 Apache 软件基金会,并于 2017 年 9 月 25 日成为 Apache 的顶级项目。

作为经历过多次阿里巴巴双十一这种“超级工程”的洗礼并有稳定出色表现的国产中间件,以其高性能、低延时和高可靠等特性近年来已经也被越来越多的国内企业使用。


一、初识 RocketMQ

2011 年初,Linkin 开源了 Kafka 这个优秀的消息中间件,淘宝中间件团队在对 Kafka 做过充分 Review 之后,被 Kafka 无限消息堆积、高效的持久化速度等优点吸引了。

美中不足的的是,Kafka 主要定位于日志传输,对于使用在淘宝交易、订单、充值等场景下还有诸多特性不满足。所以,阿里的中间件团队重新用 Java 语言编写了 RocketMQ ,定位于全场景的可靠消息传输。

目前 RocketMQ 在阿里集团的应用生态里被广泛应用于订单、交易、充值、物流、消息推送、日志处理, binglog 分发等场景。

RocketMQ 对比 Kafka,虽然设计的思想上有借鉴,但在架构上做了减法,在功能上做了加法:

  • 去掉 Zookeeper,使用 NameServer 来管理 Broker 集群,通信更方便;
  • 有延时队列和死信队列,开箱即用,减化代码逻辑实现。

1.1基本模型

RocketMQ 主要由 Producer、Broker、Consumer 三部分组成
。其中,Producer 负责生产消息,Consumer 负责消费消息,Broker 负责存储消息。

基本模型

而 Broker 在实际部署过程中对应的是一台服务器,每个 Broker 可以存储多个 Topic 的消息,每个Topic 的消息也可以分片存储于不同的 Broker。Message Queue 用于存储消息的物理地址,每个 Topic 中的消息地址都会存储在多个 Message Queue 中。

ConsumerGroup 由多个Consumer 实例构成。


二、基本概念

以下的基本概念是理解和掌握 RocketMQ 最基础的概念,也是最重要的概念。现在不理解没有关系,先记住有个印象,后续使用的时候,兴许能帮助你豁然开朗。

2.1Producer

消息生产者(Producer)负责生产消息,一般由业务系统负责生产消息。

一个消息生产者会把业务应用系统里产生的消息(封装好的消息体)发送到 Broker 服务器。RocketMQ 提供多种发送方式,同步发送、异步发送、顺序发送、单向发送。其中,同步和异步方式均需要 Broker 返回确认信息(即Ack),单向发送不需要。

2.2Consumer

消息消费者(Consumer)负责消费消息,一般是由下游的系统负责异步消费。

一个消息消费者会从 Broker 服务器默认主动拉取(Pull 模式)消息,并将其提供给应用程序。从用户应用的角度而言提供了两种消费形式:拉取式消费(默认 Pull 模式)、推动式消费。

2.3Topic

主题(Topic)表示一类消息的集合,每个主题包含若干条消息,每条消息只能属于一个主题,是 RocketMQ 进行消息订阅的基本单位。

2.4Tag

标签(Tag)为消息设置的标志,用于同一 Topic 下区分不同类型的消息。来自同一业务单元的消息,可以根据不同业务的功能模块在同一主题下设置不同的标签。标签能够有效地保持代码的清晰度和连贯性,并优化 RocketMQ 提供的查询系统。消费者可以根据 Tag 实现对不同子主题的不同消费逻辑,实现更好的扩展性。

2.5Message

消息(Message)是系统所传输信息的物理载体、生产和消费数据的最小单位,每条消息必须属于某一个主题。RocketMQ 中的每条消息都拥有唯一的 Message ID 作为标识,且可以携带具有业务标识的 Key。系统提供了通过 Message ID 和 Key 查询消息的功能。

2.6Broker

代理服务器(Broker)是消息中转角色,负责存储消息、转发消息。代理服务器在 RocketMQ 系统中负责接收从生产者发送来的消息并存储、同时为消费者的拉取请求作准备。代理服务器也存储消息相关的元数据,包括消费者组、消费进度偏移和主题和队列消息等。

2.7Pull Consumer

拉取式消费(Pull Consumer)是 Consumer 消费的一种类型,也是默认的类型。下游应用系统通常主动调用 Consumer 的拉消息方法从 Broke r服务器拉消息,即主动权由下游应用控制。一旦获取了批量消息,应用就会启动消费过程。

2.8Producer Group

生产者组(Producer Group)是同一类 Producer 的集合,这类 Producer 发送同一类消息且发送逻辑一致。如果发送的是事务消息且原始生产者在发送之后崩溃,则 Broker 服务器会联系同一生产者组的其他生产者实例重试提交或回溯消费。

2.9Consumer Group

消费者组(Consumer Group)是同一类 Consumer 的集合,这类 Consumer 通常消费同一类消息且消费逻辑一致。消费者组使得在消息过程中实现负载均衡和提高容错变得非常容易。要注意的是,消费者组的每个消费者实例必须订阅完全相同的 Topic。RocketMQ 支持两种消息模式:集群消费(Clustering)和广播消费(Broadcasting)。

2.10Ordered Message

顺序消息分为普通顺序消费(Normal Ordered Message)和严格顺序消息(Strictly Ordered Message)。

普通顺序消费(Normal Ordered Message)下的消费者通过同一个消息队列(Message Queue) 收到的消息是有顺序的,不同消息队列收到的消息则可能是无顺序的。

而在严格顺序消息(Strictly Ordered Message)模式下,消费者收到的所有消息均是严格有序的。


三、高级特性

3.1消息顺序

消息有序指的是一类消息消费时,能按照发送的顺序来消费,RocketMQ 可以严格的保证消息有序。

例如:一个订单产生了三条消息分别是订单创建、订单付款、订单完成。消费时要按照这个顺序消费才能有意义,但是同时订单之间是可以并行消费的。

顺序消息分为全局顺序消息与分区顺序消息,全局顺序是指某个 Topic 下的所有消息都要保证顺序,部分顺序消息只要保证每一组消息被顺序消费即可。

  • 全局顺序


    • 对于指定的一个 Topic,所有消息按照严格的先进先出(FIFO)的顺序进行发布和消费。

    • 适用场景:性能要求不高,所有的消息严格按照 FIFO 原则进行消息发布和消费的场景。

  • 分区顺序


    • 对于指定的一个 Topic,所有消息根据 sharding key 进行区块分区。 同一个分区内的消息按照严格的 FIFO 顺序进行发布和消费。 Sharding key 是顺序消息中用来区分不同分区的关键字段,和普通消息的 Key 是完全不同的概念。

    • 适用场景:性能要求高,以 sharding key 作为分区字段,在同一个区块中严格的按照 FIFO 原则进行消息发布和消费的场景。

3.2消息可靠性

RocketMQ 支持消息的高可靠,以下是影响消息可靠性的 6 种情况:

  1. Broker 非正常关闭
  2. Broker 异常 Crash
  3. OS Crash
  4. 机器掉电,但是能立即恢复供电情况
  5. 机器无法开机(可能是 cpu、主板、内存等关键设备损坏)
  6. 磁盘设备损坏

其中上述的1、2、3、4 这四种情况都属于硬件资源可立即恢复的情况,RocketMQ 在这四种情况下能保证消息不丢失,或者丢失少量数据(取决于刷盘方式是同步还是异步)。

而5、6这两点属于单点故障,无法恢复,一旦发生,在此单点上的消息会全部丢失。

RocketMQ 在这两种情况下,通过异步复制可保证 99% 的消息不丢失,但是仍然会有极少量的消息可能丢失。
通过同步双写技术可以完全避免单点,同步双写势必会影响性能,适合对消息可靠性要求极高的场合,例如与订单、支付等相关的应用。注:RocketMQ 从 3.0 版本开始支持同步双写。

3.3延时队列

延迟队列是指消息发送到 Broker 后,不会立即被消费,等待特定时间后才会投递给真正的 Topic。

Broker 有配置项 messageDelayLevel,默认值为:1s、5s、10s、30s、1min、2min、3min、4min、5min、6min、7min、8min、9min、10min、20min、30min、1h、2h 这 18 个 level。

也可以配置自定义 messageDelayLevel ,注意:messageDelayLevel 是 Broker 的属性,不属于某个 Topic。

发消息时,设置 delayLevel 等级即可:msg.setDelayLevel(level)。level 有以下 3 种情况:

  • level == 0,消息为非延迟消息
  • 1<=level<=maxLevel,消息延迟特定时间,例如 level==1,延迟1s
  • level > maxLevel,则 level== maxLevel,例如 level==20,延迟 2h

定时消息会暂存在名为 SCHEDULE_TOPIC_XXXX 的 Topic 中,并根据 delayTimeLevel 存入特定的 queue,queueId = delayTimeLevel – 1,即一个 queue 只存相同延迟的消息,保证具有相同发送延迟的消息能够顺序消费。Broker 会调度地消费 SCHEDULE_TOPIC_XXXX,将消息写入真实的 Topic。

需要注意的是,定时消息会在第一次写入和调度写入真实 Topic 时都会计数,因此发送数量、TPS 都会变高,对性能可能会有一定影响。

3.4消息重试

Consumer 消费消息失败后,可以提供一种重试机制,令消息再消费一次。
Consumer 消费消息失败通常可以认为有以下几种情况:

  • 由于消息本身的原因
    • 例如反序列化失败,消息数据本身无法处理(例如话费充值,当前消息的手机号被注销,无法充值)等。
    • 这种错误通常需要跳过这条消息,再消费其它消息,而这条失败的消息即使立刻重试消费,99% 也不成功,所以最好提供一种定时重试机制,即过 10 秒后再重试。
  • 由于依赖的下游应用服务不可用
    • 例如数据库连接不可用,系统网络故障等。
    • 遇到这种错误,即使跳过当前失败的消息,消费其他消息同样也会报错。这种情况建议应用 sleep 30s,再消费下一条消息,这样可以减轻 Broker 重试消息的压力。

RocketMQ 会为每个消费组都设置一个 Topic 名称为:%RETRY%+consumerGroup 的重试队列。这里需要注意的是:这个 Topic 的重试队列是针对消费组,而不是针对每个 Topic 设置的,用于暂时保存因为各种异常而导致 Consumer 端无法消费的消息。

考虑到异常恢复起来需要一些时间,会为重试队列设置多个重试级别,每个重试级别都有与之对应的重新投递延时,重试次数越多投递延时就越大。

RocketMQ 对于重试消息的处理是先保存至 Topic 名称为:SCHEDULE_TOPIC_XXXX 的延迟队列中,后台定时任务按照对应的时间进行 Delay 后重新保存至 %RETRY%+consumerGroup 的重试队列中。

3.5死信队列

死信队列用于处理无法被正常消费的消息。

当一条消息初次消费失败,消息队列会自动进行消息重试。达到最大重试次数后,若消费依然失败,则表明消费者在正常情况下无法正确地消费该消息,此时,消息队列不会立刻将消息丢弃,而是将其发送到该消费者对应的特殊队列中。

RocketMQ 将这种正常情况下无法被消费的消息称为死信消息(Dead-Letter Message),将存储死信消息的特殊队列称为死信队列(Dead-Letter Queue)。

在 RocketMQ 中,可以通过使用 consol e控制台对死信队列中的消息进行重发来使得消费者实例再次进行消费。


四、文章小结

到这里关于消息队列 RocketMQ 的基本结构就分享完了,其实本文主要还是介绍一些基本的概念,后续笔者还会分享一些在正真项目中的实践,尽请期待。

最后,如果文章有不足和错误,还请大家指正。或者你有其它想说的,也欢迎大家在评论区里交流!

参考文档:

https://github.com/apache/rocketmq/blob/master/docs/cn/concept.md

https://github.com/apache/rocketmq/blob/master/docs/cn/features.md

开源的翻译软件众多,但大多数依赖于翻译 API 服务,因此就需要联网、有次数限制、并非完全免费。然后,本周上榜的是一款可以离线使用的 Android 翻译软件:RTranslator,它创建于 4 年前,最初也是基于谷歌翻译 API 开发,但在上周发布的 2.0 版本中,采用了全新的 NLLB+Whisper 模型,实现了可离线使用的同声翻译功能,这一改动 Star 数直接一飞冲天!

接下来上榜的开源项目,包括可当成命令行工具使用的爬虫框架 katana,轻松查看带宽使用情况的命令行工具 bandwhich,零代码开发游戏的 GDevelop,以及端到端的 WebRTC 技术栈 LiveKit,它能简化 Web 实时通信应用的开发。

最后,高颜值的 LLM 聊天应用 lobe-chat,搭配上简化大模型 API 服务的工具 LiteLLM,帮助你轻松打造属于自己的免费 ChatGPT 应用。

  • 本文目录
    • 1. 开源热搜项目
      • 1.1 离线的 Android 实时翻译软件:RTranslator
      • 1.2 开箱即用的爬虫工具和框架:katana
      • 1.3 零代码的游戏开发平台:GDevelop
      • 1.4 端到端的 WebRTC 技术栈:LiveKit
      • 1.5 高颜值的 ChatGPT/LLM 聊天应用:lobe-chat
    • 2. HelloGitHub 热评
      • 2.1 简化大模型 API 调用的工具:LiteLLM
      • 2.2 查看带宽使用情况的命令行工具:bandwhich
    • 3. 结尾

1. 开源热搜项目

1.1 离线的 Android 实时翻译软件:RTranslator

主语言:C++

Star:2.3k

周增长:2.1k

这是一款开源、免费、离线的 Android 实时翻译软件,它使用 Meta 开源的 NLLB 模型进行翻译,并结合 OpenAI 的 Whisper 技术处理语音,实现完全免费且无需联网的“同声翻译”功能,支持对话、对讲和文本翻译模式。需要注意,首次启动应用时会下载约 1GB 的模型,手机需具备至少 6GB 的运行内存。

GitHub 地址→
github.com/niedev/RTranslator

1.2 开箱即用的爬虫工具和框架:katana

主语言:Go

Star:9.6k

周增长:600

这是一个用 Go 语言编写的爬虫框架,可作为命令行工具或库使用,支持无头模式、JS 解析、正则表达式、输出 JSON 文件和自动填写表单等功能。把它当成命令行工具使起来十分方便,简单的爬虫根本不用写,一条命令直接搞定。

GitHub 地址→
github.com/projectdiscovery/katana

1.3 零代码的游戏开发平台:GDevelop

主语言:JavaScript

Star:7.1k

周增长:700

它是一个免费的开源游戏制作工具,它提供了可视化的编辑器和游戏开发环境,让用户不用写复杂的代码,即可通过拖拽的方式制作 2D 游戏。

GitHub 地址→
github.com/4ian/GDevelop

1.4 端到端的 WebRTC 技术栈:LiveKit

主语言:Go

Star:8.7k

周增长:400

该项目可用于构建基于 WebRTC 的可扩展多用户音/视频在线会议应用,它提供了丰富的客户端 SDK 和易于部署的服务器端,支持发言人检测、端到端加密、屏幕共享等功能。

GitHub 地址→
github.com/livekit/livekit

1.5 高颜值的 ChatGPT/LLM 聊天应用:lobe-chat

主语言:TypeScript

Star:33k

周增长:1k

该项目是由一群热情洋溢的设计工程师开发的 ChatGPT/LLM 桌面应用,它拥有极高的颜值,支持语音对话、视觉识别、文生图、插件市场、移动端适配和多用户管理等功能,可接入多种模型服务商和本地大语言模型。

GitHub 地址→
github.com/lobehub/lobe-chat

2. HelloGitHub 热评

在这个章节,将会分享下本周 HelloGitHub 网站上的热门开源项目,欢迎与我们分享你上手这些开源项目后的使用体验。

2.1 简化大模型 API 调用的工具:LiteLLM

主语言:Python

该项目能够将各种 AI 大模型和服务的接口,统一转换成 OpenAI 的格式,简化了在不同 AI 服务/大模型切换和管理的工作。此外,它还支持设置预算、限制请求频率、管理 API Key 和配置 OpenAI 代理服务器等功能。

项目详情→
hellogithub.com/repository/8c5825ab3aa640349dba422c26178376

2.2 查看带宽使用情况的命令行工具:bandwhich

主语言:Rust

这是一个开源的命令行网络带宽监控工具,它可以实时显示网络使用情况,包括进程、连接和远程地址等信息。

项目详情→
hellogithub.com/repository/bcff09fdc3864c3c8aa3024e0f56ea1e

3. 结尾

以上就是本期「GitHub 热点速览」的全部内容,希望你能够在这里找到自己感兴趣的开源项目,如果你有其他好玩、有趣的 GitHub 开源项目想要分享,欢迎来
HelloGitHub
与我们交流和讨论。

往期回顾

2023.10-2024.06十年有余,没想到在一家公司可以干这么久,属于超长期服役。原本3年前掀完桌子就该背包走人的,没想到又赖了三年。公司属于危机自救无奈减兵过冬,在国法的基础上还加了一点点毕业礼包,在这里真心感谢老板、感谢CCTV、MTV、BTV、皇恩浩荡。

从6.18接到人事通知到6.21最后一天站岗,3天时间速度之快表达了公司的情况不容乐观,也反应了在公司的价值已所剩全无!毕业后的心态全然放松,压抑的情绪突然释放,从惊到喜只用了几分钟,因为早已在预料之中。毕竟属于广进计划的第二梯队,感谢老板还是照顾了脸面(据说领导递交名单是第一梯队)。身心突然释放,有很多的后遗症:连续几晚失眠、没有了福报的加班、没有了BT的考核加持,还有彷徨、漫无目的、恐慌,当然这些并没有,只是为了博得几位十几年损友的安慰!

从事件发生后,先后很多朋友发来了安慰,甚至走了几年的同事也纷纷发来贺电。

好在这些年饭没白吃,脸皮也长厚了,逢人就说是喜丧。人生只有经历低谷才知道哪些才是真朋友。最佳损友聊天日常:

最近回顾了一下前30年,少年时期差点进厂打螺丝、青年时期运起顺势干到管理岗,中年时期运去又跌落一线码农,总结年少得志未必佳,套用易经智慧“福兮祸所伏,祸兮福所倚”,也相信人生并不会一直处于低谷。重新出发,未来可期!

前言

上一章我们熟悉了
Semantic Kernel
中的内置插件和对
ConversationSummaryPlugin
插件进行了实战,本章我们讲解一下另一个常用的内置插件
HttpPlugin
的应用。

上一章对
ConversationSummaryPlugin
总结进行了调整之后,顺便给
Semantic Kernel
提了一个
PR
已经被采纳了,在此记录一下!

image

.Net: refactor : SummarizeConversation #6719

HttpPlugin

HttpPlugin
插件属于
Native Plugins
原生插件。它提供了
Http
的功能,允许用户通过
Http
协议与外部进行交互。

我们对这个插件的整体进行分析一下

构造函数

提供了两个构造函数。第一个构造函数没有参数,它调用了第二个构造函数,并传递
null
作为参数。

第二个构造函数接受一个
HttpClient
类型的参数,如果未提供,则使用
HttpClientProvider.GetHttpClient()
方法获取一个新的
HttpClient
实例。

   public HttpPlugin() : this(null)
   {
   }

    [ActivatorUtilitiesConstructor]
    public HttpPlugin(HttpClient? client = null) =>
     this._client = client ?? HttpClientProvider.GetHttpClient();

这里重点说一下第二个构造函数,支持
HttpClient
的构造函数,这就有更多的可玩性了,比如可以定义一个
HttpclientHandler
对请求进行添加自定义的
HttpHeader
或者进行参数的拼接转发等操作。

Native functions

GetAsync
:发送一个
HTTP GET
请求,并返回响应体作为字符串。
PostAsync
:发送一个
HTTP POST
请求,带有请求体,并返回响应体作为字符串。
PutAsync
:发送一个
HTTP PUT
请求,带有请求体,并返回响应体作为字符串。
DeleteAsync
:发送一个
HTTP DELETE
请求,并返回响应体作为字符串。

实战

第一步需要安装
Nuget

NuGet\Install-Package Microsoft.SemanticKernel.Plugins.Core -Version 1.14.1-alpha

该包目前只有预览版本,如果用VS的包管理器安装,那需要勾选
包括预览发行版

Semantic Kernel
注册插件有两种方式:

kernel.ImportPluginFromType<HttpPlugin>();
var httpclient = new HttpClient();
kernel.ImportPluginFromObject(new HttpPlugin(httpclient));

以上两种方式对应两种生命周期的注册

创建的接口

image

这个接口都很简单 对我们
Student
对象的增删改查

public class Student
{
 
    public string Name { get; set; }


    public int Age { get; set; }

}

执行测试

我们的测试程序还是以
Semantic Kernel
的会话服务,自动触发
function calling
的形式

// Get chat completion service
var chatCompletionService = kernel.GetRequiredService<IChatCompletionService>();

// Start the conversation
Console.Write("User > ");
string? userInput;
while ((userInput = Console.ReadLine()) is not null)
{
    // Add user input
    history.AddUserMessage(userInput);

    // Enable auto function calling
    OpenAIPromptExecutionSettings openAIPromptExecutionSettings = new()
    {
        ToolCallBehavior = ToolCallBehavior.AutoInvokeKernelFunctions
    };

    // Get the response from the AI
    var result = await chatCompletionService.GetChatMessageContentAsync(
        history,
        executionSettings: openAIPromptExecutionSettings,
        kernel: kernel);

    // Print the results
    Console.WriteLine("Assistant > " + result);

    // Add the message from the agent to the chat history
    history.AddMessage(result.Role, result.Content ?? string.Empty);

    // Get user input again
    Console.Write("User > ");
}

Get请求测试

User > 帮我向https://localhost:7014/Student发一个get请求
Assistant > 向https://localhost:7014/Student发起GET请求后成功得到了响应,返回的数据显示包含了一个学生的信息。该学生名为 张三,年龄为16岁。这表明请求执行成功,获取到了预期的数据。

Post请求测试

HttpPlugin
的这个功能比较鸡肋,可以看一下代码

 [KernelFunction]
 [Description("Makes a POST request to a uri")]
 public Task<string> PostAsync([Description("The URI of the request")] string uri, [Description("The body of the request")] string body, CancellationToken cancellationToken = default(CancellationToken))
 {
     return SendRequestAsync(uri, HttpMethod.Post, new StringContent(body), cancellationToken);
 }

参数形式是
new StringContent(body)
,也就是说
MediaTypeHeaderValue
媒体类型默认为
StringContent text/plain

Asp.Net Core
只能接收
Post
请求
json
格式的
string
,不能接收原始
string

content-type

text/plain

post
请求,如果支持需要自定义实现没有提供对应的
MediaTypeFormatter

所以说这个插件的
Post
请求场景局限,真正用到生产还需要自己去实现一个插件!!!

User > 向https://localhost:7014/student 发一个post请求
Assistant > 已成功向 https://localhost:7014/student 发送了 POST 请求。如果需要发送具体的数据,请提供要包含在请求体内的 JSON 数据。

其他

Put

Delete
类似。

最后

可以借鉴
HttpPlugin
的实现思路在项目中灵活的运行,如果不支持那就可以自定义插件来完成需求的开发,还是比较期待这个插件能够更加完善的一点,在未来以更灵活的方式支持Post等请求的多种形式。

我们很高兴地宣布 Visual Studio 2022 的最新更新,它为您带来了 IDE 各个领域的一系列性能增强。在这篇博客中,我们将重点介绍17.10版本中一些最显著的改进,比如更快的 Windows Forms 设计器加载、更快的 Razor 着色、更快的解决方案加载以及更少的 dll 开销。

Windows Forms 设计器加载速度

我们从开发人员和合作伙伴那里听说,在.NET Core 3.1 及更高版本的项目中,Windows Forms 设计器的加载速度可能很慢。在这些情况下,设计器被加载到与 Visual Studio 一起运行的单独进程中。加载此进程的时间可能很长,具体取决于项目的依赖项。当在某些情况下需要重新启动此设计器进程时,例如当项目引用更改时,影响会加重。为了改善设计器重新启时间,我们优化了如何确定优先级并将程序集加载到设计器进程中。

我们很高兴地宣布,这些增强已经产生了显著的设计时性能改进,在典型的业务应用程序中,从30%到惊人的50%不等。我们鼓励您探索更新后的设计器,并通过 VS 反馈渠道分享您宝贵的反馈意见,以便我们能够继续改进 Windows Forms 设计器的性能。

Razor/C# 着色速度

为 C# 代码着色是一项复杂的操作。当 Razor 页面中有 C# 代码时, Razor 会将这些代码的着色任务委托给 C# 语言服务(Roslyn)。我们的数据显示,在大多数情况下,这种着色非常快,但大约10%的情况可能会持续数百毫秒。

Razor 编辑体验的性能改进 是我们工程师始终关注的焦点;在17.10中,他们专注于缓慢的着色。在他们的分析中,他们发现 Roslyn 执行了大量的工作,而这些工作在代码着色的特定上下文中并不真正需要(例如,确定哪些变量可能为空)。

已经进行了优化,这样 Roslyn 就可以完成在着色上下文中所需要的工作。根据17.10预览版本的数据,我们注意到在最慢的情况下,着色时间减少了25%。如果您注意到 Razor 在着色前有延迟,我们希望您能注意到17.10的改进。

更快的 .NET 解决方案加载

打开解决方案的速度是我们在 Visual Studio 的每次更新中都在改进的,17.10也不例外。Visual Studio 使用了一种称为评估缓存(evaluation cache)的东西,这样在每次打开解决方案时,MSBuild 都不必重新评估所有的依赖项。

在17.10中,这个缓存的内容进行了大量的调优,以便更有效地加载它。我们对 OrchardCore 解决方案的测量表明,缓存大小下降了近50%。对我们的用户来说更重要的是,这使得打开解决方案的时间减少了10%。

改善基础

在17.10中,除了改进 CPU 和内存使用等基础外,我们还减少了在特定场景中加载的 dll 数量。通过对加载 .NET 项目的代码进行仔细的重构和调优,我们将加载的 dll 数量减少了10%!在带有机械硬盘的低端机器上加载 dll 可能很慢。此外,dll 加载会引起检查 dll 的杀毒软件的开销,因此我们希望这些改进将对较慢的机器有所帮助。

分享您的反馈并与 Visual Studio 保持联系!

我们感谢您花时间报告问题和提交建议,并希望您在使用 Visual Studio 时继续给我们反馈,告诉我们您喜欢什么以及我们可以改进什么。您的反馈对于帮助我们使 Visual Studio 成为最好的工具至关重要!您可以通过开发者社区与我们分享反馈,通过发送反馈来报告问题或分享您的建议,并分享您对新功能或改进现有功能的建议。

通过在 YouTube, Twitter, LinkedIn, Twitch 和 Microsoft Learn 上关注我们与 Visual Studio 团队保持联系。

我代表整个 Visual Studio 团队,感谢您的阅读和编码愉快!

原文链接:https://devblogs.microsoft.com/visualstudio/visual-studio-2022-17-10-performance-enhancements/