私は少し読み込んで、解析して、面白い(実際にはない)統計をApacheログファイルから取得します。今までは、ログファイルのすべての要求で送信された合計バイト数と最も一般的なIPアドレスの上位10個の2つの簡単なオプションを作成しました。マップとバイトストリングキーを使用した折り畳みのパフォーマンス解析
最初の「モード」は、すべての解析されたバイトの単純な合計です。 2番目のマップはマップ(Data.Map)の倍数で、insertWith (+) 1'
を使用して出現を数えます。
最初のものは予想どおりに動作し、ほとんどの時間は解析に費やされ、一定のスペースで実行されます。使用中のGC 113712バイト最大レジデンシー(1553サンプル(複数可)) 145872バイト最大スロープ 2メガバイト総メモリ(によるフラグメンテーションのために失わ0メガバイト中にコピー に割り当て
42359709344バイトヒープ 72405840バイト)
発生0:76311のコレクション、
経過しました
0平行、0.89s、0.99sが
1世代経過:1553点のコレクション、0 平行、0.21s、0.22sはINIT時間0.00s(0.00s 経過)MUT時間21.76s( 24.82s経過)GC時間1.10s(1.20s経過)EXIT時間
0.00s(0.00s経過)合計時間22.87s(26.02s )経過% 4.8%(4.6%経過GC時間)
のAllocレート1946258962バイト秒MUTあたり
生産総ユーザの95.2%で、全体の 83.6パーセントが
経過
ただし、2番目のものはありません! に割り当て
49398834152バイトヒープ使用におけるGC 718385088バイト最大レジデンシー(15試料(S)) 134532128バイト最大スロープ 1393メガバイト総メモリによるフラグメンテーションに失われた(172メガバイト中にコピー 580579208バイト)
発生0:91275輪のコレクション、
0平行、252.65s、254.46s経過
ジェネレーション1:15点のコレクション、0がパラレル、0.12sは、0.12s経過INIT時間0.00s(0.00s 経過)MUT時間41.11s( 48.87s経過)GC時間252.77s(254.58s経過)EXIT時間
0.00s(0.01秒経過)時間の合計293.88s(303.45 S経過)%のGC時間経過86.0パーセント(83.9パーセント)
のAllocレート 生産14
秒MUTあたり1201635385バイト。合計ユーザーの0% 合計の13.5%が
ここに記載されています。
{-# LANGUAGE OverloadedStrings #-}
module Main where
import qualified Data.Attoparsec.Lazy as AL
import Data.Attoparsec.Char8 hiding (space, take)
import qualified Data.ByteString.Char8 as S
import qualified Data.ByteString.Lazy.Char8 as L
import Control.Monad (liftM)
import System.Environment (getArgs)
import Prelude hiding (takeWhile)
import qualified Data.Map as M
import Data.List (foldl', sortBy)
import Text.Printf (printf)
import Data.Maybe (fromMaybe)
type Command = String
data LogLine = LogLine {
getIP :: S.ByteString,
getIdent :: S.ByteString,
getUser :: S.ByteString,
getDate :: S.ByteString,
getReq :: S.ByteString,
getStatus :: S.ByteString,
getBytes :: S.ByteString,
getPath :: S.ByteString,
getUA :: S.ByteString
} deriving (Ord, Show, Eq)
quote, lbrack, rbrack, space :: Parser Char
quote = satisfy (== '\"')
lbrack = satisfy (== '[')
rbrack = satisfy (== ']')
space = satisfy (== ' ')
quotedVal :: Parser S.ByteString
quotedVal = do
quote
res <- takeTill (== '\"')
quote
return res
bracketedVal :: Parser S.ByteString
bracketedVal = do
lbrack
res <- takeTill (== ']')
rbrack
return res
val :: Parser S.ByteString
val = takeTill (== ' ')
line :: Parser LogLine
l ine = do
ip <- val
space
identity <- val
space
user <- val
space
date <- bracketedVal
space
req <- quotedVal
space
status <- val
space
bytes <- val
(path,ua) <- option ("","") combined
return $ LogLine ip identity user date req status bytes path ua
combined :: Parser (S.ByteString,S.ByteString)
combined = do
space
path <- quotedVal
space
ua <- quotedVal
return (path,ua)
countBytes :: [L.ByteString] -> Int
countBytes = foldl' count 0
where
count acc l = case AL.maybeResult $ AL.parse line l of
Just x -> (acc +) . maybe 0 fst . S.readInt . getBytes $ x
Nothing -> acc
countIPs :: [L.ByteString] -> M.Map S.ByteString Int
countIPs = foldl' count M.empty
where
count acc l = case AL.maybeResult $ AL.parse line l of
Just x -> M.insertWith' (+) (getIP x) 1 acc
Nothing -> acc
---------------------------------------------------------------------------------
main :: IO()
main = do
[cmd,path] <- getArgs
dispatch cmd path
pretty :: Show a => Int -> (a, Int) -> String
pretty i (bs, n) = printf "%d: %s, %d" i (show bs) n
dispatch :: Command -> FilePath -> IO()
dispatch cmd path = action path
where
action = fromMaybe err (lookup cmd actions)
err = printf "Error: %s is not a valid command." cmd
actions :: [(Command, FilePath -> IO())]
actions = [("bytes", countTotalBytes)
,("ips", topListIP)]
countTotalBytes :: FilePath -> IO()
countTotalBytes path = print . countBytes . L.lines =<< L.readFile path
topListIP :: FilePath -> IO()
topListIP path = do
f <- liftM L.lines $ L.readFile path
let mostPopular (_,a) (_,b) = compare b a
m = countIPs f
mapM_ putStrLn . zipWith pretty [1..] . take 10 . sortBy mostPopular . M.toList $ m
編集:+ RTS -A16M追加
は20%までGCを減少させました。もちろん、メモリの使用は変わりません。
解決策ではありませんが、蓄積マップ上の「foldl」は無駄です。通常の 'foldl'を使用してください。 –
@John L、あなたは大丈夫です。この場合、foldlとfoldlの間のスピード、GCまたはメモリの使用に違いは見られません。 –