重新学.Net[四]——效率和安全
生活随笔
收集整理的這篇文章主要介紹了
重新学.Net[四]——效率和安全
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
用.Net就不得不考慮效率問題(這點和Java一樣),到底有沒有這種性能問題?性能問題有多大?而微軟一直聲稱托管程序是安全的,這種安全性到底是指的什么東西?達到這種安全到底付出了什么東西?我一直對這些問題很迷惑,最近看了一些書后有一些理解,僅僅是理解,歡迎大家來討論。
要比效率,通常都是與C++相比。毫無疑問,除了極少的情況下,托管的程序與傳統C++程序相比,效率有所降低,這種降低我個人覺得來源于以下幾個方面:
1.就是從FCL的設計中看。FCL是完全面向對象設計的,它始終強到安全和異常處理。舉個很簡單的例子,C++的數組是一段連續的內存空間(棧或堆),而.Net(更嚴格說是CTS)中的數組是一個類(其實在定義上它是不同于類的一個引用型的東西,但其實不會有太多區別)。為了維護這個類的易操作性和更好的支持異常處理。在很多語言(以下就說C#)多做了很多其他工作。比如會默認初始化,在下標獲取的時候會做越界的異常判斷。這些都會耗費時間(C++中也有完全面向對象的庫,這些庫的情況也一樣)。但是個人覺得,這部分效率,很多時候和使用場所,和編碼者對所用語言的理解相關的。比如在需要為C++的數組初始化的場合要用賦值,效率還不如默認初始化。而在C#中,個人理解對效率也起到很重要的作用。比如為了滿足非0初值的數組,有人會全部重新初始化,有人會取值然后加一個底數,根據場合不同,這兩種方式的效率是不同的(考慮遍歷和少數訪問當情況)。再比如,在文件操作中有靜態的File類和可實例化的FileInfo類。在反復對同一個文件進行copy的時候,我們應該選用FileInfo類,因為它只在實例化的時候進行異常檢查,而靜態的方法會每次操作都做這些檢查。這樣就降低了性能。總之,很多時候對類庫的理解和正確使用會很大程度上影響的效率。C++不被好好的用也會寫出很慢的程序。
2.JIT方式導致的性能損失。如果上面那部分有人的因素,那么這部分就幾乎是天然的。JIT的性能損失可以從兩個角度看,一個是第一次調用時會需要二次編譯。這無疑會造成性能損失。但這種損失有時候是值得的,比如如果是一個新型的CPU,JIT可能更好利用其新的指令,編譯出符合它特點的機器碼,反而提升了性能(在框架程序一書中還列舉了其他可能),這也就是有人說JIT方式理論上能超越C++程序性能的來源(至少不是不可能)。但總而言之,根據計算機程序的特點(通常會反復調用一些方法,80/20原理),JIT方式不會造成太大的性能損失。并且,如果你實在無法容忍,你可以NGEN提前編譯成機器碼再運行。但,很多時候是不推薦的。為什么不推薦這種方式呢?因為它會損失JIT的其它好處,就是安全性。JIT在編譯中會做驗證和安全性檢查。所謂驗證就是檢查代碼會不會跳出AppDomain的范圍,避免了C++中一個不慎將指針指出界或者使用野指針造成的不可預知的錯誤。而安全性檢查,指通過操作系統管理員的配置,可以控制JIT的權利。比如,不編譯IO操作的代碼,不允許其訪問網絡等等。與之相比,傳統的程序一旦運行就無法控制(考慮一下,你運行了一個病毒exe,除了殺毒你還能干什么),而托管的程序,即使運行起來也可以控制(運行了又怎么樣,不讓你寫我看你能干什么),從根源上堵住了惡意程序,這就是微軟始終強調的安全性編碼。只有應用JIT編譯,才能實現(覺得很酷的方式,只要在操作系統中良好配置,就可以保證安全,很多防火墻軟件以后估計要下崗了)。同樣,這也需要損失一些性能,但是,如果你不需要,可以強行關閉(操作系統管理員的權利)。
3.最后是垃圾回收導致。因為垃圾回收會需要切換線程,打擾程序的運行。這部分性能我也不知道有多大的損失,總之微軟說不大。
總之,托管的方式確實會造成一定的損失,但是這種損失在很多手段的運用下一步步減少。同時不要忘了,它提供了更安全的編碼(比如在編碼過程中,如果越界可以很快的發現,不會頭痛不已)和運行方式。我覺得,在很多場合,也許這種性能的降低不會成為你用.Net編程的阻礙。
本文轉自 duguguiyu 51CTO博客,原文鏈接:http://blog.51cto.com/duguguiyu/361615,如需轉載請自行聯系原作者
要比效率,通常都是與C++相比。毫無疑問,除了極少的情況下,托管的程序與傳統C++程序相比,效率有所降低,這種降低我個人覺得來源于以下幾個方面:
1.就是從FCL的設計中看。FCL是完全面向對象設計的,它始終強到安全和異常處理。舉個很簡單的例子,C++的數組是一段連續的內存空間(棧或堆),而.Net(更嚴格說是CTS)中的數組是一個類(其實在定義上它是不同于類的一個引用型的東西,但其實不會有太多區別)。為了維護這個類的易操作性和更好的支持異常處理。在很多語言(以下就說C#)多做了很多其他工作。比如會默認初始化,在下標獲取的時候會做越界的異常判斷。這些都會耗費時間(C++中也有完全面向對象的庫,這些庫的情況也一樣)。但是個人覺得,這部分效率,很多時候和使用場所,和編碼者對所用語言的理解相關的。比如在需要為C++的數組初始化的場合要用賦值,效率還不如默認初始化。而在C#中,個人理解對效率也起到很重要的作用。比如為了滿足非0初值的數組,有人會全部重新初始化,有人會取值然后加一個底數,根據場合不同,這兩種方式的效率是不同的(考慮遍歷和少數訪問當情況)。再比如,在文件操作中有靜態的File類和可實例化的FileInfo類。在反復對同一個文件進行copy的時候,我們應該選用FileInfo類,因為它只在實例化的時候進行異常檢查,而靜態的方法會每次操作都做這些檢查。這樣就降低了性能。總之,很多時候對類庫的理解和正確使用會很大程度上影響的效率。C++不被好好的用也會寫出很慢的程序。
2.JIT方式導致的性能損失。如果上面那部分有人的因素,那么這部分就幾乎是天然的。JIT的性能損失可以從兩個角度看,一個是第一次調用時會需要二次編譯。這無疑會造成性能損失。但這種損失有時候是值得的,比如如果是一個新型的CPU,JIT可能更好利用其新的指令,編譯出符合它特點的機器碼,反而提升了性能(在框架程序一書中還列舉了其他可能),這也就是有人說JIT方式理論上能超越C++程序性能的來源(至少不是不可能)。但總而言之,根據計算機程序的特點(通常會反復調用一些方法,80/20原理),JIT方式不會造成太大的性能損失。并且,如果你實在無法容忍,你可以NGEN提前編譯成機器碼再運行。但,很多時候是不推薦的。為什么不推薦這種方式呢?因為它會損失JIT的其它好處,就是安全性。JIT在編譯中會做驗證和安全性檢查。所謂驗證就是檢查代碼會不會跳出AppDomain的范圍,避免了C++中一個不慎將指針指出界或者使用野指針造成的不可預知的錯誤。而安全性檢查,指通過操作系統管理員的配置,可以控制JIT的權利。比如,不編譯IO操作的代碼,不允許其訪問網絡等等。與之相比,傳統的程序一旦運行就無法控制(考慮一下,你運行了一個病毒exe,除了殺毒你還能干什么),而托管的程序,即使運行起來也可以控制(運行了又怎么樣,不讓你寫我看你能干什么),從根源上堵住了惡意程序,這就是微軟始終強調的安全性編碼。只有應用JIT編譯,才能實現(覺得很酷的方式,只要在操作系統中良好配置,就可以保證安全,很多防火墻軟件以后估計要下崗了)。同樣,這也需要損失一些性能,但是,如果你不需要,可以強行關閉(操作系統管理員的權利)。
3.最后是垃圾回收導致。因為垃圾回收會需要切換線程,打擾程序的運行。這部分性能我也不知道有多大的損失,總之微軟說不大。
總之,托管的方式確實會造成一定的損失,但是這種損失在很多手段的運用下一步步減少。同時不要忘了,它提供了更安全的編碼(比如在編碼過程中,如果越界可以很快的發現,不會頭痛不已)和運行方式。我覺得,在很多場合,也許這種性能的降低不會成為你用.Net編程的阻礙。
本文轉自 duguguiyu 51CTO博客,原文鏈接:http://blog.51cto.com/duguguiyu/361615,如需轉載請自行聯系原作者
總結
以上是生活随笔為你收集整理的重新学.Net[四]——效率和安全的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django View使用装饰器捕获数据
- 下一篇: 定制zabbix的rpm包---spec