beforefieldinit释义(3)
1.看下面的例子:
public static class MyClass<T>
{
public static readonly DateTime Time = GetNow();
private static DateTime GetNow()
{
Console.WriteLine("GetNow execute!");
return DateTime.Now;
}
}
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Main execute!");
Console.WriteLine("int: " + MyClass<int>.Time);
Thread.Sleep();
Console.WriteLine("string: " + MyClass<string>.Time);
Console.ReadLine();
}
}
结果如下:
GetNow execute!
GetNow execute!
Main execute!
int: 2009/9/8 15:34:31
string: 2009/9/8 15:34:31
看上面的结果在Main函数执行之前GetNow就执行了,就取到了DateTime.Now,所以输出的时间是一样的。
2.我们在上面的MyClass中加一个静态的构造函数我们在来看结果:
public static class MyClass<T>
{
public static readonly DateTime Time = GetNow();
private static DateTime GetNow()
{
Console.WriteLine("GetNow execute!");
return DateTime.Now;
}
static MyClass() { }
}
结果如下:
Main execute!
GetNow execute!
int: 2009/9/8 15:40:12
GetNow execute!
string: 2009/9/8 15:40:15
我们可以发现每次的时间不同了。出现这种现象是由于当类没有静态构造函数的时候。在il中该类会被标记为BeforeFieldInit,这个是由编译器自动完成的。没有静态构造函数的时候初始化在刚进入方法的时候就发生了,而有静态函数的时候而且我们不需要做任何动作,只要有就可以,这个时候静态初始化在使用前才发生.我们可以通过看IL代码来证实这种现象,如下:
![]()
3.使用BeforeFieldInit会提高性能,下面我们就测试下,在测试我们需要计算代码执行时间,我们就是用老赵的组件,我稍稍做了一点修改,因为老赵用的win32 API是vista下的,为了以后查询方便,也贴下代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.Threading;
using System.Runtime.InteropServices;
namespace CSharpDemo
{
public static class CodeTimer
{
public static void Initialize()
{
Process.GetCurrentProcess().PriorityClass = ProcessPriorityClass.High;
Thread.CurrentThread.Priority = ThreadPriority.Highest;
Time("", , () => { });
}
public static void Time(string name, int iteration, Action action)
{
if (String.IsNullOrEmpty(name)) return;
// 1.
ConsoleColor currentForeColor = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine(name);
// 2.
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
int[] gcCounts = new int[GC.MaxGeneration + ];
for (int i = ; i <= GC.MaxGeneration; i++)
{
gcCounts[i] = GC.CollectionCount(i);
}
// 3.
Stopwatch watch = new Stopwatch();
watch.Start();
long cycleCount = GetCycleCount();
for (int i = ; i < iteration; i++) action();
long cpuCycles = GetCycleCount() - cycleCount;
watch.Stop();
// 4.
Console.ForegroundColor = currentForeColor;
Console.WriteLine("\tTime Elapsed:\t" + watch.ElapsedMilliseconds.ToString("N0") + "ms");
Console.WriteLine("\tCPU Cycles:\t" + cpuCycles.ToString("N0"));
// 5.
for (int i = ; i <= GC.MaxGeneration; i++)
{
int count = GC.CollectionCount(i) - gcCounts[i];
Console.WriteLine("\tGen " + i + ": \t\t" + count);
}
Console.WriteLine();
}
private static long GetCycleCount()
{
long l;
long kernelTime, userTimer;
GetThreadTimes(GetCurrentThread(), out l, out l, out kernelTime, out userTimer);
return kernelTime + userTimer;
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool GetThreadTimes(IntPtr hThread, out long lpCreationTime,
out long lpExitTime, out long lpKernelTime, out long lpUserTime);
[DllImport("kernel32.dll")]
static extern IntPtr GetCurrentThread();
}
}
下面我们开始测试,我们准备两个类:
public class MarkBeforeFieldInit
{
public static string test;
}
public class NoBeforeFieldInit
{
public static string test;
static NoBeforeFieldInit()
{
}
}
测试代码如下:
class Program
{
static void Main(string[] args)
{
CodeTimer.Initialize();
int iteration = * *;
CodeTimer.Time("MarkBeforeFieldInit", iteration, () => { MarkBeforeFieldInit.test = "test"; });
CodeTimer.Time("NoBeforeFieldInit", iteration, () => { NoBeforeFieldInit.test= "test"; });
CodeTimer.Time("MarkBeforeFieldInit2", iteration, () => { MarkBeforeFieldInit.test = "test"; });
CodeTimer.Time("NoBeforeFieldInit2", iteration, () => { NoBeforeFieldInit.test = "test"; });
}
}
结果如下:
![]()
![]()

可以看出BeforeFieldInit方式的执行速度确实快,但为什么第二次执行的速度差不多呢?因为经过第一次执行后JIT编译器知道类型的构造器已经被调用了,所以第二次执行时不会显示对构造函数进行调用。
beforefieldinit释义(3)的更多相关文章
- beforefieldinit释义(2)
首先来看一段代码: using System; namespace BeforeFieldInit { internal class Foo { Foo(){ Console.WriteLine(&q ...
- beforefieldinit释义
首先让我们认识什么是,当字段被标记为beforefieldinit类型时,该字段初始化可以发生在任何时候任何字段被引用之前.这句话听起了有点别扭,接下来让我们通过具体的例子介绍. /// <su ...
- 常见linux命令释义(第八天)—— Bash Shell 的操作环境
换了新公司,公司的领导很不错.自己感受比较多的地方是,自己的工作效率明显比以前高了.以前会对频繁变动的需求十分不耐烦,现在接到需求后会仔细的思考,进行整体构建.即使以后需求有变动,也能够比较轻易的在原 ...
- 常见linux命令释义(第三天)
今天晚上看鸟哥的私房菜,边学边写笔记. 在linux中压缩大多是.tar, .tar.gz , .tgz, /gz, .bz2等. .gz 是通过gzip压缩的文件. .bz2 是通过bzip2压缩的 ...
- 常见linux命令释义(第一天)
快到中午吃饭了,然后忽然想起来samba里面没有添加用户.于是乎,就玩弄起了samba. Samba三下五除二就安装好了,想想window里面不断的点击下一步,还要小心提防各种隐藏再角落里的绑定软件. ...
- Tomcat的目录结构、处理流程、主配置文件(server.xml)释义
参考资料: http://www.cnblogs.com/xdp-gacl/p/3744053.html http://grass51.blog.51cto.com/4356355/1123400 1 ...
- 使用Perl5获取有道词典释义
Get Word Definition from dict.youda.com via Perl Script 获取基本释义 Get Basic Definition http://dict.youd ...
- Web前端名词释义及原理
引言:看题目的时候,不要觉得这是一个很深奥的问题,Web前端这些东西很多就是叫的名字牛逼,其实原理很TM简单,也就那么回事. 一.javascript名词释义 1.啥是事件队列? 就是 弄一个数组,里 ...
- linux内核的冒险md来源释义# 14raid5非条块读
linux内核的冒险md来源释义# 14raid5非条块读 转载请注明出处:http://blog.csdn.net/liumangxiong 假设是非条块内读.那么就至少涉及到两个条块的读,这就须要 ...
随机推荐
- linux进程间通信之管道篇
本文是对http://www.cnblogs.com/andtt/articles/2136279.html管道一节的进一步阐释和解释 1 管道 1.1 管道简介 管道是unix系统IPC的最古老的形 ...
- Java - 文件(IO流)
Java - 文件 (IO) 流的分类: > 文件流:FileInputStream | FileOutputStream | FileReader | FileWriter ...
- mysql命令学习笔记(1):show table status like 'user';显示表的相关信息
show table status like 'user';显示表的相关信息 +------------+--------+---------+------------+------+-------- ...
- eclipse.ini内存设置
这两天用eclipse,突然变得很卡,就上网找了些资料,对eclipse.ini启动参数配置,整理如下: 1.先了解下JVM内存管理机制,JVM内存分为堆内存和非堆内存 2.JVM内存限制 首先JVM ...
- js库开发--参数传递及方法修改
<!DOCTYPE html><html> <head> <meta charset="UTF-8"> ...
- oracle使用exp与imp在本地导入导出数据
导出: exp user/password owner=user file=你要输出的目录以及文件名,后缀为dmpexp IOTMON/iotmon owner=QSMES file=/home/or ...
- 设置启动页面-Launch Image
一.添加启动图 二.拖入相应尺寸的图片 图片必须是png格式的.不同机型需要的图片的尺寸: iPhone4.4s-@2x 3.5寸 640*960 iPhone5.5s.5c-@2x 4.0寸 640 ...
- poj-2403-cup
题目描述 The WHU ACM Team has a big cup, with which every member drinks water. Now, we know the volume o ...
- R - 递推
Description 我们看到过很多直线分割平面的题目,今天的这个题目稍微有些变化,我们要求的是n条折线分割平面的最大数目.比如,一条折线可以将平面分成两部分,两条折线最多可以将平 ...
- G - Reduced ID Numbers(第二季水)
Description T. Chur teaches various groups of students at university U. Every U-student has a unique ...