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

為了賬號(hào)安全,請(qǐng)及時(shí)綁定郵箱和手機(jī)立即綁定
已解決430363個(gè)問(wèn)題,去搜搜看,總會(huì)有你想問(wèn)的

String.Substring() 似乎是這個(gè)代碼的瓶頸

String.Substring() 似乎是這個(gè)代碼的瓶頸

C#
尚方寶劍之說(shuō) 2021-11-14 15:10:14
介紹我有這個(gè)最喜歡的算法,我很久以前就做了,我總是用新的編程語(yǔ)言、平臺(tái)等編寫(xiě)和重寫(xiě)它作為某種基準(zhǔn)。雖然我的主要編程語(yǔ)言是 C#,但我只是從字面上復(fù)制粘貼了代碼并稍微更改了語(yǔ)法,用 Java 構(gòu)建它并發(fā)現(xiàn)它的運(yùn)行速度提高了 1000 倍。編碼有相當(dāng)多的代碼,但我只想展示這個(gè)似乎是主要問(wèn)題的片段:for (int i = 0; i <= s1.Length; i++) {    for (int j = i + 1; j <= s1.Length - i; j++)    {        string _s1 = s1.Substring(i, j);        if (tree.hasLeaf(_s1))         ...數(shù)據(jù)需要指出的是,這個(gè)特定測(cè)試中的字符串 s1 的長(zhǎng)度為 100 萬(wàn)個(gè)字符 (1MB)。測(cè)量我在 Visual Studio 中分析了我的代碼執(zhí)行情況,因?yàn)槲艺J(rèn)為我構(gòu)建樹(shù)的方式或遍歷它的方式不是最佳的。檢查結(jié)果后,該行似乎string _s1 = s1.Substring(i, j);可以容納超過(guò) 90% 的執(zhí)行時(shí)間!其他觀察我注意到的另一個(gè)區(qū)別是,雖然我的代碼是單線程的,但 Java 設(shè)法使用所有 8 個(gè)內(nèi)核(100% CPU 利用率)來(lái)執(zhí)行它,而即使使用 Parallel.For() 和多線程技術(shù),我的 C# 代碼也設(shè)法使用了 35-最多 40%。由于算法與內(nèi)核數(shù)量(和頻率)成線性比例,我對(duì)此進(jìn)行了補(bǔ)償,并且 Java 中的代碼片段的執(zhí)行速度仍然快 100-1000 倍。推理我認(rèn)為發(fā)生這種情況的原因與 C# 中的字符串是不可變的事實(shí)有關(guān),因此 String.Substring() 必須創(chuàng)建一個(gè)副本,并且由于它在嵌套的 for 循環(huán)中進(jìn)行多次迭代,因此我認(rèn)為有很多復(fù)制和垃圾收集正在進(jìn)行,但是,我不知道 Substring 在 Java 中是如何實(shí)現(xiàn)的。題此時(shí)我有哪些選擇?子串的數(shù)量和長(zhǎng)度沒(méi)有辦法解決(這已經(jīng)被最大限度地優(yōu)化了)。是否有一種我不知道(或可能是數(shù)據(jù)結(jié)構(gòu))的方法可以為我解決這個(gè)問(wèn)題?請(qǐng)求最小實(shí)現(xiàn)(來(lái)自評(píng)論)我省略了后綴樹(shù)的實(shí)現(xiàn),即構(gòu)造中的 O(n) 和遍歷中的 O(log(n))public static double compute(string s1, string s2){    double score = 0.00;    suffixTree stree = new suffixTree(s2);    for (int i = 0; i <= s1.Length; i++)     {        int longest = 0;        for (int j = i + 1; j <= s1.Length - i; j++)        {            string _s1 = s1.Substring(i, j);            if (stree.has(_s1))            {                score += j - i;                longest = j - i;            }            else break;         };        i += longest;    };    return score;}分析器的屏幕截圖請(qǐng)注意,這是使用 300.000 個(gè)字符的字符串 s1 進(jìn)行測(cè)試的。出于某種原因,100 萬(wàn)個(gè)字符在 C# 中永遠(yuǎn)不會(huì)完成,而在 Java 中只需要 0.75 秒。消耗的內(nèi)存和垃圾收集的數(shù)量似乎并不表示內(nèi)存問(wèn)題。峰值約為 400 MB,但考慮到巨大的后綴樹(shù),這似乎是正常的。也沒(méi)有發(fā)現(xiàn)奇怪的垃圾收集模式。
查看完整描述

1 回答

?
倚天杖

TA貢獻(xiàn)1828條經(jīng)驗(yàn) 獲得超3個(gè)贊

問(wèn)題來(lái)源


在經(jīng)歷了持續(xù)兩天三夜的光榮戰(zhàn)斗(以及來(lái)自評(píng)論的驚人想法和想法)之后,我終于設(shè)法解決了這個(gè)問(wèn)題!


我想為遇到類(lèi)似問(wèn)題的任何人發(fā)布一個(gè)答案,其中該string.Substring(i, j)函數(shù)不是獲取字符串子字符串的可接受解決方案,因?yàn)樽址蟛⑶夷鸁o(wú)法負(fù)擔(dān)string.Substring(i, j)(它必須制作一個(gè)副本,因?yàn)?C# 字符串是不可變的,無(wú)法繞過(guò)它)或者在string.Substring(i, j)同一個(gè)字符串上被大量調(diào)用(就像在我的嵌套 for 循環(huán)中)給垃圾收集器帶來(lái)了困難,或者就像我的情況一樣!


嘗試


我已經(jīng)嘗試了許多建議的東西,例如StringBuilder、Streams、在塊內(nèi)使用Intptr和Marshal 的非托管內(nèi)存分配unsafe{},甚至創(chuàng)建一個(gè) IEnumerable 并通過(guò)引用返回給定位置內(nèi)的字符。所有這些嘗試最終都失敗了,因?yàn)楸仨毻瓿赡撤N形式的數(shù)據(jù)連接,因?yàn)槲覜](méi)有簡(jiǎn)單的方法可以在不影響性能的情況下逐個(gè)字符地遍歷我的樹(shù)。如果只有一種方法可以一次跨越數(shù)組中的多個(gè)內(nèi)存地址,就像您可以在 C++ 中使用一些指針?biāo)惴ㄒ粯?.....除了有......(歸功于@Ivan Stoev 的評(píng)論)


解決方案


解決方案是使用System.ReadOnlySpan<T>(不可能是System.Span<T>因?yàn)樽址遣豢勺兊模渌?,它允許我們?cè)诓粍?chuàng)建副本的情況下讀取現(xiàn)有數(shù)組中內(nèi)存地址的子數(shù)組。


這段代碼發(fā)布:


string _s1 = s1.Substring(i, j);

if (stree.has(_s1))

{

    score += j - i;

    longest = j - i;

}

更改為以下內(nèi)容:


if (stree.has(i, j))

{

    score += j - i;

    longest = j - i;

}

哪里stree.has()現(xiàn)在需要兩個(gè)整數(shù)(子字符串的位置和長(zhǎng)度)并執(zhí)行:


ReadOnlySpan<char> substr = s1.AsSpan(i, j);

請(qǐng)注意,substr變量實(shí)際上是對(duì)初始s1數(shù)組字符子集的引用,而不是副本?。ㄔ搒1變量已可從此函數(shù)訪問(wèn))


請(qǐng)注意,在撰寫(xiě)本文時(shí),我使用的是 C#7.2 和 .NET Framework 4.6.1,這意味著要獲得 Span 功能,我必須轉(zhuǎn)到 Project > Manage NuGet Packages,勾選“Include prerelease”復(fù)選框并瀏覽 System .內(nèi)存并安裝它。


重新運(yùn)行初始測(cè)試(在長(zhǎng)度為 100 萬(wàn)個(gè)字符的字符串上,即 1MB)速度從 2+ 分鐘(我在 2 分鐘后放棄等待)增加到 ~86 毫秒!!


查看完整回答
反對(duì) 回復(fù) 2021-11-14
  • 1 回答
  • 0 關(guān)注
  • 230 瀏覽

添加回答

舉報(bào)

0/150
提交
取消
微信客服

購(gòu)課補(bǔ)貼
聯(lián)系客服咨詢(xún)優(yōu)惠詳情

幫助反饋 APP下載

慕課網(wǎng)APP
您的移動(dòng)學(xué)習(xí)伙伴

公眾號(hào)

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