摘要: 作为《ASP.NET Core 3框架揭秘》的升级版,《ASP.NET Core 6框架揭秘》提供了很多新的章节,同时对现有的内容进行大量的修改。虽然本书旨在对ASP.NET Core框架的架构设计和实现原理进行剖析,但是其中提供的258个实例演示却可以作为入门材料,这个系列会将这些演示实例单独提取 阅读全文
posted @ 2022-02-22 08:23 Artech 阅读(22156) 评论(8) 推荐(54) 编辑
摘要: 我想很多人已经体验过GRPC提供的三种流式消息交换模式,在.NET Core上构建的GRPC应用本质上是采用HTTP2/HTTP3协议的ASP.NET Core应用,我们当然也可以在一个普通的ASP.NET Core应用实现这些流模式。不仅如此,HttpClient也提供了响应的支持,这篇文章通过一个简单的实例提供了相应的实现 阅读全文
posted @ 2024-02-20 08:13 Artech 阅读(1194) 评论(5) 推荐(11) 编辑
摘要: 针对“缓冲区”编程是一个非常注重“性能”的地方,我们应该尽可能地避免武断地创建字节数组来存储读取的内容,这样不但会导致大量的字节拷贝,临时创建的字节数组还会带来GC压力。要正确、高效地读写缓冲内容,我们应该对几个我们可能熟悉的类型具有更深的认识。 阅读全文
posted @ 2024-02-19 08:07 Artech 阅读(4163) 评论(8) 推荐(43) 编辑
摘要: 由于Memory存储的是单纯的二进制字节,所以原则上我们可以用来它作为媒介,在wasm模块和数组程序之间传递任何类型的数据。在JavaScript API中,Memory通过WebAssembly.Memory类型表示,我们一般将它内部的缓冲区映射相应类型的数组进行处理。WebAssembly也提供了相应的指令来提供针对Memory的读、写、扩容等操作 阅读全文
posted @ 2024-02-05 09:42 Artech 阅读(1289) 评论(4) 推荐(7) 编辑
摘要: WebAssembly程序总是以模块来组织,模块是基本的部署、加载和编译单元。在JavaScript编程接口中,模块通过WebAssembly.Module类型表示。WebAssembly.Module通过加载的.wasm二进制文件创建而成,它承载了描述wasm模块的元数据,类似于描述程序集的Assembly对象。WebAssembly.Module自身是只读且无状态的,有状态的是根据它结合指定的导入对象创建的模块实例,后者通过WebAssembly.Instance表示。这两个类型提供了几个核心API,解析我们就通过它们来介绍WebAssembly的这两个核心对象。 阅读全文
posted @ 2024-02-02 09:39 Artech 阅读(381) 评论(0) 推荐(3) 编辑
摘要: 对于绝大多数编程语言来说,类型都是编程的基础,WebAssembly自然也不例外。总的来说,WebAssembly涉及的类型不多,很好掌握,接下来我们就来介绍一下WebAssembly编程涉及到的几种类型。本篇内容参考WebAssembly Spec。 阅读全文
posted @ 2024-02-01 08:33 Artech 阅读(370) 评论(0) 推荐(4) 编辑
摘要: 当我们在一个Web应用中使用WebAssembly,最终的目的要么是执行wasm模块的入口程序(通过start指令指定的函数),要么是调用其导出的函数,这一切的前提需要创建一个通过WebAssembly.Instance对象表示的wasm模块实例(源代码)。 阅读全文
posted @ 2024-01-31 08:37 Artech 阅读(499) 评论(0) 推荐(5) 编辑
摘要: 利用WebAssembly的导入导出功能可以灵活地实现宿主JavaScript程序与加载的单个wasm模块之间的交互,那么如何在宿主程序与多个wasm之间传递和共享数据呢?这就需要使用到Global这个重要的对象了。 阅读全文
posted @ 2024-01-30 08:33 Artech 阅读(481) 评论(2) 推荐(8) 编辑
摘要: 在《WebAssembly入门笔记[2]》中,我们介绍了如何利用Memory在作为宿主的JavaScript应用和wasm模块之间传递数据,但是Memory面向单纯二进制字节的读写在使用起来还是不太方便,此时我们会更多地用到另一个重要的对象Table。Table利用用来存储一组指定类型的对象,说得准确一点是对象的引用,所以可以读取出来直接消费。 阅读全文
posted @ 2024-01-29 08:35 Artech 阅读(562) 评论(2) 推荐(6) 编辑
摘要: 利用灵活的“导入”和“导出”机制,WebAssembly与承载的JavaScript应用之间可以很便利地“互通有无”。《与JavaScript的交互》着重演示了如何利用函数的导入和导出实现功能的共享,接下来我们主要关注数据的传递或者共享。宗地来说,WebAssembly与宿主程序之间的数据传递主要有如下三种手段,本篇文章主要关注Memory。 阅读全文
posted @ 2024-01-26 08:40 Artech 阅读(669) 评论(0) 推荐(8) 编辑
摘要: 前一阵子利用Balazor开发了一个NuGet站点,对WebAssembly进行了初步的了解,觉得挺有意思。在接下来的一系列文章中,我们将通过实例演示的方式介绍WebAssembly的一些基本概念和编程模式。 阅读全文
posted @ 2024-01-25 08:27 Artech 阅读(1756) 评论(7) 推荐(15) 编辑
摘要: 前几天有人在我的《ASP.NET Core框架揭秘》读者群跟我留言说:“我最近在看ASP.NET Core MVC的源代码,发现整个系统太复杂,涉及的东西太多,完全找不到方向,你能不能按照《200行代码,7个对象——让你了解ASP.NET Core框架的本质》这篇文章思路剖析一下MVC框架”,今天我们就来试试看。 阅读全文
posted @ 2023-11-08 08:31 Artech 阅读(4225) 评论(33) 推荐(56) 编辑
摘要: 在过去一段时间里,我陆陆续续写一些关于.NET对象类型布局的文章,其中包括值类型和引用类型的内存布局、字符串对象和数组的内存布局等,这里作一个简单的汇总。 阅读全文
posted @ 2023-11-07 08:11 Artech 阅读(1524) 评论(4) 推荐(10) 编辑
摘要: 在《NativeBuffering,一种高性能、零内存分配的序列化解决方案[性能测试篇]》我比较了NativeBuffering和System.Text.Json两种序列化方式的性能,通过性能测试结果可以看出NativeBuffering具有非常明显的优势,有的方面的性能优势甚至是“碾压式”的,唯独针对字符串的序列化性能不够理想。我趁这个周末对此做了优化,解决了这块短板,接下来我们就来看看最新的性能测试结果和背后“加速”的原理。 阅读全文
posted @ 2023-11-06 08:29 Artech 阅读(1145) 评论(1) 推荐(12) 编辑
摘要: 实现一个极简的字节数组对象池 .NET利用ArrayPoolPool<T>和MemoryPool<T>提供了针对Array/Memory<T>的对象池功能。最近在一个项目中需要使用到针对字节数组的对象池,由于这些池化的字节数组相当庞大,我希望将它们分配到POH上以降低GC的压力。由于ArrayPoolPool<T>没法提供支持, 阅读全文
posted @ 2023-11-03 08:22 Artech 阅读(1983) 评论(5) 推荐(17) 编辑
摘要: 第一版的NativeBuffering([上篇]、[下篇])发布之后,我又对它作了多轮迭代,对性能作了较大的优化。比如确保所有类型的数据都是内存对齐的,内部采用了池化机器确保真正的“零内存分配”等。对于字典类型的数据成员,原来只是“表现得像个字段”,这次真正使用一段连续的内存构架了一个“哈希表”。我们知道对于每次.NET新版本的发布,原生的JSON序列化(System.Text.Json)的性能都作了相应的提升,本篇文章通过具体的性能测试比较NativeBuffering和它之间的性能差异。 阅读全文
posted @ 2023-11-02 09:46 Artech 阅读(2589) 评论(26) 推荐(20) 编辑
摘要: 两种基于时间窗口的限流器的简单实现 之前开发的一款基于OpenTelemetry的Tracing组件需要使用基于速率限制(Rate Limiting)的跟踪采样策略,本想使用现有的解决方案,比如System.Threading.RateLimiting命名空间下的RateLimiter。大体看了RateLimiter的三种实现(固定窗 阅读全文
posted @ 2023-11-01 08:29 Artech 阅读(946) 评论(1) 推荐(7) 编辑
摘要: 《.NET中的数组在内存中如何布局? 》介绍了一个.NET下针对数组对象的内存布局。既然我们知道了内存布局,我们自然可以按照这个布局规则创建一段字节序列来表示一个数组对象。 阅读全文
posted @ 2023-10-31 08:44 Artech 阅读(729) 评论(4) 推荐(7) 编辑
摘要: 总的来说,.NET的值类型和引用类型都映射一段连续的内存片段。就内存布局来说,引用类型有两个独特的存在,一个是字符串,另一个就是数组。今天我们来聊聊数组类型的内存布局。 阅读全文
posted @ 2023-10-30 08:50 Artech 阅读(3136) 评论(5) 推荐(26) 编辑
摘要: 上文说到Unmanaged、BufferedBinary和BufferedString是NativeBuffering支持的三个基本数据类型,其实我们也可以说NativeBuffering只支持Unmanaged和IReadOnlyBufferedObject 阅读全文
posted @ 2023-08-01 08:30 Artech 阅读(980) 评论(4) 推荐(6) 编辑
摘要: 之前一个项目涉及到针对海量(千万级)实时变化数据的计算,由于对性能要求非常高,我们不得不将参与计算的数据存放到内存中,并通过检测数据存储的变化实时更新内存的数据。存量的数据几乎耗用了上百G的内存,再加上它们在每个时刻都在不断地变化,所以每时每刻都无数的对象被创建出来(添加+修改),同时无数现有的对象被“废弃”(删除+修改)。这种情况针对GC的压力可想而知,所以每当进行一次2代GC的时候,计算的耗时总会出现“抖动”。为了解决这类问题,几天前尝试着创建了一个名为NativeBuffering的框架 阅读全文
posted @ 2023-07-31 08:31 Artech 阅读(2013) 评论(9) 推荐(22) 编辑
摘要: 作为构建.NET的标准,CLI Spec(ECMA-335)针对基元类型的对齐规则具有如下的描述。按照这个标准,我们是这么理解的:8字节的数据类型(int64、unsigned int64和float64)根据采用的机器指令架构选择4字节或者8字节对其。进一步来说,它们在x86/x64机器上的对其字节分别为4字节和8字节,但实验证明却并非如此。 阅读全文
posted @ 2023-07-18 08:24 Artech 阅读(758) 评论(1) 推荐(3) 编辑
摘要: 毫无疑问,字符串是我们使用频率最高的类型。但是如果我问大家一个问题:“一个字符串对象在内存中如何表示的?”,我相信绝大部分人回答不上来。我们今天就来讨论这个问题。 阅读全文
posted @ 2023-07-17 08:32 Artech 阅读(4335) 评论(11) 推荐(25) 编辑
摘要: 一个对象总是映射一块连续的内存序列(不考虑对象之间的引用关系),如果我们知道了引用类型实例的内存布局,以及变量引用指向的确切的地址,我们不仅可以采用纯“二进制”的方式在内存“绘制”一个指定引用类型的实例,还可以修改某个变量的“值”指向它 阅读全文
posted @ 2023-07-14 08:25 Artech 阅读(3050) 评论(4) 推荐(13) 编辑
摘要: 非公开的类型或者方法被“隐藏”在程序集内部,本就不希望从外部访问,但是有时候调用一个内部或者私有方法可能是唯一的“救命稻草”,这篇文章列出了几种具体的实现方式。 阅读全文
posted @ 2023-07-13 12:12 Artech 阅读(2857) 评论(1) 推荐(21) 编辑
摘要: C#具有一个默认开启的代码分析规则:[CA1810]Initialize reference type static fields inline,推荐我们以内联的方式初始化静态字段,而不是将初始化放在静态构造函数中。 阅读全文
posted @ 2023-07-10 08:36 Artech 阅读(2679) 评论(6) 推荐(16) 编辑
摘要: 现代化的应用及服务的部署场景主要体现在集群化、微服务和容器化,这一切都建立在针对部署应用或者服务的健康检查上。ASP.NET提供的健康检查不仅可能确定目标应用或者服务的可用性,还具有健康报告发布功能。ASP.NET框架的健康检查功能是通过HealthCheckMiddleware中间件完成的。我们不仅可以利用该中间件确定当前应用的可用性,还可以注册相应的IHealthCheck对象来完成针对不同方面的健康检查。 阅读全文
posted @ 2023-07-06 09:15 Artech 阅读(2549) 评论(5) 推荐(22) 编辑
摘要: 实例方法和静态方法有区别吗?对于很多人来说,这是一个愚蠢的问题。因为我们都知道它们的区别,实例方法作用于某个具体的上下文对象,该上下文对象可以利用this关键字获得;静态方法则是定义在某个类型中,不存在上下文对象的概念。但是如果我们从函数的角度来看的话,不论是静态方法还是实例方法都是一个用于处理输入参数的操作,貌似又没有什么区别。 阅读全文
posted @ 2023-07-05 08:33 Artech 阅读(4126) 评论(11) 推荐(24) 编辑
摘要: 同源策略是所有浏览器都必须遵循的一项安全原则,它的存在决定了浏览器在默认情况下无法对跨域请求的资源做进一步处理。为了实现跨域资源的共享,W3C制定了CORS规范。ASP.NET利用CorsMiddleware中间件提供了针对CORS规范的实现 阅读全文
posted @ 2023-07-04 08:43 Artech 阅读(1435) 评论(3) 推荐(10) 编辑
摘要: 除了参数,ref关键字还可以用在什么地方? 《老生常谈:值类型 V.S. 引用类型》中花了很大的篇幅介绍ref参数针对值类型和引用类型变量的传递。在C#中,除了方法的ref参数,我们还有很多使用ref关键字传递引用/地址的场景,本篇文章作一个简单的总结。 一、参数 二、数组索引 三、方法 四、ref 结构体 五、ref 结构体字段 一、参数 阅读全文
posted @ 2023-07-03 08:41 Artech 阅读(4090) 评论(9) 推荐(35) 编辑
摘要: 之前参与一个机票价格计算的项目,为他们设计了基本的处理流程,但是由于整个计算流程相当复杂,而且变化非常频繁,导致日常的修改、维护和升级也变得越来越麻烦,当我后来再接手的时候已经看不懂计算逻辑了。为了解决这个问题,我借鉴了“工作流”的思路,试图将整个计算过程设计成一个工作流。但是我又不想引入一个独立的工作流引擎,于是写了一个名为Pipelines的框架。 阅读全文
posted @ 2023-06-30 08:16 Artech 阅读(7141) 评论(35) 推荐(56) 编辑
摘要: 老生常谈:值类型 V.S. 引用类型 我在面试的时候经常会问一个问题:“谈谈值类型和引用的区别”。对于这个问题,绝大部分人都只会给我两个简洁的答案:“值类型分配在栈中,引用类型分配在堆中”,“在默认情况下,值类型参数传值(拷贝),引用类型参数传引用”。其实这个问题有很大的发挥空间,如果能够从内存布局、GC、互操作、跨AppDomain传 阅读全文
posted @ 2023-06-29 08:57 Artech 阅读(3842) 评论(10) 推荐(36) 编辑
摘要: ASP.NET应用并没有对如何定义授权策略做硬性规定,但是针对角色的授权策略依然是最常用的。角色(或者用户组)实际上就是对一组权限集的描述,将一个用户添加到某个角色之中就是为了将对应的权限赋予该用户。在《使用最简洁的代码实现登录、认证和注销》中,我们提供了一个用来演示登录、认证和注销的程序,现在我们在此基础上添加基于“角色授权的部分”。 阅读全文
posted @ 2023-06-25 09:43 Artech 阅读(3105) 评论(3) 推荐(13) 编辑
摘要: 认证是一个确定请求访问者真实身份的过程,与认证相关的还有其他两个基本操作——登录和注销。ASP.NET Core利用AuthenticationMiddleware中间件完成针对请求的认证,并提供了用于登录、注销以及“质询”的API,本篇文章利用它们使用最简单的代码实现这些功能。 阅读全文
posted @ 2023-06-19 10:23 Artech 阅读(2285) 评论(8) 推荐(16) 编辑
摘要: 承载ASP.NET应用的服务器资源总是有限的,短时间内涌入过多的请求可能会瞬间耗尽可用资源并导致宕机。为了解决这个问题,我们需要在服务端设置一个阀门将并发处理的请求数量限制在一个可控的范围,即使会导致请求的延迟响应,在极端的情况会还不得不放弃一些请求。ASP.NET应用的流量限制是通过ConcurrencyLimiterMiddleware中间件实现的。 阅读全文
posted @ 2023-06-14 09:28 Artech 阅读(1156) 评论(0) 推荐(4) 编辑
摘要: 在HTTP的语义中,重定向一般指的是服务端通过返回一个状态码为3XX的响应促使客户端像另一个地址再次发起请求,本章将此称为“客户端重定向“。既然有客户端重定向,自然就有服务端重定向,本章所谓的服务端重定向指的是在服务端通过改变请求路径将请求导向另一个终结点。ASP.NET下的重定向是通过RewriteMiddleware中间件实现的。 阅读全文
posted @ 2023-06-13 08:27 Artech 阅读(2444) 评论(3) 推荐(8) 编辑
摘要: 在讨论.NET的类型系统的时候,我们经常提到“基元类型(Primitive Type)”的概念,我发现很多人并没有真正理解基元类型就究竟包含哪些(比如很多人觉得字符串是基元类型)。除了明确界定基元类型外,本篇文章还会简单介绍额外两种关于类型的概念——Unmananged类型和Blittable类型。 阅读全文
posted @ 2023-06-12 08:52 Artech 阅读(1001) 评论(2) 推荐(17) 编辑
摘要: 如何将一个实例的内存二进制内容读出来? 在《如何计算一个实例占用多少内存?》中我们知道一个值类型或者引用类型的实例在内存中占多少字节。如果我们知道这段连续的字节序列的初始地址,我们就能够将代表该实例的字节内容读取出来。在接下来的内容中,我们将利用一个简单的方法输出指定实例的字节序列,并此次分析值类型和引用类型实例在内存的布局。 一、读取实 阅读全文
posted @ 2023-06-08 09:30 Artech 阅读(2847) 评论(2) 推荐(21) 编辑
摘要: 我们都知道CPU和内存是程序最为重要的两类指标,那么有多少人真正想过这个问题:一个类型(值类型或者引用类型)的实例在内存中究竟占多少字节?我们很多人都回答不上来。其实C#提供了一些用于计算大小的操作符和API,但是它们都不能完全解决我刚才提出的问题。本文提供了一种计算值类型和引用类型实例所占内存字节数量的方法。 阅读全文
posted @ 2023-06-05 08:51 Artech 阅读(5789) 评论(20) 推荐(54) 编辑
摘要: HTTPS是确保传输安全最主要的手段,并且已经成为了互联网默认的传输协议。不知道读者朋友们是否注意到当我们利用浏览器(比如Chrome)浏览某个公共站点的时候,如果我们输入的是一个HTTP地址,在大部分情况下浏览器会自动重定向到对应HTTPS地址。这一特性源于浏览器和服务端针对HSTS(HTTP Strict Transport Security)这一HTTP规范的支持。ASP.NET利用HstsMiddleware和HttpsRedirectionMiddleware这两个中间件提供了对HSTS的实现。 阅读全文
posted @ 2023-06-01 10:09 Artech 阅读(2480) 评论(9) 推荐(10) 编辑
摘要: 了解OpenTelemetry的朋友应该知道,为了将率属于同一个请求的多个操作(Span)串起来,上游应用会生成一个唯一的TraceId。在进行跨应用的Web调用时,这个TraceId和代表跟踪操作标识的SpanID一并发给目标应用。其实我们的应用也可能会使用到分布式跟踪这种类似的功能,我们需要在某个应用中添加一些“埋点”,当它调用另一个应用时,这些埋点会自动添加到请求的报头集合中,从而实现在整个调用链中自动传递 阅读全文
posted @ 2023-05-31 08:31 Artech 阅读(1320) 评论(2) 推荐(13) 编辑