on master help sign in
Add fold benchmark
8de5ea9Jasper Van der Jeugt
tests/benchmarks/ruby/fold.rbnew file+50
@@ -0,0 +1,50 @@
1+#!/usr/bin/env ruby
2+
3+require './utils.rb'
4+
5+def fold(filename, max_width)
6+ File.open(filename, 'r:utf-8') do |file|
7+ # Words in this paragraph
8+ paragraph = []
9+
10+ file.each_line do |line|
11+ # If we encounter an empty line, we reformat and dump the current
12+ # paragraph
13+ if line.strip.empty? then
14+ puts fold_paragraph(paragraph, max_width)
15+ puts
16+ paragraph = []
17+ # Otherwise, we append the words found in the line to the paragraph
18+ else
19+ paragraph.concat line.split
20+ end
21+ end
22+
23+ # Last paragraph
24+ puts fold_paragraph(paragraph, max_width) unless paragraph.empty?
25+ end
26+end
27+
28+# Fold a single paragraph to the desired width
29+def fold_paragraph(paragraph, max_width)
30+ # Gradually build our output
31+ str = paragraph.first
32+ width = str.length
33+
34+ paragraph.drop(1).each do |word|
35+ if width + word.length + 1 <= max_width then
36+ str += ' ' + word
37+ width += word.length + 1
38+ else
39+ str += "\n" + word
40+ width = word.length
41+ end
42+ end
43+
44+ str
45+end
46+
47+ARGV.each do |f|
48+ t = benchmark { fold(f, 80) }
49+ STDERR.puts "#{f}: #{t}"
50+end
tests/benchmarks/src/Data/Text/Benchmarks.hs+2
@@ -23,6 +23,7 @@ import qualified Data.Text.Benchmarks.WordFrequencies as WordFrequencies
23
23
24import qualified Data.Text.Benchmarks.Programs.BigTable as Programs.BigTable
24import qualified Data.Text.Benchmarks.Programs.BigTable as Programs.BigTable
25import qualified Data.Text.Benchmarks.Programs.Cut as Programs.Cut
25import qualified Data.Text.Benchmarks.Programs.Cut as Programs.Cut
26+import qualified Data.Text.Benchmarks.Programs.Fold as Programs.Fold
26import qualified Data.Text.Benchmarks.Programs.Sort as Programs.Sort
27import qualified Data.Text.Benchmarks.Programs.Sort as Programs.Sort
27import qualified Data.Text.Benchmarks.Programs.StripTags as Programs.StripTags
28import qualified Data.Text.Benchmarks.Programs.StripTags as Programs.StripTags
28import qualified Data.Text.Benchmarks.Programs.Throughput as Programs.Throughput
29import qualified Data.Text.Benchmarks.Programs.Throughput as Programs.Throughput
@@ -54,6 +55,7 @@ benchmarks = do
54 ps <- bgroup "Programs" `fmap` sequence
55 ps <- bgroup "Programs" `fmap` sequence
55 [ Programs.BigTable.benchmark sink
56 [ Programs.BigTable.benchmark sink
56 , Programs.Cut.benchmark (tf "russian.txt") sink 20 40
57 , Programs.Cut.benchmark (tf "russian.txt") sink 20 40
58+ , Programs.Fold.benchmark (tf "russian.txt") sink
57 , Programs.Sort.benchmark (tf "russian.txt") sink
59 , Programs.Sort.benchmark (tf "russian.txt") sink
58 , Programs.StripTags.benchmark (tf "yiwiki.xml") sink
60 , Programs.StripTags.benchmark (tf "yiwiki.xml") sink
59 , Programs.Throughput.benchmark (tf "russian.txt") sink
61 , Programs.Throughput.benchmark (tf "russian.txt") sink
tests/benchmarks/src/Data/Text/Benchmarks/Programs/Fold.hsnew file+68
@@ -0,0 +1,68 @@
1+-- | Benchmark which formats paragraph, like the @sort@ unix utility.
2+--
3+-- Tested in this benchmark:
4+--
5+-- * Reading the file
6+--
7+-- * Splitting into paragraphs
8+--
9+-- * Reformatting the paragraphs to a certain line width
10+--
11+-- * Concatenating the results using the text builder
12+--
13+-- * Writing back to a handle
14+--
15+{-# LANGUAGE OverloadedStrings #-}
16+module Data.Text.Benchmarks.Programs.Fold
17+ ( benchmark
18+ ) where
19+
20+import Data.List (foldl')
21+import Data.List (intersperse)
22+import Data.Monoid (mempty, mappend, mconcat)
23+import System.IO (Handle)
24+import Criterion (Benchmark, bench)
25+import qualified Data.Text as T
26+import qualified Data.Text.IO as T
27+import qualified Data.Text.Lazy.Builder as TLB
28+import qualified Data.Text.Lazy as TL
29+import qualified Data.Text.Lazy.IO as TL
30+
31+benchmark :: FilePath -> Handle -> IO Benchmark
32+benchmark i o = return $
33+ bench "Fold" $ T.readFile i >>= TL.hPutStr o . fold 80
34+
35+-- | We represent a paragraph by a word list
36+--
37+type Paragraph = [T.Text]
38+
39+-- | Fold a text
40+--
41+fold :: Int -> T.Text -> TL.Text
42+fold maxWidth = TLB.toLazyText . mconcat .
43+ intersperse "\n\n" . map (foldParagraph maxWidth) . paragraphs
44+
45+-- | Fold a paragraph
46+--
47+foldParagraph :: Int -> Paragraph -> TLB.Builder
48+foldParagraph _ [] = mempty
49+foldParagraph max' (w : ws) = fst $ foldl' go (TLB.fromText w, T.length w) ws
50+ where
51+ go (builder, width) word
52+ | width + len + 1 <= max' =
53+ (builder `mappend` " " `mappend` word', width + len + 1)
54+ | otherwise =
55+ (builder `mappend` "\n" `mappend` word', len)
56+ where
57+ word' = TLB.fromText word
58+ len = T.length word
59+
60+-- | Divide a text into paragraphs
61+--
62+paragraphs :: T.Text -> [Paragraph]
63+paragraphs = splitParagraphs . map T.words . T.lines
64+ where
65+ splitParagraphs ls = case break null ls of
66+ ([], []) -> []
67+ (p, []) -> [concat p]
68+ (p, lr) -> concat p : splitParagraphs (dropWhile null lr)