第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

FactoryFinder 性能/緩存不良

FactoryFinder 性能/緩存不良

楊魅力 2023-10-19 21:26:54
我有一個相當大的 java ee 應用程序,它有一個巨大的類路徑,可以進行大量的 xml 處理。目前,我正在嘗試加快一些功能的速度,并通過采樣分析器找到緩慢的代碼路徑。我注意到的一件事是,特別是我們的代碼中包含類似調(diào)用的部分TransformerFactory.newInstance(...)速度非常慢。我追蹤到這個FactoryFinder方法findServiceProvider總是創(chuàng)建一個新ServiceLoader實例。在ServiceLoader javadoc中我發(fā)現(xiàn)了以下關(guān)于緩存的注釋:提供者是延遲定位和實例化的,即按需定位和實例化。服務(wù)加載器維護迄今為止已加載的提供者的緩存。每次調(diào)用迭代器方法都會返回一個迭代器,該迭代器首先按實例化順序生成緩存的所有元素,然后延遲查找并實例化任何剩余的提供程序,依次將每個元素添加到緩存中。可以通過reload方法清除緩存。到目前為止,一切都很好。這是 OpenJDK 方法的一部分FactoryFinder#findServiceProvider:private static <T> T findServiceProvider(final Class<T> type)        throws TransformerFactoryConfigurationError    {      try {            return AccessController.doPrivileged(new PrivilegedAction<T>() {                public T run() {                    final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);                    final Iterator<T> iterator = serviceLoader.iterator();                    if (iterator.hasNext()) {                        return iterator.next();                    } else {                        return null;                    }                 }            });        } catch(ServiceConfigurationError e) {            ...        }    }每次findServiceProvider來電ServiceLoader.load。這每次都會創(chuàng)建一個新的ServiceLoader。這樣看來根本就沒有使用ServiceLoaders的緩存機制。每次調(diào)用都會掃描類路徑以查找所請求的 ServiceProvider。我已經(jīng)嘗試過的:我知道您可以設(shè)置系統(tǒng)屬性,例如javax.xml.transform.TransformerFactory指定特定的實現(xiàn)。這樣FactoryFinder就不會使用ServiceLoader進程而且速度超級快。遺憾的是,這是一個 jvm 范圍的屬性,會影響我的 jvm 中運行的其他 java 進程。例如,我的應用程序隨 Saxon 一起提供,應該使用com.saxonica.config.EnterpriseTransformerFactory我有另一個不隨 Saxon 提供的應用程序。一旦我設(shè)置了系統(tǒng)屬性,我的另一個應用程序就無法啟動,因為com.saxonica.config.EnterpriseTransformerFactory它的類路徑上沒有。所以這對我來說似乎不是一個選擇。我已經(jīng)重構(gòu)了調(diào)用 a 的每個地方TransformerFactory.newInstance并緩存了 TransformerFactory。但我的依賴項中有很多地方無法重構(gòu)代碼。我的問題是:為什么 FactoryFinder 不重用 ServiceLoader?除了使用系統(tǒng)屬性之外,還有其他方法可以加快整個 ServiceLoader 進程嗎?難道不能在 JDK 中對此進行更改,以便 FactoryFinder 重用 ServiceLoader 實例嗎?此外,這并不特定于單個 FactoryFinder。javax.xml對于我迄今為止查看過的包中的所有 FactoryFinder 類,此行為都是相同的。我正在使用 OpenJDK 8/11。我的應用程序部署在 Tomcat 9 實例中。
查看完整描述

2 回答

?
Smart貓小萌

TA貢獻1911條經(jīng)驗 獲得超7個贊

35 毫秒聽起來像是涉及磁盤訪問時間,這表明操作系統(tǒng)緩存存在問題。

類路徑上是否有任何目錄/非 jar 條目可能會減慢速度。此外,如果資源不存在于檢查的第一個位置。

ClassLoader.getResource如果您可以通過配置(我已經(jīng)多年沒有接觸 tomcat)或只是設(shè)置線程上下文類加載器,則可以覆蓋Thread.setContextClassLoader。


查看完整回答
反對 回復 2023-10-19
?
慕姐4208626

TA貢獻1852條經(jīng)驗 獲得超7個贊

我可以再花 30 分鐘來調(diào)試這個問題,并研究 Tomcat 如何進行資源緩存。


我特別CachedResource.validateResources感興趣(可以在上面的火焰圖中找到)。true如果CachedResource仍然有效則返回:


protected boolean validateResources(boolean useClassLoaderResources) {

? ? ? ? long now = System.currentTimeMillis();

? ? ? ? if (this.webResources == null) {

? ? ? ? ? ? ...

? ? ? ? }


? ? ? ? // TTL check here!!

? ? ? ? if (now < this.nextCheck) {

? ? ? ? ? ? return true;

? ? ? ? } else if (this.root.isPackedWarFile()) {

? ? ? ? ? ? this.nextCheck = this.ttl + now;

? ? ? ? ? ? return true;

? ? ? ? } else {

? ? ? ? ? ? return false;

? ? ? ? }

? ? }

看起來CachedResource實際上有一個生存時間 (ttl)。實際上Tomcat中有一種方法可以配置cacheTtl?,但你只能增加這個值。資源緩存配置看起來并不那么靈活。

所以我的Tomcat配置了默認值5000毫秒。這在進行性能測試時欺騙了我,因為我的請求之間有 5 秒多一點的時間(查看圖表和其他內(nèi)容)。這就是為什么我的所有請求基本上都在沒有緩存的情況下運行,并且ZipFile.open每次都會觸發(fā)如此繁重的操作。

因此,由于我對 Tomcat 配置并不是很有經(jīng)驗,所以我還不確定什么是正確的解決方案。增加cacheTTL可以使緩存更長,但從長遠來看并不能解決問題。

概括

我認為這里實際上有兩個罪魁禍首。

  1. FactoryFinder 類不重用 ServiceLoader。他們不重復使用它們可能是有正當理由的——但我實在想不出一個原因。

  2. Tomcat 在固定時間后驅(qū)逐 Web 應用程序資源的緩存(類路徑中的文件 - 就像ServiceLoader配置)

再加上沒有為 ServiceLoader 類定義系統(tǒng)屬性,您每秒都會收到一次緩慢的 FactoryFinder 調(diào)用cacheTtl。

現(xiàn)在我可以忍受將cacheTtl 增加到更長的時間。我也可能會看看 Tom Hawtins 的重寫建議,Classloader.getResources即使我認為這是擺脫性能瓶頸的一種嚴厲方式。不過,這可能值得一看。


查看完整回答
反對 回復 2023-10-19
  • 2 回答
  • 0 關(guān)注
  • 166 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯(lián)系客服咨詢優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動學習伙伴

公眾號

掃描二維碼
關(guān)注慕課網(wǎng)微信公眾號