पिछले हफ्ते उपयोगकर्ता मास ने हास्केल में एक निर्देशिका में question about recursively listing files से पूछा। मेरा पहला विचार प्रिंटिंग शुरू होने से पहले स्मृति में पूरी सूची बनाने से बचने के लिए List
package से मोनैडिक सूचियों का उपयोग करने का प्रयास करना था। मैंने इसे निम्नानुसार कार्यान्वित किया:सूची पैकेज से मोनैडिक सूचियों का उपयोग करके मेरा कोड इतना धीमा क्यों है?
module Main where
import Prelude hiding (filter)
import Control.Applicative ((<$>))
import Control.Monad (join)
import Control.Monad.IO.Class (liftIO)
import Control.Monad.ListT (ListT)
import Data.List.Class (cons, execute, filter, fromList, mapL)
import System (getArgs)
import System.Directory (getDirectoryContents, doesDirectoryExist)
import System.FilePath ((</>))
main = execute . mapL putStrLn . listFiles =<< head <$> getArgs
listFiles :: FilePath -> ListT IO FilePath
listFiles path = liftIO (doesDirectoryExist path) >>= listIfDir
where
valid "." = False
valid ".." = False
valid _ = True
listIfDir False = return path
listIfDir True
= cons path
$ join
$ listFiles
<$> (path </>)
<$> (filter valid =<< fromList <$> liftIO (getDirectoryContents path))
यह खूबसूरती से प्रिंट करना शुरू करता है और बहुत कम स्मृति का उपयोग करता है। दुर्भाग्यवश यह तुलनीय FilePath -> IO [FilePath]
संस्करण की तुलना में धीमी बार भी धीमी है।
मैं क्या गलत कर रहा हूं? मैंने इस तरह के खिलौनों के उदाहरणों के बाहर List
पैकेज का ListT
कभी भी उपयोग नहीं किया है, इसलिए मुझे नहीं पता कि किस प्रकार का प्रदर्शन अपेक्षित है, लेकिन ~ 40,000 फ़ाइलों के साथ निर्देशिका को संसाधित करने के लिए 30 सेकंड (बनाम सेकेंड का एक अंश) बहुत धीमी
हम 'Data.ByteString.getDirectoryContents :: बाइटस्ट्रिंग -> [बाइटस्ट्रिंग] 'का उपयोग कर सकते हैं। जब आप प्रत्येक 10+ अक्षर पर 40,000 फाइलों पर विचार करते हैं, तो यह 400,000 वर्ण है। हास्केल में एक [चार] क्या लेता है? Ballpark 12 बाइट्स (x86) या 24 (x86-64)। तो उन 400,000 वर्ण एक लिंक की गई सूची में 8 एमबी या अधिक फैले हुए हैं। अब जब मैंने यह सब कहा है, तो उम्मीद है कि आप जवाब देंगे "मैंने बेंचमार्क किया है डायरेक्ट्री कॉन्टैक्ट्स और यह मुद्दा नहीं है"। –
@TomMD: मैं मुख्य रूप से 'फाइलपाथ -> आईओ [फाइलपाथ]' संस्करणों की तुलना में रूचि रखता हूं जो 'getDirectoryContents' का उपयोग उसी तरह से करते हैं (उदाहरण के लिए मास का मूल कार्यान्वयन)। इसलिए मुझे नहीं लगता कि यह समस्या है, लेकिन मैं एक नज़र डालेगा। –