Eu tenho o seguinte script:
#!/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
Tenho certeza de que poderia ser simplificado de várias maneiras, mas é o que eu criei. data / passphrase-words é uma lista de cerca de 170k palavras, uma palavra por linha. data/enwiki-*
é 12GB de XML compactado (é um dump da Wikipedia). A partir daí, getArticleText pega o texto de cada artigo, reduceWikiText "reduz" esse texto para uma palavra por linha, eliminando todos os xml e pontuação, e a palavra frequencia conta quantas vezes cada palavra aparece.
Se eu estiver lendo meu gerenciador de tarefas corretamente, o gawk dentro de wordFrequency () está usando quantidades massivas de memória; 695MB, se eu deixar correr o suficiente, mais de 1GB de RAM.
O comando grep que não faz parte de nenhuma função limita o número de palavras diferentes que o gawk verá, e ocupa uma constante de 36 MB. Eu poderia ver o gawk precisando de 50 MB ou até 100 MB, mas com mais de 1 GB? Isso parece errado. E a taxa de crescimento implica que crescerá sem limites.
Alguém pode me ajudar a descobrir por que o gawk está usando tanta memória? Devido ao tamanho do arquivo BZ2, não posso deixar que o Gawk saia muito do controle ...
E a razão pela qual eu não estou usando o tipo | uniq -c | sort -nr é porque eu realmente quero que a agregação de contagem de palavras ocorra na memória; Eu sei que pode se encaixar, pelo número de palavras com as quais estou lidando. Menos uso de HDD = mais rápido, certo?
Para referência, o Linux Subsystem for Windows e:
$ 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/.
EDIT: Publicou o que eu tenho (menos o arquivo de 12GB .xml.bz2) em link se isso ajudar. Usando mawk, conforme as sugestões nos comentários, não parece fazer nada, mas eu parei o processo em 200MB de RAM. Permitirá que o processo seja executado durante a noite sem usar o awk, apenas para ver o que acontece.
EDIT2: Após substituir em | sort | uniq -c
pelo awk problemático, o processo foi concluído dentro das 6-7 horas que eu estava fora. Eu vou fazer alguns ajustes para tentar remover o uso de HTML em artigos (se livrar de "" causando tanta poluição), e tempo de novo, mas pelo menos ele é executado em uma quantidade "razoável" de tempo agora .