Managed空间

彭刚的blog
随笔 - 26, 评论 - 153, 引用 - 81

导航

标签

每月存档

最新留言

广告

Whidbey中类型检查和Cast的JIT 优化

使用Collection<基类>来存储继承类是一个常见的模式。在理想的设计中,基类应当定义用户所需要使用的所有接口。这样通过多态性,不同的继承类可以有不同的行为。然而在现实中,我们往往需要使用类型检查或Cast来判断对象的具体类型, 然后根据不同的类型进行不同的操作。

    if( obj.GetType() == typeof(BaseClass)) {

       

}

   

    Derived d (DerivedbaseObj;

   

    Derived d baseObj as Derived;

 

WhidbeyJIT编译器对这两种情况进行了优化。下面是一段C#代码(仅作说明使用):

 

using System;

class Test {

    public static void Main() {

        Console.ReadLine();

        object o = "abcd";

        if(o.GetType() == typeof(string)) {

            string s = (string)o;

            Console.WriteLine(s);

        }

    }

}  

 

 

相应的汇编代码如下:

CLR 1.1:

; code for type check

06f80066 8b350417ac05     mov     esi,[05ac1704] ("abcd")

06f8006c 8bce             mov     ecx,esi

06f8006e 3909             cmp     [ecx],ecx

06f80070 ff15b0c3b779  call dword ptr [mscorlib_79980000+0x1fc3b0 (79b7c3b0)] (System.Object.GetType)

06f80076 b9f8dab779    mov     ecx,0x79b7daf8 (MT: System.String)

06f8007b 89442404      mov     [esp+0x4],eax

06f8007f e8c7152772    call mscorwks!COMClass::GetClassFromHandle (791f164b)

06f80084 8b542404         mov     edx,[esp+0x4]

06f80088 3bd0             cmp     edx,eax

06f8008a 751c             jnz     06f800a8

 

; code for cast

06f8008c 8bd6             mov     edx,esi

06f8008e b9f8dab779       mov     ecx,0x79b7daf8 (MT: System.String)

06f80093 e8840b2772       call    mscorwks!JIT_ChkCastClass (791f0c1c)

 

Whidbey:

; code for type check

0377007e 8b351c20ac01     mov     esi,[01ac201c] ("abcd")

03770084 8bce             mov     ecx,esi

03770086 baf4adba78       mov     edx,0x78baadf4 (MT: System.String)

0377008b e8204b0876       call    mscorwks!JIT_IsObj_Typehandle (797f4bb0)

03770090 85c0             test    eax,eax

03770092 743f             jz      image00400000!Test.Main()+0x63 (037700d3)

  

;code for cast

03770094 85f6             test    esi,esi

03770096 741a             jz      image00400000!Test.Main()+0x42 (037700b2)

03770098 813ef4adba78     cmp     dword ptr [esi],0x78baadf4

0377009e 7502             jnz     image00400000!Test.Main()+0x32 (037700a2)

037700a0 eb0e             jmp     image00400000!Test.Main()+0x40 (037700b0)

037700a2 8bd6             mov     edx,esi

037700a4 b9f4adba78       mov     ecx,0x78baadf4 (MT: System.String)

037700a9 e8a0522976       call    mscorwks!JIT_ChkCastClass (79a0534e)

037700ae 8bf0             mov     esi,eax

037700b0 eb00             jmp     image00400000!Test.Main()+0x42 (037700b2)

 

相对与1.1而言,Whidbey上类型检查的汇编代码简单了许多。对常见的对象而言,JIT_IsObj_Typehandle仅仅是将对象MethodTable(储存在每个对象的开头)和一个固定的值进行比较。所以在Whidbey上类型检查速度提高了很多。

 

WhidbeyCast的汇编代码反而更大。但是在通常情况下速度会有所提高。原因是如果Cast的成功时,JIT_ChkCastClass不会被调用。JIT_ChkCastClass的基本工作是比较对象的MethodTable和指定的MethodTable,在不匹配时获取父类的MethodTable继续进行比较。所以在类的层次(Hierarchy)很深时,JIT_ChkCastClass会较费时间。

 

理论上而言。Whidbey所生成的代码还有改进的余地。因为从上下文可以知道这里的Cast一定会成功。所以Cast的代码完全没有必要。希望在以后的版本中能得到改进。

 

posted on 2004-07-20 10:32:00 by gangp  评论(8) 阅读(3576)

System.Threading.Timer与System.Timers.Timer的区别

当系统中有活跃的System.Threading.Timer对象,CLR会建立一个Timer线程。

该线程获得执行权时会查询系统中注册的所有System.Threading.Timer对象并

调用相应的回调函数。

1.01.1中,System.Timers.Timer使用windows提供的Waitable Timer。所以System.Timers.TimerSystem.Threading.Timer的实现不同。

Whidbey System.Timers.Timer使用System.Threading.Timer。区别在于System.Timers.Timer可以用于可视化的插入窗体中。

posted on 2004-07-18 14:27:00 by gangp  评论(16) 阅读(10796)

Method Inlining

函数调用有一定的代价:参数需要保存到堆栈上或寄存中(在可能的情况下JIT使用ecxedx来传递前俩个参数),执行函数的prologepilog也需要一定的时间。Inlining可以避免函数调用的代价,然而CLRJIT inliner较为保守。下面是一些最重要的规则:

l           IL代码大于32字节的函数不被inline

l           虚拟函数(virtual method)调用或接口函数(interface method)调用不被inline

l           使用复杂的程序流控制的函数不被inline。复杂的程序流控制指if/then/else之外的流控制语句。

l           包含异常处理快的方法和产生异常的方法不被inline。可以将throw语句移到一个独立的函数中来避免这个问题。下面是一个例子:

        public T this[int index] {

            get {

                // Fllowing trick can reduce the range check by one

                if ((uint) index >= (uint)_size) { ThrowHelper.ThrowIndexOutOfRangeException();}

                return _items[index];

            }

        }

l           包含值类型参数的方法不被inline

注意不要为了inline一个方法而牺牲程序的正确性。同时要注意inline较大的函数可能导致工作集的增长。

如果你读过如下的文章:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dndotnet/html/highperfmanagedapps.asp

你会注意到我基本上是翻译了该文章的一部分。不过注意有分歧的地方可以假设我的信息更准确。:)

posted on 2004-07-17 09:51:00 by gangp  评论(10) 阅读(5059)

减少范围检查(range check)的小Trick

 接受非负整数为参数的方法通常需要做范围检查。下面是一个例子(ArrayList.RemoveAt):

        public virtual void RemoveAt(int index) {

            if (index < 0 || index >= _size) {

throw new ArgumentOutOfRangeException("index");

            }

                    

        }

实际上这里并不需要两次检查。如下的代码可以起到相同的作用:

        public virtual void RemoveAt(int index) {

            if ((uint)index >= _size) {

throw new ArgumentOutOfRangeException("index");

            }

                    

        }

当然不到必要的时候不要使用这个Trick因为这会降低程序的可读性。

 

posted on 2004-07-17 08:20:00 by gangp  评论(11) 阅读(3245)

System.Collections.Generic.ICollection与System.Collections.ICollection的区别

    public interface ICollection : IEnumerable {

           void CopyTo(Array array, int index);

           int Count { get; }

           Object SyncRoot { get; }

           bool IsSynchronized     { get; }

}

 

    public interface ICollection : IEnumerable {

        int Count { get; }

        bool IsReadOnly { get; }

        void Add(T item);

        void Clear();

        bool Contains(T item);

        void CopyTo(T[] array, int arrayIndex);                

        bool Remove(T item);

}

ICollection相比,泛型ICollection接口中增加了许多方法。ICollection中的方法太少,所以实际上没有什么用处。ICollecion使定义新的Collection(比如LinkedListTree可以实现ICollection<T>)更加方便。

 

Synchronization有关的方法被去掉了,原因是使用Framework提供的Wrapper并不能保证正确的Synchronization. 下面是一个例子:

         Hashtable hashtable = Hashtable.Synchronized(new Hashtable());  

      if(!hashtable.Contains(key)) {

              hashtable.Add(key, value);

}

Add方法还是有可能产生异常。用户有更多的信息来决定什么时候需要使用lock以及lock的范围。

 

例外Remove方法返回bool,用于指明指定的值是否存在于Collection中。

posted on 2004-07-08 09:49:00 by gangp  评论(8) 阅读(4577)

Powered by: Joycode.MVC引擎 0.5.2.0