再探C 类与结构体究竟谁快——考虑栈变量、栈分配、位整数、密封类_第1页
再探C 类与结构体究竟谁快——考虑栈变量、栈分配、位整数、密封类_第2页
再探C 类与结构体究竟谁快——考虑栈变量、栈分配、位整数、密封类_第3页
再探C 类与结构体究竟谁快——考虑栈变量、栈分配、位整数、密封类_第4页
再探C 类与结构体究竟谁快——考虑栈变量、栈分配、位整数、密封类_第5页
已阅读5页,还剩15页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、再探C#类与结构体究竟谁快考虑栈变量、栈分配、64位整数、密封类 上次我对C#类与结构体做了一次速度评测(/zyl910/article/details/6788417)。经过一段时间思索,发现还可以进一步探讨第一、栈变量。上次的“硬编码”,是访问类中的静态变量的。若改为访问函数中的栈变量,性能会不会有所提高?第二、栈分配(stackalloc)。既然要测试栈变量,我们还可以顺便测试一下在栈上分配的内存块的访问性能。第三、64位整数。由于32位系统的成功,我们已经习惯了使用32位整数(int)。现在64位系统逐渐普及,我们得为此做好准备。对于指针操作时经常

2、要用到的偏移量增减运算来说,是使用32位整数,还是使用64位整数,或写两套代码?这需要测试后才能决定。第四、密封类(sealed)。听说密封类能提高性能,我们可以测试一下。有两种测试方式,一是为原来的派生类增加sealed关键字,二是专门另外写一个密封类。我决定同时使用这两种方法,分别测试其性能。一、测试代码测试代码如下?123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737

3、475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182

4、183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282

5、283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382

6、383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482

7、483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525using System; using System.Collections.Generic; using System.Text; using System.Diagnostics; namespace TryPointerCall / / 指针操作接口 / public interface IPointerCall / / 指针操作 /

8、 / 源指针 / 修改后指针 unsafe byte* Ptr(byte* p); #region 非泛型 / / 非泛型 指针操作基类 / public abstract class PointerCall : IPointerCall public abstract unsafe byte* Ptr(byte* p); / / 非泛型 指针操作派生类: 指针+偏移 / public sealed class PointerCallAdd : PointerCall / / 偏移值 / public int Offset = 0; public override unsafe byte* P

9、tr(byte* p) return unchecked(p + Offset); / / 非泛型 指针操作密封类: 指针+偏移 / public sealed class SldPointerCallAdd : IPointerCall / / 偏移值 / public int Offset = 0; public unsafe byte* Ptr(byte* p) return unchecked(p + Offset); / / 非泛型 指针操作结构体: 指针+偏移 / public struct SPointerCallAdd : IPointerCall / / 偏移值 / publ

10、ic int Offset; public unsafe byte* Ptr(byte* p) return unchecked(p + Offset); #endregion #region 泛型 / ! C#不支持将整数类型作为泛型约束 ! /public abstract class GenPointerCall : IPointerCall where T: int, long / / public abstract unsafe byte* Ptr(byte* p); / void d() / / / #endregion #region 全部测试 / / 指针操作的一些常用函数 /

11、 public static class PointerCallTool #if DEBUG private const int CountLoop = 10000000; / 循环次数 #else private const int CountLoop = 200000000; / 循环次数 #endif / / 调用指针操作 / / 具有IPointerCall接口的类型。 / 调用者 / 源指针 / 修改后指针 public static unsafe byte* CallPtr(T ptrcall, byte* p) where T : IPointerCall return ptrc

12、all.Ptr(p); public static unsafe byte* CallClassPtr(T ptrcall, byte* p) where T : PointerCall return ptrcall.Ptr(p); public static unsafe byte* CallRefPtr(ref T ptrcall, byte* p) where T : IPointerCall return ptrcall.Ptr(p); / C#不允许将特定的结构体作为泛型约束。所以对于结构体只能采用上面那个方法,通过IPointerCall接口进行约束,可能会造成性能下降。 /pub

13、lic static unsafe byte* SCallPtr(T ptrcall, byte* p) where T : SPointerCallAdd / / return ptrcall.Ptr(p); / private static int TryIt_Static_Offset; private static unsafe byte* TryIt_Static_Ptr(byte* p) return unchecked(p + TryIt_Static_Offset); / / 执行测试 - 静态调用 / / 文本输出 private static unsafe void Try

14、It_Static(StringBuilder sOut, int CountLoop) TryIt_Static_Offset = 1; / = 性能测试 = byte* p = null; Stopwatch sw = new Stopwatch(); int i; unchecked #region 测试 / 硬编码.栈变量 int iOffset = 1; sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = p + iOffset; sw.Stop(); sOut.AppendLine(string.Format(硬编码.栈

15、变量:t0, sw.ElapsedMilliseconds); / 硬编码.栈分配 int* pOffset = stackalloc int1; pOffset0 = 1; sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = p + pOffset0; sw.Stop(); sOut.AppendLine(string.Format(硬编码.栈分配:t0, sw.ElapsedMilliseconds); / 硬编码.静态 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p

16、 = p + TryIt_Static_Offset; sw.Stop(); sOut.AppendLine(string.Format(硬编码.静态:t0, sw.ElapsedMilliseconds); / 静态调用 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = TryIt_Static_Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(静态调用:t0, sw.ElapsedMilliseconds); #endregion / 测试 private static long

17、 TryIt_Static64_Offset; private static unsafe byte* TryIt_Static64_Ptr(byte* p) return unchecked(p + TryIt_Static64_Offset); / / 执行测试 - 静态调用 / / 文本输出 private static unsafe void TryIt_Static64(StringBuilder sOut, int CountLoop) TryIt_Static64_Offset = 1; / = 性能测试 = byte* p = null; Stopwatch sw = new

18、Stopwatch(); int i; unchecked #region 测试 / 硬编码.栈变量 long iOffset = 1; sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = p + iOffset; sw.Stop(); sOut.AppendLine(string.Format(64硬编码.栈变量:t0, sw.ElapsedMilliseconds); / 硬编码.栈分配 long* pOffset = stackalloc long1; pOffset0 = 1; sw.Reset(); sw.Start();

19、 for (i = 0; i CountLoop; +i) p = p + pOffset0; sw.Stop(); sOut.AppendLine(string.Format(64硬编码.栈分配:t0, sw.ElapsedMilliseconds); / 硬编码.静态 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = p + TryIt_Static64_Offset; sw.Stop(); sOut.AppendLine(string.Format(64硬编码.静态:t0, sw.ElapsedMilliseconds);

20、/ 静态调用 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = TryIt_Static64_Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(64静态调用:t0, sw.ElapsedMilliseconds); #endregion / 测试 / / 执行测试 - 非泛型 / / 文本输出 private static unsafe void TryIt_NoGen(StringBuilder sOut, int CountLoop) / 创建 PointerCallAdd pc

21、a = new PointerCallAdd(); SldPointerCallAdd dpca = new SldPointerCallAdd(); SPointerCallAdd spca; pca.Offset = 1; spca.Offset = 1; / 转型 PointerCall pca_base = pca; IPointerCall pca_itf = pca; IPointerCall dpca_itf = dpca; IPointerCall spca_itf = spca; / = 性能测试 = byte* p = null; Stopwatch sw = new St

22、opwatch(); int i; unchecked #region 调用 #region 直接调用 / 调用派生类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = pca.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用派生类:t0, sw.ElapsedMilliseconds); / 调用密封类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = dpca.Ptr(p); sw.Stop(); sOut.A

23、ppendLine(string.Format(调用密封类:t0, sw.ElapsedMilliseconds); / 调用结构体 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = spca.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用结构体:t0, sw.ElapsedMilliseconds); #endregion / 直接调用 #region 间接调用 / 调用基类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop;

24、+i) p = pca_base.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用基类:t0, sw.ElapsedMilliseconds); / 调用派生类的接口 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = pca_itf.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用派生类的接口:t0, sw.ElapsedMilliseconds); / 调用密封类的接口 sw.Reset(); sw.Start(); fo

25、r (i = 0; i CountLoop; +i) p = dpca_itf.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用密封类的接口:t0, sw.ElapsedMilliseconds); / 调用结构体的接口 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = spca_itf.Ptr(p); sw.Stop(); sOut.AppendLine(string.Format(调用结构体的接口:t0, sw.ElapsedMilliseconds); #endregio

26、n / 间接调用 #endregion / 调用 #region 泛型调用 #region 泛型基类约束 / 基类泛型调用派生类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallClassPtr(pca, p); sw.Stop(); sOut.AppendLine(string.Format(基类泛型调用派生类:t0, sw.ElapsedMilliseconds); / 基类泛型调用基类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallClas

27、sPtr(pca_base, p); sw.Stop(); sOut.AppendLine(string.Format(基类泛型调用基类:t0, sw.ElapsedMilliseconds); #endregion / 泛型基类约束 #region 泛型接口约束 - 直接调用 / 接口泛型调用派生类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallPtr(pca, p); sw.Stop(); sOut.AppendLine(string.Format(接口泛型调用派生类:t0, sw.ElapsedMilliseco

28、nds); / 接口泛型调用密封类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallPtr(dpca, p); sw.Stop(); sOut.AppendLine(string.Format(接口泛型调用密封类:t0, sw.ElapsedMilliseconds); / 接口泛型调用结构体 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallPtr(spca, p); sw.Stop(); sOut.AppendLine(string.Format

29、(接口泛型调用结构体:t0, sw.ElapsedMilliseconds); / 接口泛型调用结构体引用 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallRefPtr(ref spca, p); sw.Stop(); sOut.AppendLine(string.Format(接口泛型调用结构体引用:t0, sw.ElapsedMilliseconds); #endregion / 直接调用 #region 间接调用 / 接口泛型调用基类 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallPtr(pca_base, p); sw.Stop(); sOut.AppendLine(string.Format(接口泛型调用基类:t0, sw.ElapsedMilliseconds); / 接口泛型调用派生类的接口 sw.Reset(); sw.Start(); for (i = 0; i CountLoop; +i) p = CallPtr(pca_itf, p); sw.Stop(); sOut.AppendLine(string.Format(接口泛型调用派生类的接口:t0, sw.E

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论