C#如何安全、高效地玩转任何种类的内存之Span的本质

C#如何安全、高效地玩转任何种类的内存之Span的本质攻略

什么是Span

Span<T> 是 .NET Core 中新增的一种类型,它是一种类似于指针的结构体,表示一块连续的内存区域,其内容不一定是类型T的连续区域,可以是其他原语类型(如byte、int、long等)的连续区间。Span<T> 可以让我们高效地访问和读写内存在不进行垃圾回收的情况下,同时提高代码的可读性和安全性。

为什么要使用Span

在.NET Core中,Span<T>可以取代一部分App端耗费运行性能的,无法直接内联为CPU指令的Array类型(如byte[]、char[]等)。在某些场景下,使用Span比使用数组更快、更节省内存、更安全且易于维护。大多数情况下,Span可以完全替代传统Array类型。Span能够提供更快的数据访问速度,而且由于它并不在堆上分配内存,不会引发GC和堆内碎片。

Span的核心API

Span支持各种常见的API,比如基于范围(“range-based”)的访问、数组初始化、复制、遍历等等。以下是Span类型的几个重要API方法:

Slice

Slice方法可以创建一个新的Span,其所占据的连续内存段为当前原始Span所指定的一部分。从而可以通过该方法在Span中提供对子范围的非常高效的访问。

Span<byte> original = stackalloc byte[10];
original[0] = 1;
original[9] = 10;
Span<byte> slice = original.Slice(2, 6);
Console.WriteLine(slice[0]); // output is 3

Pin

针对临时的内存分配,Span还提供了一种手段——Pin,用于将Span关联起来的内存固定在内存中,防止GC在处理对象的过程中重复移动这个对象所提供的内存。如果你不经意间将 Span 的内存地址传递给其他代码,GC 稍后可能会移动该内存,导致应用程序崩溃。因此,通过固定内存而使其不可移动,即可避免该问题。

unsafe
{
    fixed (int* p = &source[0])
    fixed (int* q = &dest[0])
    {
        var src = new Span<int>(p, source.Length);
        var dst = new Span<int>(q, dest.Length);
        Span<int> slice = src.Slice(1, 2);
        MemoryExtensions.CopyTo(slice, dst);
    }
}

TryRead, TryWrite

TryRead和TryWrite方法能够更加高效地处理Span的访问。TryRead可以通过返回success值来判断是否成功读取,而不是抛出异常。TryWrite可以通过返回success值来判断是否成功写入,同时返回写入字节数。

Span<byte> buffer = new byte[4] { 1, 2, 3, 4 };
Span<int> casted = MemoryMarshal.Cast<byte, int>(buffer);

int val;
if(casted.TryRead(out val))
{
    Console.WriteLine(val);
}

Span的示例

数组快速排序

下面展示了使用Span实现的静态快速排序算法,其中排序的数组是int类型的。

public static void QuickSort(Span<int> span)
{
    if (span.Length <= 1)
    {
        return;
    }

    int pivotIndex = span.Length / 2;
    int pivotValue = span[pivotIndex];

    int left = 0;
    int right = span.Length - 1;

    while (left <= right)
    {
        while (span[left] < pivotValue)
        {
            left++;
        }

        while (span[right] > pivotValue)
        {
            right--;
        }

        if (left <= right)
        {
            int temp = span[left];
            span[left] = span[right];
            span[right] = temp;
            left++;
            right--;
        }
    }

    QuickSort(span.Slice(0, left));
    QuickSort(span.Slice(left));
}

比较两个Span

下面用举例的方式来展示比较两个Span的方法。

public static bool SequenceEqual(Span<byte> span1, Span<byte> span2)
{
    if (span1.Length != span2.Length)
    {
        return false;
    }

    for (int i = 0; i < span1.Length; i++)
    {
        if (span1[i] != span2[i])
        {
            return false;
        }
    }

    return true;
}

总结

Span是一个非常有用的数据类型,使用它有助于提高应用程序的性能和可读性。使用Span可以避免访问托管内存时的内存拷贝,提高程序的效率。Span API有助于简化代码,从而提高类型安全性。通过实践,Span也可以成为您的.NET Core开发工具箱中的一部分。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C#如何安全、高效地玩转任何种类的内存之Span的本质 - Python技术站

(0)
上一篇 2023年5月15日
下一篇 2023年5月15日

相关文章

  • C#百万数据查询出现超时问题的解决方法

    Alright,针对“C#百万数据查询出现超时问题的解决方法”的问题,我们可以考虑以下两个方面进行优化。 1.程序性能优化 2.数据库设计优化 下面将详细解释这两个方面的具体操作步骤。 1. 程序性能优化 1.1. 使用分页查询 针对大数据集合的查询,我们可以使用分页的方式进行查询。以每次查询 10000 条记录进行分页,将数据分成多个 10000 的批次,…

    C# 2023年5月15日
    00
  • C#实现操作windows系统服务(service)的方法

    C#实现操作Windows系统服务的方法,可以通过以下几个步骤来完成: 引入System.ServiceProcess命名空间 在代码文件中,使用以下代码引入System.ServiceProcess命名空间: using System.ServiceProcess; 创建服务的控制器类 public partial class Service1 : Ser…

    C# 2023年6月6日
    00
  • ubuntu16.4下用jexus部署ASP.NET Core环境

    Ubuntu 16.04下用Jexus部署ASP.NET Core环境 Jexus是一个高性能的Web服务器,支持多种Web技术,包括ASP.NET Core。在本攻略中,我们将介绍如何在Ubuntu 16.04下使用Jexus部署ASP.NET Core环境。 步骤一:安装Jexus 首先,需要安装Jexus。可以使用以下命令在Ubuntu 16.04中安…

    C# 2023年5月17日
    00
  • .NET 6线程池ThreadPool实现概述

    “.NET 6线程池ThreadPool实现概述”指 .NET 6 中线程池 ThreadPool 的实现方法和相关概念。本攻略将会对线程池的基础概念、线程池的创建、使用、回收等过程进行详细讲解,并提供两个示例说明以帮助读者深入理解。 1、线程池的基础概念 1.1 线程池概述 线程池是管理线程的一个集合。线程池中的所有线程统一由线程池管理,极大地降低了线程的…

    C# 2023年6月6日
    00
  • C#中Arraylist的sort函数用法实例分析

    C#中ArrayList的Sort函数用法实例分析 简介 C#中的 ArrayList 是一个动态数组,可以动态地增加或删除数组的元素,不需要提前设置数组的大小。同时,ArrayList 还提供了 Sort 方法来进行元素的排序。Sort 方法是利用快排来完成排序操作的。接下来,我们将详细讲解 C# 中 ArrayList 的 Sort 函数的使用方法。 S…

    C# 2023年6月7日
    00
  • .NET 个人博客系统

    前言 之前通过github学习了一个.net core的博客项目,最近也是完成了博客的备案,完善了一下。该项目是传统的MVC项目,可以进行主题的切换,采用Bootstrap进行前台页面的展示,有配套的后台管理系统,可以解析Markdown文件。 参观地址 ZY知识库可以将个人的意见评论到该文章,我可以采纳采纳。 采用技术 后端:.NET Core ORM:E…

    C# 2023年4月18日
    00
  • c#中判断字符串是不是数字或字母的方法

    在C#中,判断字符串是否为数字或字母,可以使用正则表达式或字符操作方法。 使用正则表达式 使用正则表达式可以方便地检验一个字符串是否符合某种格式,例如是否只包含数字或字母。 using System.Text.RegularExpressions; string str = "Hello1234"; bool isDigitOrLette…

    C# 2023年6月8日
    00
  • asp.net下定制日期输出格式的代码

    当在ASP.NET中输出日期时,默认情况下日期格式会是 “月/日/年” 或者 “日/月/年”,这样的输出格式不一定满足实际需要,我们可以通过一些代码的方式来定制日期输出格式。 下面是具体的攻略步骤: 1. 设置Globle.asax文件 在 ASP.NET 应用程序根目录下新建 Global.asax 文件,添加以下代码: <%@ Applicatio…

    C# 2023年5月31日
    00
合作推广
合作推广
分享本页
返回顶部