.NET Core中妙用unsafe减少gc提升字符串处理性能

一、前言

昨天在群里讨论怎么样效率的把一个字符串进行反转,一般的情况我们都知道,只要对String对象进行操作, 那么就会生成新的String对象,比如"1"+"2" 这样的操作会生成新的String对象。

二、通正方案

通常我们要反转一个字符中我们都是使用如下方法:

static string Reverse1(string original)
{
    char[] arr = original.ToCharArray();
    Array.Reverse(arr);
    return new string(arr);
}

这种方式,只是通过将数组反转的方式重新排列了字符的顺序,最终还是要重新生成新的String对象,这样无疑会在数据量比较大的时候,会增加GC负担的。

三、unsafe方案

本文主要想讲述使用**unsafe**的方式来优化性能,当然在最后面还提到了**c# 7.0**中的新特性来实现相同功能。

unsafe关键字表示不安全上下文,该上下文是任何涉及指针的操作所必需的。有关更多信息,请参见不安全代码和指针(C# 编程指南)。

可以在类型或成员的声明中使用 unsafe 修饰符。因此,类型或成员的整个正文范围均被视为不安全上下文。

c#在默认情况下生成的都是安全代码,即进行了代码托管(.NET的CLR机制好处之一就是自动进行代码托管,适时的释放内存,程序员便不必考虑资源的回收问题),而此时,指针不能出现在安全代码的编译条件下。 如果因需要想在c#中使用指针,那么unsafe便是一个通道(当然在使用前,需在项目属性的生成选项中,选择“允许不安全代码”)。

直接上代码吧:

string hello = "hello world你好";

int len = hello.Length * 2;

fixed (char* strs = hello)
{
    byte* start = (byte*)strs;
    byte* end = start + len - 1;
    byte[] ch = new byte[2];
    if (start != null)
    {
        while (start < end)
        {
            ch[0] = *start;
            ch[1] = *(start + 1);

            *start = *(end-1);
            *(start+1) = *(end);

            start = start + 2;

            *(end - 1) = ch[0];
            *(end) = ch[1];

            end = end - 2;
        }
    }

}

fixed 语句设置指向托管变量的指针并在 statement 执行期间“钉住”该变量。如果没有 fixed 语句,则指向可移动托管变量的指针的作用很小,因为垃圾回收可能不可预知地重定位变量。C# 编译器只允许在 fixed 语句中分配指向托管变量的指针。(这句话是机器翻译的,呵呵)

好了最终的结果就是: hello="好你dlrow olleh" , 但是我们并没有new String哦!

四、C#7 Ref locals ?

其实对说新的C# 7.0来说,它为我们带来了新ref关键字,来处理本地引用(Ref locals )。

让我们来开一下脑洞,下面是段成立的代码:

string hello = "hello world你好";
ref char strRef = ref getStringArray(ss, 0);

static ref char getStringArray(char[] str,int index)
{
    return ref str[index];
}

strRef是什么?我们是不是可以通过这样的方式,来达到与使用指针相同的目地?请继续关注下一篇文章。

同时宣传一下我的新博客,当然博客园我也会更新的。  http://www.dotnet.ren

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏老九学堂

【超详细】Java入门学习进阶知识点汇总

入门阶段,主要是培养Java语言的编程思想。了解Java语言的语法,书写规范等,掌握Eclipse、MyEclipse等开发工具,编写Java代码的能力。学完这...

4045
来自专栏点滴积累

Scala 中方法扩展实践

这个名字不知道取得是否合适,简单来说要干的事情就是给某个类型添加一些扩展方法,此场景在各种语言中都会用到,比如 C# 语言,如果我们使用一个别人写好的类库,而又...

721
来自专栏Python爬虫与算法进阶

PEP8规则及Pycharm应用

PEP8 PEP是 Python Enhancement Proposal 的缩写,翻译过来就是 Python增强建议书 PEP8 是什么呢,简单说就是一种编码...

4065
来自专栏数据结构与算法

BZOJ2339: [HNOI2011]卡农(dp 容斥)

直接转移会非常麻烦,因为要同时限制集合不同 xor不为0,我们又不知道集合的具体元素。

691
来自专栏java学习

面试题63(链表,哈希表)

关于链表,哈希表 1·以下关于链式存储结构的叙述中哪一个是正确的? A.链式存储结构不是顺序存取结构 B.逻辑上相邻的节点物理上必须邻接 C.可以通过计算直接确...

3106
来自专栏Jimoer

java设计模式之代理模式

代理模式 代理模式是常见设计模式的一种,代理模式的定义是:为其他对象提供一种代理以控制对这个对象的访问。 在某些情况下,一个对象不适合或者不能直接引用另一个对象...

3245
来自专栏互联网技术栈

《Effective Java 》系列一

编写实例受控类有几个原因。实例受控使得类可以确保他是一个Singleton或者是不可实例化的。他还使得不可变类可以确保不会存在两个相等的实例。

1804
来自专栏码神联盟

java常见异常汇总

程序猿的成长之路,从这开始.......... ? 在6月的投票中,结果昨天已经出来了,大家多数的希望多推送一些java的基础知识。首先来一下热...

3936
来自专栏微信公众号:Java团长

Java中的String不再纠结

这个的运行结果是 true //解释:两个字符串的内容完全相同,因而指向常量池中的同一个区域 false //解释:每一次new都会创建一个新的对象 fals...

1172
来自专栏程序员宝库

这些 Java 面试题必须会---鲁迅

写在前面 春天来了,万物复苏的季节到了. 许多程序猿安奈不住生理需求,我要涨工资,我要跳槽. 毕竟金三银四嘛. 那么要从众多的面试者中获得求职机会,我们就要面对...

30610

扫码关注云+社区

领取腾讯云代金券