性能比拼: .NET (C#) vs. Fiber (Go)

本内容是对知名性能评测博主 Anton Putra .NET (C#) vs. Fiber (Go): Performance (Latency - Throughput - Saturation - Availability) 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准


在本视频中,我们将对比 C# 与 .NET 框架和 Golang 的表现。在第一个测试中,我们将专注于各自的最小框架实现。我们将测量 CPU 使用率、内存使用率、每秒可处理的请求数量,以及最重要的——最终用户延迟。

我们会运行第一个测试直到其中一个应用程序失败,然后再继续运行一段时间,以找出另一个应用程序的崩溃临界点。

在第二个测试中,我们将模拟一个常见的使用场景:从本地文件系统读取一个文件(在本例中是图片),然后将其上传到 S3 存储桶。同时,我们会将有关该图片的一些元数据(比如使用时间戳、文件名等)保存到一个关系型数据库中,例如 Postgres。此外,我们还会测量上传图片到 S3 的延迟以及将数据插入数据库的查询延迟。

基于之前的基准测试和反馈,我还会测量每个应用程序创建的数据库连接数。

我们还将测量在云环境中启动应用程序所需的时间。这不仅包括启动时间,还包括拉取镜像和通过健康检查所需的时间。这将直接影响在云端的自动扩展能力。



对于 C# 我们将使用最新的 .NET 8 框架,这是由微软构建并开源的跨平台框架,它支持构建各种类型的应用程序,从简单的 Web 应用与移动应用,到微服务和机器学习模型。

在本视频中,我们将使用 .NET Core 框架搭配 Minimal API,以构建该语言与框架中最快的应用程序。

根据微软的说法,这种设置在性能上应该优于 Golang。然而,他们的对比使用的是 Go 平台上的 Gin 框架。


另一方面,对于Golang我们将使用 Fiber 框架,这是该语言中最快的 HTTP 框架之一。但有些人并不喜欢 Fiber,因为它并不完全兼容标准库,因此并不是所有的中间件、可观测性工具以及其他相关组件都能直接与 Fiber 一起使用。


现在,让我们来看一下具体的测试。我有一个家用实验室(Home Lab),使用 VMware Hypervisor 创建了一个多节点的 Kubernetes 集群。

我已经在 Kubernetes 中设置了一些监控组件:使用 Prometheus 服务器来抓取指标,Grafana 用于可视化这些指标并创建仪表盘,cAdvisor 用来抓取每个 Kubernetes 节点的指标,提供每个 Pod 的 CPU、内存与网络使用情况。我还部署了 kube-state-metrics,我们将用它来测量启动时间。

首先,我们将应用程序部署到 Kubernetes 集群。我有一个客户端程序,可以配置来生成负载并测量每个请求的延迟。

测量延迟的最佳方式是使用外部客户端,因为这能模拟任何最终用户的真实体验。当客户端开始发送请求时,Prometheus 会抓取这些指标,并在仪表盘中展示。

在第二个测试中,我们将使用应用程序中的另一个端点 /api/images。每当客户端发送请求时,应用程序会从本地文件系统读取一个文件并上传到 S3 存储桶。我们不会使用 AWS S3,而是使用 MinIO,它是一个兼容 S3 的对象存储,同样部署在 Kubernetes 中。

在客户端上传图片之后,我们会将一些图片的元数据(比如创建时间戳、文件名等)写入一个关系型数据库——Postgres,这也部署在 Kubernetes 中。

你可以在我的 GitHub 公共仓库中找到每个应用程序的源代码,以及用于部署监控组件的 Terraform 脚本、Helm 图表和 YAML 文件。

在这个测试中,我们还将使用 Prometheus 客户端对每个应用程序进行指标注入,用来测量一些特定函数的调用时间。例如,我们将跟踪上传图片所需的时间,以及将数据写入数据库所需的时间。

因此,在第二个测试中,我们将从外部客户端和应用程序本身中收集指标。

接下来,我们来比较两个应用程序的镜像大小。对于 .NET 应用程序,我们将使用多阶段 Docker 构建,并在最终阶段使用 distroless 镜像。这样可以减少最终镜像的体积。你也可以使用 Alpine 作为最终阶段的基础镜像,但那样会增加 1 到 2 兆字节的大小。

对于 Go 应用程序,我们也将使用多阶段构建,并在最终阶段使用 distroless 镜像,这个镜像由 Google 提供和构建。

现在,让我们查看最终的镜像大小。Go 的镜像比 .NET 的小两倍以上。实际上,你甚至可以将 Go 的镜像压缩到大约 39MB (使用go build -ldflags "-s -w")。更小的镜像意味着 Kubernetes 在拉取镜像和启动应用程序时所需时间更短。


接下来,我们来测量启动时间。这包括应用程序的启动时间、Kubernetes 拉取镜像的时间以及 Pod 通过健康检查的时间。

这并不是一个非常科学的方法,因为网络速度会极大地影响拉取镜像的时间。但你仍然可以获得一个大致的概念。我们可以使用 kube-state-metrics 来测量 Pod 就绪所需的时间。相关仪表盘也可以在我的代码仓库中找到。

好了,让我们创建两个 Pod,看看它们需要多长时间启动。

由于镜像更小,Golang 第一个启动(耗时7s),而 C# 紧随其后(耗时12s)。我多次运行了这个测试,并在每次之前都从 Kubernetes 节点中删除了镜像。如果你使用 Karpenter、自动扩缩容工具或云端的 Spot 节点,需要考虑 Kubernetes 每次都必须重新拉取镜像。否则,两者的启动时间差异不大。

好了,我们开始第一次测试。首先,我会将这些应用程序部署到 Kubernetes,并在没有任何负载的情况下运行大约 20 分钟。

你可能会注意到 C# 的 CPU 使用率略高,但真正的区别在于内存使用。在空闲状态下,C# 和 .NET 框架的内存消耗远高于 Golang。

现在我们开始测试。首先,我们运行 10 个客户端,持续约 5 分钟,大约每个应用程序会接收到 20 个请求每秒。你会立即注意到 C# 的 CPU 使用率飙升,而且从客户端侧测量的整体延迟明显更高。但内存使用几乎没有变化,因为我们只是返回了硬编码的 JSON 数据。

接下来,我们增加到 50 个客户端,大约是每秒 100 个请求。CPU 使用的差异变得更大,而延迟的差异保持一致。

现在,我们将客户端数量增加到 200。整体延迟有所下降,但两者之间的相对比例保持不变。此时,Golang 更高效,CPU 使用更少。

我们继续,将客户端数量增加到 400,测试 5 分钟。

然后,我们将客户端数量降到 5,观察应用程序的适应能力。

接着,尝试 10 个客户端。

从现在开始,我们将从 550 个客户端开始,每隔 5 分钟持续增加,直到某个应用程序失败。

当请求数达到每秒约 1200 时,.NET 应用程序开始丢弃部分请求。

请求达到每秒约 1300 时,.NET 应用程序开始出现故障,并伴随延迟激增。我们会继续运行几分钟。

最后,Golang 开始丢弃一些请求,但它的延迟仍保持在几毫秒的范围内。

整个测试持续了大约 2.5 小时。现在让我打开各项图表,查看整个测试期间的表现。

首先是 CPU 使用率图表。

接着是内存使用图表。

然后是每秒请求数图表。

最后是整体延迟图表。

这就是第一个测试的全部内容,我们对比了框架本身:.NET Minimal API 与 Golang Fiber 框架,两者在 Kubernetes 中并行运行。



现在我们开始第二个测试,先从 10 个客户端开始。你可以立刻看出 CPU 和内存使用显著上升。同时我们还会测量延迟,看看读取文件并上传到 S3 所需的时间。目前来看,Golang 在低负载下表现更高效。我们还会测量保存文件元数据到关系型数据库的延迟。

目前看起来,Golang 的性能更好,使用更少的 CPU 和内存完成任务。

接下来我们模拟一个突发流量,将客户端数量暂时增加到 50,持续 5 分钟。

S3 的延迟几乎不变,但数据库延迟的差异增大。

好了,我们将客户端数量降回 10。

接下来的一个小时左右,我将逐步将客户端数量从 100 增加到 200,以观察哪一个应用程序表现更好。

你还可以看到 .NET 增加了连接池大小,而 Golang 保持相对稳定。我本可以手动设置连接池大小,但我的目标是测试这些框架和库在默认设置下的表现,因为很多人就是这么使用的。

好了,我再运行几分钟的测试。到目前为止,这大概就是两个应用程序所能处理的最大请求量了。你可以看到每秒请求数保持平稳。

现在让我打开整个测试期间的 CPU 使用图表。

接下来是内存使用图表。

然后是数据库延迟图表。

这是每个应用程序的连接池大小图。顺便一提,Postgres 默认可以打开 100 个并发连接——至少这是我用 Helm 图表部署数据库时的默认设置。

现在是客户端延迟图表。

在每秒请求数指标中,你可以看到 Golang 实际上能处理更多请求。

最后是 S3 延迟图表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/94293.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/94293.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

信誉代币的发行和管理机制是怎样的?

信誉代币的发行与管理机制是区块链技术与经济模型深度融合的产物,其核心在于通过代码和社区共识构建可量化、可验证的信任体系。以下从技术架构、经济模型、治理机制三个维度展开分析,并结合具体案例说明:一、发行机制:行为即价值…

神经网络|(十二)概率论基础知识-先验/后验/似然概率基本概念

【1】引言 前序学习进程中,对贝叶斯公式曾经有相当粗糙的回归,实际上如果我们看教科书或者网页,在讲贝叶斯公式的时候,会有几个名词反复轰炸:先验概率、后验概率、似然概率。 今天就来把它们解读一下,为以…

使用UE5开发《红色警戒3》类战略养成游戏的硬件配置指南

从零开始,学习 虚幻引擎5(UE5),开始游戏开发之旅!本文章仅提供学习,切勿将其用于不法手段!开发类似《红色警戒3》级别的战略养成游戏,其硬件需求远超普通2D或小型3D项目——这类游戏…

Vue2+Vue3前端开发_Day12-Day14_大事件管理系统

参考课程: 【黑马程序员 Vue2Vue3基础入门到实战项目】 [https://www.bilibili.com/video/BV1HV4y1a7n4] ZZHow(ZZHow1024) 项目收获 Vue3 composition APIPinia / Pinia 持久化处理Element Plus(表单校验,表格处理,组件封装&#xff09…

[ACTF新生赛2020]明文攻击

BUUCTF在线评测BUUCTF 是一个 CTF 竞赛和训练平台,为各位 CTF 选手提供真实赛题在线复现等服务。https://buuoj.cn/challenges#[ACTF%E6%96%B0%E7%94%9F%E8%B5%9B2020]%E6%98%8E%E6%96%87%E6%94%BB%E5%87%BB下载查看,一个压缩包和一张图片。压缩包需要密…

关于日本服务器的三种线路讲解

租用日本服务器时,哪种线路选择更适合?当初次接触跨境业务的站长们着手租用日本服务器时,会发现不同服务商提供的网络线路五花八门,从陌生的运营商名称到复杂的技术参数,常常使其感到眼花缭乱。为了帮助大家理清思路,…

【大白话解析】 OpenZeppelin 的 MerkleProof 库:Solidity 默克尔证明验证工具全指南​​(附源代码)

🧩 一、Merkle Tree 是什么?为什么要验证它? 想象你有一个名单,比如: ["Alice", "Bob", "Charlie", "Dave"] 你想让别人验证:“我(比如 Alice)是不是在这个名单里?”,但不想把整个名单都放在区块链上(太贵!)。 于是你…

机械学习综合练习项目

数据集合完整项目文件已经上传一、项目介绍案例介绍 案例是针对“红酒.csv”数据集,在红葡萄酒质量分析的场景 中,利用多元线性回归来探索红葡萄酒的不同化学成分如何共同 影响其质量评分。在建立线性回归模型之后,当给出了红葡萄酒 的新的一…

第3篇:配置管理的艺术 - 让框架更灵活

前言 在前一章中,我们设计了强大的注解API。本章将深入探讨配置管理系统的设计,学习如何将注解中的声明式配置转换为运行时可用的配置对象。 配置管理的核心挑战 在我们的框架中,配置来源有三个层级:主要挑战: &#x…

发版混乱怎么规范

你是否经历过这种场景:临到发版,一堆功能代码挤在一起,测试分不清范围,修复一个Bug可能引发三个新Bug?发布过程像一场豪赌?问题的核心往往在于分支策略和流程的混乱。今天,我们就来建立一套在绝…

【golang长途旅行第30站】channel管道------解决线程竞争的好手

channel 为什么需要channel 使用全局变量加锁同步来解决goroutine的竞争,可以但不完美难以精确控制等待时间​(主线程无法准确知道所有 goroutine 何时完成)。全局变量容易引发竞态条件​(即使加锁,代码复杂度也会增加…

苹果XR芯片介绍

苹果的 XR 芯片技术主要体现在 A 系列、M 系列处理器以及专为空间计算设计的 R1 协处理器中。以下从技术架构、产品迭代和综合对比三个维度展开分析:一、技术架构解析1. A 系列芯片(以 A12 Bionic 为例)制程工艺:7nm(台…

达梦数据库巡检常用SQL(三)

达梦数据库巡检常用SQL(三) 数据库SQL运行检查 数据库SQL运行检查 死锁的事务情况: SELECT TO_CHAR(HAPPEN_TIME,YYYY-MM-DD HH24:MI:SS) HAPPEN_TIME,SQL_TEXT FROM V$DEADLOCK_HISTORY WHERE HAPPEN_TIME >DATEADD(DAY,-30,

基于SpringBoot的校园周边美食探索及分享平台

1. 项目简介 项目名称:校园周边美食探索及分享平台 项目背景:针对校园师生对周边美食信息的需求,构建一个集美食推荐、鉴赏、评论互动及社交功能于一体的平台,帮助用户发现优质美食资源并进行分享交流。 主要目标: 提供…

Go数据结构与算法-常见的排序算法

虽然看过别人写了很多遍,而且自己也写过很多遍(指的是笔记),但是还是要写的就是排序算法。毕竟是初学Go语言,虽然之前写过,但是还是打算再写一遍。主要包括插入排序、选择排序、冒泡排序、快速排序、堆排序…

第 6 篇:目标规则与负载均衡 - `DestinationRule` 详解

系列文章:《Istio 服务网格详解》 第 6 篇:目标规则与负载均衡 - DestinationRule 详解 本篇焦点: 深入理解 DestinationRule 的核心作用:定义流量在到达目的地之后的行为。 详细剖析其三大核心功能:服务子集 (Subsets), 流量策略 (Traffic Policy), TLS 设置。 动手实战…

一个简洁的 C++ 日志模块实现

一个简洁的 C 日志模块实现 1. 引言 日志功能在软件开发中扮演着至关重要的角色,它帮助开发者追踪程序执行过程、诊断问题以及监控系统运行状态。本文介绍一个使用 C 实现的轻量级日志模块,该模块支持多日志级别、线程安全,并提供了简洁易用…

C语言---数据类型

文章目录数据类型分类1. 基本类型 (Basic Types)a. 整数类型 (Integer Types)char (字符型)int (整型)short (短整型)long (长整型)long long (C99标准引入)图片汇总b. 浮点类型 (Floating-Point Types)float (单精度浮点型)double (双精度浮点型)long double (长双精度浮点型)…

本搭建乌云漏洞库

1.下载镜像站文件,并拖入虚拟机 2.将bugs.rar解压至网站根目录下 /var/www/html 3.配置bugs/conn.php 4.在bugs下创建upload目录,将10-14、15-a、15-b、16压缩包文件解压到该upload目录 5.把wooyun.rar解压到 /mysql/data/wooyun目录下 6.配置hosts文件后…

Vmware虚拟机 处理器配置选项配置介绍

1. 处理器配置选项好👌,我来帮你逐一解读 VMware 里 虚拟机处理器 这些选项的含义。 你截的图里,主要有三块内容: 处理器数量 每个处理器的内核数量 ©虚拟化引擎1️⃣ 处理器数量 这是分配给虚拟机的 逻辑 CPU 插槽数。一般…