단어 주파수 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는 한 줄에 한 단어씩 약 170,000개의 단어로 구성된 목록입니다. data/enwiki-*12GB의 압축된 XML입니다(Wikipedia 덤프입니다). 여기에서 getArticleText는 각 기사의 텍스트를 가져오고, ReduceWikiText는 해당 텍스트를 한 줄에 한 단어로 "줄이고" 모든 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 대신그레고리 니스벳(Gregory Nisbet)에 따르면.

나도 결국 사용하게 됐어@dave_thompson_085의 댓글에 대한 tr -sc '[:alpha:]' '\n'. 이 플래그는 반복을 결합합니다. 즉, 빈 줄을 제거하고 찾고 있는 문자 집합을 반대로 바꿀 -s필요가 없습니다 . -c의 부작용은 -c세트가 아닌 하나의 대체 문자만 사용할 수 있다는 것입니다. 데이브에게도 감사드립니다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가 자신의 답변을 게시하려는 경우 게시할 수 있도록 이 답변을 수락하지 않겠습니다.

관련 정보