問題タブ [attoparsec]
For questions regarding programming in ECMAScript (JavaScript/JS) and its various dialects/implementations (excluding ActionScript). Note JavaScript is NOT the same as Java! Please include all relevant tags on your question; e.g., [node.js], [jquery], [json], [reactjs], [angular], [ember.js], [vue.js], [typescript], [svelte], etc.
haskell - アトパーセック使用時の入力不備の問題
パフォーマンスを向上させるために、Parsec を使用する機能している Haskell コードを、代わりに Attoparsec を使用するように変換しています。変更を行い、すべてがコンパイルされましたが、パーサーが正しく機能しません。
1 行に 1 つずつ、さまざまなレコード タイプで構成されるファイルを解析しています。レコードまたはコメントを解析するための個々の関数はそれぞれ正しく機能しますが、一連のレコードをコンパイルする関数を作成しようとすると、パーサーはより多くの入力を期待しているため、常に部分的な結果を返します。
これらは、私が試した 2 つの主なバリエーションです。どちらも同じ問題を抱えています。
この 2 番目の例では、行末文字を使用するようにレコード/コメント パーサーを変更しました。
私のアプローチに何か問題がありますか?私が試みていることを達成する他の方法はありますか?
parsing - アトパーセクを理解する
attoparsecはファイルを解析するために私に提案されました、今私はそれを使用する方法を理解しなければなりません。誰かが私にこのコードをくれました:
#
これは非常にうまく機能しますが、理由はわかりません。フリップを使用する理由は何ですか。A.feedの引数を別の順序に並べるのは簡単ではありませんか。そしてなぜB.emptyがあるのですか?私が勉強できることについてのチュートリアルはありますか?前もって感謝します
parsing - Haskell:入力文字列が空のときにData.Attoparsec.Char8.sepByを停止する方法は?
私は次のHaskellコードを書きました
コードはこのように機能すると想定されています:
しかし、上記のコードのようにsomeWithSepを定義したので、常に次の動作が発生します。
破損したエントリを提供しない限り:
どうすればこれを修正できますか?
返信ありがとう
parsing - Attoparsec は、大規模な「take」呼び出しで大量のメモリを割り当てます
だから私はパケット盗聴アプリを書いています。基本的には、tcp セッションをスニッフィングし、それらを解析して http であるかどうかを確認し、http であるかどうか、適切なコンテンツ タイプを持っているかどうかなどをハード ドライブにファイルとして保存したかったのです。
だから、そのためには、効率的にしたかったのです。現在の http ライブラリは文字列ベースであり、大きなファイルを扱うことになるため、本当に必要なのは http 応答を解析することだけだったので、attoparsec で独自のものを作成することにしました。
プログラムを終了したとき、wav ファイルを含む 9 メガの http 応答を解析しているときに、プロファイリングしたときに、http 応答の本文を解析しようとしているときに、1 ギガのメモリを割り当てていることがわかりました。 . HTTP.prof を見ると、いくつかの行が表示されます。
ご覧のとおり、httpbody 内のどこかで take が 1201 回呼び出され、バイト文字列が 500 回以上 (+++) 連結され、途方もない量のメモリが割り当てられます。
これがコードです。N は、http 応答がある場合、そのコンテンツの長さです。1 つも存在しない場合は、すべてを取得しようとします。
1000 文字程度のバイト文字列の遅延バイト文字列を返すようにしたかったのですが、n だけを取得して厳密なバイト文字列を返すように変更しても、それらの割り当てはまだ残っています (そして 14 ギガのメモリを使用します)。
コンビナトレントをやっている人のブログを読んでいて、彼も同じ問題を抱えていましたが、解決策については聞いたことがありません。以前にこの問題に遭遇したり、解決策を見つけた人はいますか?
編集:さて、私はこれを一日中放置しましたが、何も得られませんでした. 問題を調査した後、遅延バイト文字列アクセサーを attoparsec に追加せずにそれを行う方法はないと思います。他のすべてのライブラリも調べましたが、バイト文字列などが欠けていました。
そこで、回避策を見つけました。http リクエストについて考えると、ヘッダー、改行、改行、本文になります。本文は最後であり、解析すると、解析したものとバイト文字列の残りの両方を含むタプルが返されるため、attoparsec 内の本文の解析をスキップして、残っているバイト文字列から本文を直接取り出すことができます。
少し面倒ですが、最終的には高速に動作し、必要以上の割り当てはありません。したがって、基本的にはバイト文字列を折りたたんで http データ構造を収集し、コレクションの合間に、取得したばかりの構造のコンテンツの長さを確認し、残りのバイト文字列から適切な量を取り出し、バイト文字列が残っている場合は続行します。
編集:私は実際にこのプロジェクトを完成させました。魅力のように機能します。私は適切に調整されていませんが、誰かがソース全体を表示したい場合は、https://github.com/onmach/Audio-Snifferで見つけることができます。
haskell - attoparsecを使用したJPEGマーカーの解析
Haskellに関する知識と快適さをさらに高めるプロジェクトとして、将来のコンピュータービジョン作業に役立つJPEGデコーダーの実装に取り組んでいます。
私が選択した最初のステップは、画像内のすべての「マーカー」を解析することです。これらは、バイト0xFFとそれに続く非0バイトで示されます。0xFFバイトの後に0x00バイトが続く場合は、通常のデータとして扱われます。
私が遭遇している問題は、0xFF 0x00の組み合わせに遭遇すると、解析が完全に終了し、有効なマーカーが見つからないように見えることです(標準のJPEGで実行すると、画像マーカーの開始は解析されますが、終了は表示されません)多くの場合、0xFF 0x00の画像マーカーは画像データ自体の中で発生します)。
haskell - Attoparsec Iteratee
Iteratees について少し学ぶために、Data.Iteratee と Data.Attoparsec.Iteratee を使用して、私が作成した単純なパーサーを再実装したかったのです。私はかなり困惑しています。以下に、ファイルから1行を解析できる簡単な例を示します。私のパーサーは一度に 1 行ずつ読み取るため、それが完了するまで iteratee に行を供給する方法が必要です。これをグーグルで見つけたものはすべて読みましたが、反復子/列挙子に関する多くの資料はかなり高度です。これは重要なコードの部分です。
この例では、複数行のファイルから 1 行を解析して出力します。元のスクリプトは、パーサーを ByteStrings のリストにマッピングしていました。ですから、ここでも同じことをしたいと思います。私enumLines
は Iteratee で見つけましたが、一生それを使用する方法を理解することはできません。多分私はその目的を誤解していますか?
parsing - attoparsec パーサーを再帰的にする
私は attoparsec パーサーをコーディングしており、パーサーを再帰パーサーに変えたいパターンにぶつかっています (それらをモナド bind >>= 演算子と再帰的に結合します)。
そこで、次のようにパーサーを再帰パーサーに変換する関数を作成しました。
次のような再帰的なデータ型がある場合に役立ちます
もっと慣用的な解決策はありますか?recursiveParser
ある種の折り畳みのように思えます...sepBy
ドキュメントでも見ましたが、この方法は私のアプリケーションにより適しているようです。
編集:ああ、実際に考えてみると、実際には似たようなものになるはずfix
です...どうやってそれを忘れたのかわかりません。
EDIT2 : Rotsor は私の例に対する彼の代替案で良い点を指摘していますが、残念ながら、私の AST は実際にはそれよりも少し複雑です。実際にはもっと似ています(ただし、これはまだ単純化されています)。
ここで、文字列a -> b
は右にc:d
ブラケット、左にブラケットし、:
よりきつく結合します->
。
つまり、次a -> b
のように評価されます
とc:d
評価されます
foldl
一方と他方に使用できると思いますがfoldr
、まだ複雑です。少し奇妙な方法で再帰的であるため、"a:b:c -> e:f -> :g:h ->"
実際には有効な文字列ですが、そう"-> a"
では"b:"
ないことに注意してください。結局、私にfix
はもっと簡単に思えました。再帰メソッドの名前を次のように変更しました。
ありがとう。
haskell - マップと ByteString キーを使用したフォールドのパフォーマンス分析
私は、apache ログ ファイルから何らかの興味深い (実際にはそうではない) 統計を読み込んで解析し、導出するための小さなスクリプトを用意しています。これまでのところ、ログ ファイル内のすべての要求で送信されたバイトの合計数と、最も一般的な IP アドレスの上位 10 という 2 つの簡単なオプションを作成しました。
最初の「モード」は、解析されたすべてのバイトの単純な合計です。2 つ目は、マップ (Data.Map) の折り畳みでinsertWith (+) 1'
、出現回数をカウントするために使用します。
最初のものは期待どおりに実行され、ほとんどの時間は解析に費やされ、一定のスペースで実行されます。
42,359,709,344 バイトがヒープに割り当てられた 72,405,840 バイトが GC 中にコピーされた
世代 0: 76311 コレクション、
0 並列、0.89 秒、0.99 秒経過
世代 1: 1553 コレクション、0 並列、0.21 秒、0.22 秒経過INIT 時間 0.00 秒 ( 0.00 秒経過) MUT 時間 21.76 秒 ( 24.82 秒経過) GC 時間 1.10 秒 ( 1.20 秒経過) EXIT 時間
0.00 秒 ( 0.00 秒経過) 合計時間 22.87 秒 ( 26.02 秒経過)%GC 時間 4.8% (4.6% 経過)
割り当てレート 1,946,258,962 バイト/MUT 秒
生産性 総ユーザーの 95.2%、総経過時間の 83.6%
しかし、2番目のものはそうではありません!
ヒープに割り当てられた 49,398,834,152 バイト GC 中にコピーされた 580,579,208 バイト 最大常駐 (15 サンプル) 718,385,088 バイト 最大スロップ 134,532,128 バイト
ジェネレーション 0: 91275 コレクション、
0 並列、252.65 秒、254.46 秒経過
ジェネレーション 1: 15 コレクション、0 並列、0.12 秒、0.12 秒経過INIT 時間 0.00 秒 (0.00 秒経過) MUT 時間 41.11 秒 (48.87 秒経過) GC 時間 252.77 秒 (254.58 秒経過) EXIT 時間
0.00 秒 (0.01 秒経過) 合計時間 293.88 秒 (303.45 秒経過)%GC 時間 86.0% (83.9% 経過)
割り当て率 1,201,635,385 バイト/MUT 秒
生産性 総ユーザーの 14.0%、総経過時間の 13.5%
そして、これがコードです。
編集:
+RTS -A16M を追加すると、GC が 20% に減少しました。もちろんメモリ使用量は変わりません。
haskell - Attoparsec での条件付き解析とキャスト
長さがエンコードされたバイナリ ストリームを解析しており、このコードをコンパイルしようとしています。コンビナトレントコード ( https://github.com/jlouis/combinatorrent/blob/master/src/Protocol/Wire.hs ) は非常に役に立ちましたが、今は行き詰まっています。return ステートメントで frame_length を使用するにはどうすればよいですか?
また、Word64 にパス (AP.take 8) を使用するにはどうすればよいですか?
haskell - パーセクのアトパーセク`inClass`に相当
パーサーはより適切なエラーメッセージを生成する必要があるため、一部のコードをattoparsecからParsecに変換しています。attoparsecコードはinClass
(およびnotInClass
)を広範囲に使用します。inClass
発生を機械的に変換できるParsecの同様の機能はありますか?HayooとHoogleは、この問題についての洞察を提供しませんでした。
inClass "a-c'-)0-3-"
はと同等です\ x -> elem x "abc'()0123-"
が、後者は非効率的で、広い範囲に書き込むのは面倒です。
他に何も利用できない場合は、自分で関数を再実装します。