這可能是一個愚蠢的問題,基於std :: set <>已經有完美的比較運算符的事實,但我想我可能會對我的特定用例進行優化,並且要確保我沒有傷害到自己不知何故。「展平」std :: set <std::string>用於存儲和比較?
基本上,我有一個昂貴的操作,需要輸入std :: set &。我緩存操作的結果,這樣我就可以返回的結果,如果相同的輸入已經在過去。這確實需要存儲套複印件(我做的
std::map<std::set<std::string>, Result*>
,然後每次調用操作時都要搜索一次,因爲很可能連續調用同一個操作數千次,所以我會說緩存的std :: set在99%以上的時間內找到了。最近,我根據傳入字符串中某些字符無效的事實,嘗試了一些我認爲可能的小改進:我將std :: set壓扁成單個字符串,組件字符串用':'分隔。 '字符,然後我的std :: map變成
std::map<std::string, Result*>
並且每次調用該操作時,都會將該集合展平並在緩存中搜索單個字符串。
我實際上對性能改進感到驚訝。我的測試運行使用包含5個字符串的std :: sets,每個字符串長30個字符,並且運行10,000,000次搜索。在我的工作站,每次運行的時間分別爲
std::map<std::set<std::string>, Result*> : 138.8 seconds
std::map<std::string, Result> : 89.2 seconds
看來,即使壓扁設定每次調用的開銷,第二種方法是一個巨大的進步。我想我的問題是:爲什麼?我在這裏做了一些可能不好的事情,那就是有目的地避免了std :: set的實現者(即可能導致較大字符串導致壞堆碎片?)是因爲集合中的單個字符串位於不同位置並且必須單獨進行比較?我在腳下開槍自殺嗎?在這種特殊情況下,這似乎是一個明顯的改進,以提高性能。
如果你調用具有相同參數的時間功能99%,那麼我會說有一個與主叫方,而不是與溫控功能本身有問題。無論如何,你不能爲你的集合添加某種'id',這樣該方法只需要比較'id'而不是整個'set'?這聽起來像你正在傳遞的設置不經常改變。 – user463035818
我沒有簡化一點,該函數的輸入是std :: set和2個獨立的消息進行比較。該集合描述了在比較之前應用於消息的轉換,並且它構建了這種轉換,這是昂貴的部分(應用它是微不足道的)。該集合幾乎總是不變,但消息幾乎總是不同的。理想情況下,我會讓調用者以某種方式獲得轉換的句柄,然後在調用比較時使用句柄而不是該集合 - 不幸的是,這需要成爲現有代碼的簡單替換。 – Kevin
只要確保你的分隔符不能成爲實際字符串的一部分,你應該沒問題。此外,每當性能不要忘記與std :: unordered_map或std :: unordered_set的bencmark。然而,字符串並不總是存儲在其中的最佳類型,因爲您必須讀取整個字符串才能生成散列,而處理器<可以提前停止。 – SteakOverflow