為什麼java反射慢(java速度慢)

本文目錄一覽:

Java反射到底慢在哪

其實慢的原因還有安全檢查,訪問控制等。比如說這個方法你能不能獲得,能不能執行等,你傳進的參數的類型檢查等。 比如說在使用反射調用方法的時候,傳進的參數需要檢查是否符合方法參數類型要求吧? 可以通過緩存一些方法來提高速度和性能

Java反射的性能為什麼比直接調用慢一個數量級左右

反射肯定比直接調用慢

這個毋庸置疑了,我這篇文章也不是證明反射有多高效的。

現在的快遞哥很火,那我們就舉個快遞的例子。如果快遞員就在你住的小區,那麼你報一個地址:xx棟xx號,那麼快遞員就可以馬上知道你在哪裡,直接就去到你家門口;但是,如果快遞員是第一次來你們這裡,他是不是首先得查查百度地圖,看看怎麼開車過去,然後到了小區是不是得先問問物管xx棟怎麼找,然後,有可能轉在樓下轉了兩個圈才到了你的門前。

我們看上面這個場景,如果快遞員不熟悉你的小區,是不是會慢點,他的時間主要花費在了查找百度地圖,詢問物業管理。OK,反射也是一樣,因為我事先什麼都不知道,所以我得花時間查詢一些其他資料,然後我才能找到你。大家有興趣可以查看反射的實現原理,以及MetaData的相關概念。

反射到底比直接調用慢多少?

好了,我們知道反射肯定慢的,那麼是不是反射就不能用了呢?有些人一聽到慢,就非常着急的下結論,反射怎樣怎樣不行,怎樣怎樣不能用。但是,同學,反射到底比直接調用慢多少,你造嗎,能給我個實際的數據嗎?很多人其實對性能只有個模糊的概念,而沒有數值支撐。之前我給同事找了一個動態解析表達式的類庫,他覺得不太好用,他很聰明,很快的找到了用DataTale.Compute可以實現公式的動態解析。我問他,這個方法和我給的類庫性能上有什麼區別?他跟我說,這個已經很快了,執行1秒都不到。我一聽,就覺得不對勁,你的思想還停留在秒級,跟我談什麼性能?

怎麼去判斷一個函數的性能?因為函數的執行太快太快了,你需要一個放慢鏡,這樣才能捕捉到他的速度。怎麼做?把一個函數執行一百萬遍或者一千萬遍,你才能真正了解一個函數的性能。也就是,你如果想判斷性能,你就不能還停留在秒級,毫秒級的概念,你必須用另外一個概念替代,才能知道真正的性能。結果我同事把這兩種方法執行了100w遍,確實,我提供的類庫比他的快了8秒。

好了,現在拿我早兩天提供的工廠方法來做測試,其中CodeTimer的實現參考趙大神的文章《一個簡單的性能計數器:CodeTimer》:

測試方法如下:

代碼如下

複製代碼

[Test]

public void TestReflector()

{

CodeTimer.Time(“Direct”, 100 * 10000,

() =

{

var instance = new ConnectionTest();

});

CodeTimer.Time(“Reflect”, 100 * 10000,

() =

{

this.GetType().Assembly.CreateInstance(“TestPropertyGrid.ConnectionTest”);

});

}

測試結果如下:

Direct

Time Elapsed: 25ms

CPU Cycles: 57,582,163

Gen 0: 14

Gen 1: 0

Reflect

Time Elapsed: 3,231ms

CPU Cycles: 8,001,720,795

Gen 0: 269

Gen 1: 1

看到沒,我們的放大鏡起作用了,現在我們大概可以下這麼一個結論:在執行100萬遍的時候,反射大概把直接調用慢50~100倍。100倍,咋一看,是相差很大的,但是,我前文說了,別著急下結論,你要看看前提條件。自古我們就喜歡斷章取義,比如“以德報怨”這個成語,好像古人說讓我們遇到不好的,你不能怨恨,要更好的對待他人,別人打你左臉一巴掌,你應該把右臉伸過去讓他再打一下。但實際這個成語是怎樣的呢?

或曰:“以德報怨,何如?”

子曰:“何以報德?以直報怨,以德報德”

老孔的意思其實是如果別人對你好,那麼你就對他好,要是他招你惹你了,你就干他娘的!你看,傻眼了吧?

有多少情況下需要考慮反射帶來的影響?

我認為這個情況是非常非常少的,絕大多數的我們根本就無需考慮這個。就上我上一篇文章提到的工廠,你程序有多少個實體,有100萬個嗎?如果你只是在彈出窗口的時候new一下,這個百萬分之十秒的影響對你很重要嗎?

另外,有些人講,我要是真有這種需求,要把一個對象new一百萬遍,那不還是慢嗎?這種情況有沒有,有!比如我有100w條記錄,需要取出來,然後通過反射賦值到一個Model類中。

但是對於這種情況,如果你真是這麼想的話,我只能說,你坐辦公室坐久了,腦袋生鏽了,該去爬爬山,泡泡妞了。如果你需要對一個對象反射一百萬遍,那麼你就應該緩存這個對象了。拿我們上面那個例子來說,如果這個快遞員給小區的人送一百萬遍的快遞還認不得路,每次都還得百度地圖,然後問物業管理,你丫的你還沒把他開掉了,那你腦袋不是秀逗了,要不就是任性的有錢人。

上面代碼如果緩存之後執行一百萬遍,跟直接調用有多大的區別?我這裡就不貼代碼了,免得你們直接看結果沒有意思,自己把代碼敲一遍,印象更深刻。

那麼,還有沒有更快的辦法,有。比如你的快遞員開始用的是IPHONE4,現在可以考慮給他買個6+。在.net中,提供了Emit的相關方法來讓你更快的反射。這裡送你一個通過反射快速給Model賦值的輪子“Dapper”,自己回家造去。

編程中是否應該使用反射?

其實看完上面的文字,我相信你們都有了一個初步的判斷,而我的看法是:絕大多數的情況下你都可以用反射。

如果你覺得是因為反射導致你程序慢的話,那麼,請先用放慢鏡好好觀察一下,到底是不是反射的問題。如果你確定是反射的問題,那麼你再好好的考慮下是不是你沒有用對反射,是不是像上面那個走了一百萬遍都不認識路的快遞員一樣。最後,如果你覺得性能上還是不夠,那麼我建議你升級下硬件吧,把硬件性能上升個3%總好過你請個牛逼的工程師來幫你做這種極限的優化,有一句話我覺得很對“工程師比服務器要昂貴的多”。如果你還非得跟我較勁,那麼,沒辦法了,你程序對性能的要求已經超出了本文討論的範疇,如果你真有這種需求了,我覺得你也沒有必要看我這篇文章了,因為你已經足夠牛逼到對系統語言都有深入了解了。

大多時候,我們會把程序的性能歸結於編程語言,或者使用了反射等技術,而甚少去關心自己的代碼,這種心態會導致你技術的發展越來越緩慢,因為你已經失去了求知的慾望,以及一顆追求技術進步的心。請你記住,更多的時候,影響我們程序性能的,是你編程的思想,你對待編碼的態度!

總結

好吧,說了這麼多,估計很多人直接就拖到文章末尾然後因為文章碼了這麼多字而默默點了個贊,那麼,我在最後給大家奉獻一下本文的精華:

反射大概比直接調用慢50~100倍,但是需要你在執行100萬遍的時候才會有所感覺

判斷一個函數的性能,你需要把這個函數執行100萬遍甚至1000萬遍

如果你只是偶爾調用一下反射,請忘記反射帶來的性能影響

如果你需要大量調用反射,請考慮緩存。

你的編程的思想才是限制你程序性能的最主要的因素

Java 反射到底慢在哪裡?

其實慢的原因還有安全檢查,訪問控制等。比如說這個方法你能不能獲得,能不能執行等,你傳進的參數的類型檢查等。

比如說在使用反射調用方法的時候,傳進的參數需要檢查是否符合方法參數類型要求吧?

可以通過緩存一些方法來提高速度和性能

原創文章,作者:UKBBW,如若轉載,請註明出處:https://www.506064.com/zh-hant/n/329380.html

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
UKBBW的頭像UKBBW
上一篇 2025-01-14 18:55
下一篇 2025-01-14 18:55

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • java client.getacsresponse 編譯報錯解決方法

    java client.getacsresponse 編譯報錯是Java編程過程中常見的錯誤,常見的原因是代碼的語法錯誤、類庫依賴問題和編譯環境的配置問題。下面將從多個方面進行分析…

    編程 2025-04-29
  • Java騰訊雲音視頻對接

    本文旨在從多個方面詳細闡述Java騰訊雲音視頻對接,提供完整的代碼示例。 一、騰訊雲音視頻介紹 騰訊雲音視頻服務(Cloud Tencent Real-Time Communica…

    編程 2025-04-29
  • Java Bean加載過程

    Java Bean加載過程涉及到類加載器、反射機制和Java虛擬機的執行過程。在本文中,將從這三個方面詳細闡述Java Bean加載的過程。 一、類加載器 類加載器是Java虛擬機…

    編程 2025-04-29
  • Java Milvus SearchParam withoutFields用法介紹

    本文將詳細介紹Java Milvus SearchParam withoutFields的相關知識和用法。 一、什麼是Java Milvus SearchParam without…

    編程 2025-04-29
  • Java 8中某一周的周一

    Java 8是Java語言中的一個版本,於2014年3月18日發布。本文將從多個方面對Java 8中某一周的周一進行詳細的闡述。 一、數組處理 Java 8新特性之一是Stream…

    編程 2025-04-29
  • Java判斷字符串是否存在多個

    本文將從以下幾個方面詳細闡述如何使用Java判斷一個字符串中是否存在多個指定字符: 一、字符串遍歷 字符串是Java編程中非常重要的一種數據類型。要判斷字符串中是否存在多個指定字符…

    編程 2025-04-29
  • VSCode為什麼無法運行Java

    解答:VSCode無法運行Java是因為默認情況下,VSCode並沒有集成Java運行環境,需要手動添加Java運行環境或安裝相關插件才能實現Java代碼的編寫、調試和運行。 一、…

    編程 2025-04-29
  • Java任務下發回滾系統的設計與實現

    本文將介紹一個Java任務下發回滾系統的設計與實現。該系統可以用於執行複雜的任務,包括可回滾的任務,及時恢復任務失敗前的狀態。系統使用Java語言進行開發,可以支持多種類型的任務。…

    編程 2025-04-29
  • Java 8 Group By 會影響排序嗎?

    是的,Java 8中的Group By會對排序產生影響。本文將從多個方面探討Group By對排序的影響。 一、Group By的概述 Group By是SQL中的一種常見操作,它…

    編程 2025-04-29

發表回復

登錄後才能評論