ワード周波数 gawk メモリリーク

ワード周波数 gawk メモリリーク

次のbashスクリプトがあります。

#!/usr/bin/env bash

grep -e '^[a-zA-Z]\{4,8\}$' data/words3.txt | tr '[:upper:]' '[:lower:]' | sort -u > data/passphrase-words.txt

function wordfrequency() {
  awk '{ for (i=1; i<=NF; i++) { word = tolower($i); words[word]++ } } END { for (w in words) printf("%3d %s\n", words[w], w) } ' | sort -rn
}

function getArticleText() {
  awk '/<text xml:space="preserve">/,/<\/text>/' | sed 's/<.*>//'
}

function reduceWikiText() {
  tr ' [:punct:]' '[\n*]' | sed '/^$/d' | tr '[:upper:]' '[:lower:]'
}

bzcat data/enwiki-20161020-pages-articles.xml.bz2 | getArticleText | reduceWikiText | grep -F -f data/passphrase-words.txt | wordfrequency > data/wordFreqs.txt

さまざまな方法で単純化できると確信していますが、これが私が思いついたものです。 data/passphrase-words は、1 行に 1 ワードずつ約 170,000 語で構成されるリストです。data/enwiki-*12GBの圧縮XMLです(Wikipediaダンプです)。ここで getArticleText は各記事のテキストを取得し、ReduceWikiText はそのテキストを 1 行に 1 単語に「減らし」、すべての XML と句読点を削除しますが、単語頻度は各単語が表示される頻度を計算します。

タスクマネージャを正しく読み取ると wordFrequency() 内部の gawk が 695MB、十分長く実行すると 1GB 以上のメモリを使用しています。

どの機能にも属さないgrepコマンドは、gawkが表示できる一意の単語数を制限し、一定の36MBを占めます。 50MBまたは100MBが必要なgawkを見ることができますが、1GB以上の場合はどうなりますか?これは間違っているようです。成長率は無限に成長するという意味です。

gawkがなぜそんなに多くのメモリを使うのかを知る必要がありますか? BZ2ファイルのサイズのため、gawkがあまりにも手から外れることはありません...

私は sort | uniq-c | sort -nrを使用しない理由は、私が作業している単語の数に対して機能することを知っているからです。 HDD使用量の削減=より高速ですか?

ちなみに、Windows用のLinuxサブシステムは次のとおりです。

$ gawk --version
GNU Awk 4.0.1
Copyright (C) 1989, 1991-2012 Free Software Foundation.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program. If not, see http://www.gnu.org/licenses/.

編集する:私が得たもの(12GB .xml.bz2ファイルを除く)を次の場所に投稿します。https://github.com/proegssilb/wikipedia-wordcount。コメントで提案したように、mawkを使用しても何も起こらないようですが、200MB RAMでプロセスを停止しました。何が起こっているのかを確認するために、awkを使用せずに一晩プロセスを実行してみてください。

編集2:問題のあるawkを交換した後、| sort | uniq -c私がいない間、6〜7時間で作業が完了しました。私はいくつかの追加の調整を行い、記事からHTMLの使用を取り除き(あまりにも多くの汚染を引き起こす「」」を取り除き)、もう一度やり直そうとしますが、少なくとも今は「合理的な」環境で実行されています。

ベストアンサー1

したがって、役に立ついくつかのことがありますが、これを行うための最も重要なことはsort | uniq -cgawkの代わりにグレゴリー・ニスベットによると

私も結局使うことになった@dave_thompson_085でコメントについてtr -sc '[:alpha:]' '\n'。このフラグは反復を結合します。つまり、空行を削除して探している文字セットを逆にする-s必要はありません。-cの副作用は、-cセットではなく1つの代替文字しか使用できないことです。 Daveにも感謝しますgrepと正確なラインマッチングに関する質問-x)。私がこのコメントに投票する評判があれば、そうしたことでしょう。

結局、XMLエンティティ(&quot;)を削除し、html(重複<ref />)を削除するためにいくつかの追加コードを使用する必要がありました。のgetArticleText新しいsedコマンドはです| sed -e 's/&quot;/"/g' -e 's/&lt;/</g' -e 's/&gt;/>/g' -e 's/&amp;/&/g' -e 's/<.*>//g'。各式(-elinkコマンド)は異なるHTMLエンティティを処理します。私はもう少し完全なオプションを試しました(例:Perlを使用)。スタックオーバーフロー)が、私の場合は、コンピュータ関連の問題のために動作しません。最終的なスクリプトは以下にあります。私の単語ライブラリ

私のコンピュータでスクリプトを完了するのに3時間20分かかりましたが、このドライブも数年前の6コアAMDドライブでした。お客様のマイルは異なる場合がありますが、これで十分でした。

@Gregory Nisbetまたは@dave_thompson_085が自分の回答を投稿したい場合は、投稿できるようにこの回答を受け入れません。

おすすめ記事