में बड़े लॉग फाइल मैं कई 200MB + फ़ाइलें है कि मैं के माध्यम से grep करना चाहते हैं मान लीजिए। मैं हास्केल में यह कैसे करूं?पार्स हास्केल
यहाँ मेरी प्रारंभिक कार्यक्रम है:
import Data.List
import Control.Monad
import System.IO
import System.Environment
main = do
filename <- liftM head getArgs
contents <- liftM lines $ readFile filename
putStrLn . unlines . filter (isPrefixOf "import") $ contents
इस के माध्यम से यह पार्स करने से पहले स्मृति में पूरी फ़ाइल पढ़ता है। तब मैं इस के साथ चला गया:
import Data.List
import Control.Monad
import System.IO
import System.Environment
main = do
filename <- liftM head getArgs
file <- (openFile filename ReadMode)
contents <- liftM lines $ hGetContents file
putStrLn . unlines . filter (isPrefixOf "import") $ contents
मैंने सोचा था कि के बाद से hGetContents
, आलसी है it will avoid reading the whole file into memory। लेकिन valgrind
के तहत दोनों स्क्रिप्ट चलाने के लिए दोनों के लिए समान स्मृति उपयोग दिखाया गया। तो या तो मेरी स्क्रिप्ट गलत है, या valgrind
गलत है। मैं
ghc --make test.hs -prof
का उपयोग कर स्क्रिप्ट संकलित करता हूं मुझे क्या याद आ रही है? बोनस प्रश्न: मैं इस बात पर बहुत सारे उल्लेख देखता हूं कि हास्केल में आलसी आईओ वास्तव में एक बुरी चीज है। मैं सख्त आईओ का उपयोग कैसे करूं?
अद्यतन:
तो ऐसा लगता है कि मैं valgrind की मेरी पढ़ने में गलत था। +RTS -s
की सहायता से देखें कि मैं क्या मिलेगा:
7,807,461,968 bytes allocated in the heap
1,563,351,416 bytes copied during GC
101,888 bytes maximum residency (1150 sample(s))
45,576 bytes maximum slop
2 MB total memory in use (0 MB lost due to fragmentation)
Generation 0: 13739 collections, 0 parallel, 2.91s, 2.95s elapsed
Generation 1: 1150 collections, 0 parallel, 0.18s, 0.18s elapsed
INIT time 0.00s ( 0.00s elapsed)
MUT time 2.07s ( 2.28s elapsed)
GC time 3.09s ( 3.13s elapsed)
EXIT time 0.00s ( 0.00s elapsed)
Total time 5.16s ( 5.41s elapsed)
महत्वपूर्ण लाइन 101,888 bytes maximum residency
, जो कहते हैं कि किसी भी बिंदु पर मेरी स्क्रिप्ट ज्यादा से ज्यादा स्मृति के 101 केबी का उपयोग कर रहा था। जिस फ़ाइल के माध्यम से मैं grepping था 44 एमबी था। तो मुझे लगता है फैसले है: readFile
और hGetContents
दोनों आलसी होते हैं।
फ़ॉलो-अप प्रश्न:
मैं स्मृति के 7GB ढेर पर आवंटित क्यों दिखाई देता है? यह एक स्क्रिप्ट के लिए वास्तव में उच्च लगता है जो 44 एमबी फ़ाइल में पढ़ रहा है। अनुवर्ती
अद्यतन करने के लिए सवाल
ढेर पर आबंटित स्मृति के कुछ जीबी की तरह लग रहा है, इसलिए चिंता का कोई कारण हास्केल के लिए असामान्य है। String
रों के बजाय ByteString
रों का उपयोग करते हुए स्मृति उपयोग लेता है एक बहुत नीचे:
81,617,024 bytes allocated in the heap
35,072 bytes copied during GC
78,832 bytes maximum residency (1 sample(s))
26,960 bytes maximum slop
2 MB total memory in use (0 MB lost due to fragmentation)
हम, क्या आप वाकई 'putStrLn'' के साथ इसे लिखने से पहले पूरी 'अनलाइन' स्ट्रिंग बनाने की आवश्यकता नहीं है? मैं 'Control.Monad.forM_ (फ़िल्टर (isPrefixOf" आयात ") सामग्री जैसे कुछ को करने का प्रयास करूंगा) $ putStrLn'। हालांकि यह सिर्फ एक अनुमान है। –
@ रिकार्डो: नहीं, 'अनलिन्स' का आलसी मूल्यांकन किया जा सकता है। 'PutStr $ $ ghशी' में $ map शो [1 ..] 'को अनदेखा करने का प्रयास करें। – ephemient
क्या -O2 जादुई रूप से समस्या का समाधान करता है? – gspr