写点什么

C#的未来:托管指针

  • 2015-05-05
  • 本文字数:1388 字

    阅读完需:约 5 分钟

对于许多开发者,尤其是编写游戏软件,以及进行纯数字计算的开发者来说,原始性能是程序的重中之重。同时对他们来说,最大的问题莫过于内存分配了。虽然分配操作本身消耗很小,但过多的分配会造成内存的极大压力,并且造成垃圾回收器的执行周期更加频繁。

在堆中分配的内存也会造成缓存的问题。如果你有一个存放引用类型的列表或是数组,它的实际数据与数组本身是分开进行保存的。这意味着你可能不得不浪费更多的缓存线以保存这个数组以及由数组所引用的对象。而如果我们在同一时间内创建了这些对象,那么可能会造成很大的分散性,进而导致消耗更多的缓存线。相关数据的分散性也就导致了糟糕的局部性(locality)。

使用值类型(在 C#的说法中也就是结构体)能够极大地减少内存的分配次数并改善局部性。但是,在结构体的使用上存在着一些限制。因为设计它们的初衷是传递拷贝,因此你必须保证它们的尺寸非常小,否则就很可能受到性能上的严惩,这也违背了在第一时间使用值类型的本意。

为了避免无意义的拷贝,一种做法是在将值类型传递给函数时使用一个托管指针。目前为止,唯一一种能够在 C#中创建托管指针的做法是在参数前使用“ref”关键字。这种做法确实能够应对某些场景的性能问题,但实际上 CLR 通过托管指针能够实现的功能远不止这些。

Ref 返回值与 Ref 本地变量这条提议中,提出了另外两种能够为 C#程序员所用的选项。

Ref 本地变量

假设有一个 int 类型的本地变量 a,这条提议允许你通过以下语法创建一个 Ref 本地变量:

ref int x = a;

类似于 ref 参数,ref 本地变量本质上就是它所指代的本地变量的某个别名而已,这种方式使你不必再生成它的拷贝。你也可以通过这种语法创建一个指向某个数组元素、或指向另一个对象的某个字段的指针。

ref int y = b[2];
ref int z = c.d;

在 CLR 术语中,Ref 本地变量被称为一个“TypedReference”(类型化引用)。一个 TypedReference 包含了指向某个地址的指针,同时也包含了该地址所能够存放的数据的类型信息。

按规定,一个 TypedReference 必须是一个参数或本地变量。这一规定是因为 CLR 不允许堆中的元素指向其它元素的内部。你也无法返回一个 TypedReference 对象,否则你就可以返回一个对本地对象的引用,而这个对象在函数结束后自然是已经不存在了。

Ref 返回值

这条提议的第二部分允许你在函数中返回 ref 引用,这就使以下场景变得可能:

public static ref TValue Choose(
Func condition, ref TValue left, ref TValue right)
{
return condition() ? ref left : ref right;
}
Matrix3D left = […], right = […];
Choose(chooser, ref left, ref right).M20 = 1.0;

通过使用这种新语法,以上的示例代码就不会对结构体进行任何拷贝操作,而是创建托管指针并在方法调用中进行传递。

与 ref 本地变量不同,要实现这一特性或许必须对 CLR 标准进行改动。正如之前所说,通常来说是不允许返回 TypedReference 对象的。从技术上讲你可以这么做,但这种操作不是类型安全的,其结果也是“无法检验的”。在受限安全设置中,使用未经检验的代码是不允许的,因为它可能会引起严重的 bug,因此一般只在 C 与 C++ 中使用。

为了缓解这一风险,这条提议中也表示,你所返回的引用必须指向堆中的某个对象,或是指向某个已经存在的 ref 或 out 参数。换句话说,编译器将强迫你不能够返回某个指向本地变量的引用。

查看英文原文: C# Futures: Managed Pointers

2015-05-05 09:573215
用户头像

发布了 428 篇内容, 共 193.5 次阅读, 收获喜欢 39 次。

关注

评论

发布
暂无评论
发现更多内容

ThreadLocal源码分析

Java 源码 多线程 ThreadLocal

超简单!Java 项目自动生成接口文档教程

Apifox

Java 接口文档 API 文档生成 自动生成

Typescript- 数据类型

格斗家不爱在外太空沉思

typescript 三周年连更

每个Java程序员都必须知道的四种负载均衡算法

Java 负载均衡 负载均衡算法

ARB链质押挖矿代币空投游戏dapp系统开发合约定制

开发微hkkf5566

终于有人把动态规划、冒泡排序、二叉树、链表、栈全部讲清楚了

Java你猿哥

数据结构 算法 二叉树 排序 LeetCode算法

品牌活动|行云创新出席“新工业·智物联”全国巡回 CEO 峰会

行云创新

行云创新 新工业 智物联 全国巡回CEO峰会珠海站

Java中的「接口」到底是什么?

海拥(haiyong.site)

三周年连更

天呐!我真的没想到推特GIF动图保存到手机相册竟然简单几步就能完成!

frank

twitter

面试官:介绍一下什么是缓存雪崩、缓存击穿、缓存穿透?

Java你猿哥

redis 面试题 缓存穿透 缓存击穿 缓存雪崩

拿来吧你!保姆级Docker底层原理及源码实战手册,上线点赞破10W

Java Docker 容器

全栈开发实战|Vue进阶——使用静态模块打包工具webpack

TiAmo

Vue webpack 三周年连更 静态模块打包

GitHub爆款!Java性能优化:轻松道破软件性能调优,不止搞定JVM

Java你猿哥

Java JVM Java性能优化

【Linux】firewall-cmd之防火墙简介及命令详解【附加实战⭐建议收藏!!⭐】

A-刘晨阳

Linux 防火墙 Firewalld防火墙 三周年连更

java 开发 SSM 框架整合之 MyBatis 动态 SQL

Java你猿哥

Java sql mybatis SSM框架 if

我认真总结并分析了Spring事务失效的十种常见场景

Java spring Spring事务

生物计算大模型技术在药物研发领域的应用

Baidu AICLOUD

生命科学 PaddleHelix

The Beacon链游NFT系统开发技术

薇電13242772558

NFT

超级详细|Linux系统下从0到1的玩法大全

浅羽技术

Linux unix 操作系统 命令 三周年连更

python中对象引用 | python小知识

AIWeker

Python python小知识 三周年连更

Mybatis返回集合类型到底是空集合还是null?源码解读

Java 源码 mybatis

GPU 加速药物研发与基因组学分析

Baidu AICLOUD

生命科学

《人间失格》

后台技术汇

三周年连更 人间失格

JSF源码分析(一)

京东科技开发者

spring jsf 企业号 4 月 PK 榜

阿里“妈宝级”之作,Kubernetes原理剖析与实战应用手册,太全了

Java Kubernetes k8s

一文详解RocketMQ-Spring的源码解析与实战

华为云开发者联盟

开发 华为云 华为云开发者联盟 企业号 4 月 PK 榜

浅谈智能语音交互

六月的雨在InfoQ

语音识别 语音合成 三周年连更 智能语音交互

ChatGPT及大模型专题研讨会在蓉成功举办共探前沿技术与产业发展

NLP资深玩家

中国边缘云公有云服务市场 Top2,百度智能云让智算无处不在

Baidu AICLOUD

分布式云

Android C++系列:C++11函数特殊特性

轻口味

c++ 三周年连更

华为云开源项目OpenTiny中TinyVue有什么优势?

英勇无比的消炎药

开源 Vue 组件库

C#的未来:托管指针_.NET_Jonathan Allen_InfoQ精选文章