Генерация уникальных идентификаторов для индексации контента JSON

Мне удалось запустить его, создав пароль для конкретного приложения (как указано в вопросе). Затем следуйте руководству по VULTR . Но я получал сообщение об ошибке:

Ошибка конфигурации eximʻa в строке 22 файла / var / lib / exim4 / config.autogenerated.tmp:

неверное определение макроса

Мне пришлось apt-get remove - -purge exim4-config , чтобы все это очистить. Затем переустановите exim4 с помощью apt-get install exim4 .

2
03.08.2018, 04:34
3 ответа

В качестве мысленного эксперимента я хотел посмотреть, насколько далеко мы можем продвинуть инструменты CLI для решения такого рода проблем. С этой целью я хотел попробовать использовать CLI-инструмент для быстрого хэширования xxHash для выполнения этой работы.

xxHash is an extremely fast non-cryptographic hash algorithm, working at speeds close to RAM limits. It is proposed in two flavors, 32 and 64 bits.

Он доступен в каждом языке программирования, но для этого эксперимента я собираюсь использовать разновидность CLI, xxhsum, в частности, 32-битный режим, поэтому xxhsum -H0.

Как вы уже выяснили и как заявляли другие, повторный вызов инструмента CLI хэш-функции или любого другого инструмента обычно приводит к тому, что подходы такого типа терпят неудачу. Вызов xxhsumздесь 5 миллионов раз был бы неоптимальным -способом его использования. Его сила заключается в файловом вводе-выводе, так что, если бы мы взяли 5 миллионов строк и преобразовали их в файлы размером 5 миллионов?

Эта задача на самом деле тривиальна в Linux с помощью команды split:

split -l 1 afile

И насколько быстро будет хешировать, скажем, 1 миллион этих файлов, в каждом из которых есть такая строка.

образец 1-строчного файла
$ cat datadir/xzeyw
{"name": "John4000", "surname": "Gates", "country": "Germany", "age": "20", "height": "180"} 
каталог с 1M файлами
$ ls -l datadir | wc -l
1000002
пора их смешивать
$ { time xxhsum -H0 * >../nfile 2>&1 ;} |& awk '/real|user|sys/ {print $1": "$2"\t"}' | tr -d '\n'
real: 0m6.998s  user: 0m5.007s  sys: 0m1.569s

Да, верно, это заняло ~7 секунд! Я нахожу это довольно впечатляющим. Используя xxhsumтаким образом, мы понесли затраты на его запуск только один раз и позволили ему пройти через 1 миллион файлов.

Недостатки этого метода

Таким образом, одним из недостатков этого способа является, конечно, split. Это становится нашей самой дорогой операцией, как вы можете себе представить. Поскольку нам нужно взять один файл с X строками и взорвать его на жесткий диск как X файлов с одной строкой в ​​нем.

Вот некоторые из этих данных:

./hashy.bash

make data
---------
real: 0m17.492s user: 0m12.434s sys: 0m4.788s

split data
----------
real: 2m15.180s user: 0m0.700s  sys: 2m4.443s

hash data
---------
real: 0m6.487s  user: 0m5.798s  sys: 0m0.459s

Здесь мы видим, что наша splitоперация заняла ~2 минуты.ПРИМЕЧАНИЕ.:В первой строке этого вывода показано время создания файла с 1 млн строк JSON.

Другим недостатком является количество файлов, с которыми мы имеем дело в командной строке. Я использую *в некоторых местах, так что это расширится до 1M или 5M имен файлов, что может считаться опасным, это так. Имейте в виду, что при увеличении количества файлов вы рискуете превысить объем пространства, выделенного для аргументов командной строки.

Обратитесь к этим ссылкам относительно длины командной строки:

Заключение

Как вы понимаете, решение подобной проблемы с помощью файлов размером 1 или 5 МБ кажется почти нелепым. И мне пришлось бы согласиться. Но это все равно интересный эксперимент, поскольку он показывает, что если вы используете инструменты CLI соответствующим образом, вы можете добиться от них отличной производительности.

Код для hashy.bash

Если кому интересно код:

$ cat hashy.bash
#!/bin/bash

echo ""
echo "make data"
echo "---------"
rm -f afile
{ time for i in {0..1000000};do echo "{\"name\": \"John${i}\", \"surname\": \"Gates\", \"country\": \"Germany\", \"age\": \"20\", \"height\": \"180\"}">> afile ;done ;} \
  |& awk '/real|user|sys/ {print $1": "$2"\t"}' | tr -d '\n'
echo ""
echo ""

rm -fr datadir && mkdir datadir && cd datadir

echo "split data"
echo "----------"
{ time split -l 1../afile ;} |& awk '/real|user|sys/ {print $1": "$2"\t"}' | tr -d '\n'
echo ""
echo ""

echo "hash data"
echo "---------"
{ time xxhsum -H0 * >../nfile 2>&1 ;} |& awk '/real|user|sys/ {print $1": "$2"\t"}' | tr -d '\n'

cd - > /dev/null 2>&1
echo ""
echo ""

Ссылки

1
27.01.2020, 21:55

Реализация вашей простой идеи ID в awk, предполагая, что строки JSON такие, как вы указали --все в одной строке:

awk -F'"' 'BEGIN{OFS=FS} {$1=$1"\"id\": \""$4$8$12$16$20"\", "; }1' < input

У меня нет системы, сравнимой с вашей, так что вам придется посмотреть, подходит ли время.

1
27.01.2020, 21:55

Готов поспорить, что причина, по которой ваши скрипты занимают так много времени, заключается в том, что вы запускаетеuuidgen(илиcksum)для каждой строки. Много времени тратится впустую, просто запуская процессы для каждого из них.

Если поместить 5 млн строк формы {"name": "John%d", "surname": "Gates", "country": "Germany", "age": "20", "height": "180"}в файл в файловой системе tmpfs, следующий скрипт Python завершится за секунды:

#! /usr/bin/env python3

import hashlib
import sys
for line in sys.stdin:
    print(hashlib.md5(line.rstrip('\n').encode('utf-8')).hexdigest())

Исполнение:

$ time./foo.py < input > output
./foo.py < input > output  6.00s user 0.13s system 99% cpu 6.135 total
% wc -l input output
  5000000 input
  5000000 output
 10000000 total

Поскольку это Python, вы также можете декодировать строки в формате JSON -и вставлять в каждую из них идентификатор. Даже неэффективный код вроде:

#! /usr/bin/env python3

import hashlib
import json
import sys
for line in sys.stdin:
    l = line.rstrip('\n').encode('utf-8')
    o = json.loads(line)
    o["id"] = hashlib.md5(l).hexdigest()
    print(json.dumps(o))

Готово менее чем за минуту:

% time./foo.py < input > output
./foo.py < input > output  42.11s user 0.42s system 99% cpu 42.600 total

% head output 
{"name": "John1", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2dc573ccb15679f58abfc44ec8169e52"}
{"name": "John2", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "ee0583acaf8ad0e502bf5abd29f37edb"}
{"name": "John3", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "a7352ebb79db8c8fc2cc8758eadd9ea3"}
{"name": "John4", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2062ad1b67ccdce55663bfd523ce1dfb"}
{"name": "John5", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "5f81325c104c01c3e82abd2190f14bcf"}
{"name": "John6", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "493e0c9656f74ec3616e60886ee38e6a"}
{"name": "John7", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "19af9ef2e20466d0fb0efcf03f56d3f6"}
{"name": "John8", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "2348bd47b20ac6445213254c6a8aa80b"}
{"name": "John9", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "090a521b4a858705dc69bf9c8dca6c19"}
{"name": "John10", "surname": "Gates", "country": "Germany", "age": "20", "height": "180", "id": "fc3c699323cbe399e210e4a191f04003"}

Мои характеристики:

  • Процессор Intel® Core™ i7 -8700 с тактовой частотой 3,20 ГГц × 12
  • Память DDR4 2666 МГц

Сценарий, основанный на uuidgen-, едва смог закончить 500 тыс. строк за 4 минуты. Изменено для сохранения вывода:

#!/usr/bin/bash

while IFS= read -r line
do
   uuidgen -s --namespace @dns --name "$line"
done < input > uuid

Исполнение:

% timeout 240./foo.sh
% wc -l uuid
522160 uuid
3
27.01.2020, 21:55

Теги

Похожие вопросы