Стандартный выход Добавить к ограничениям на размер файла

Я извлекаю спецификации VIN из API Национальной администрации безопасности дорожного движения для примерно 25 000 000 номеров VIN. Это большой объем данных, и, поскольку я никоим образом не преобразую данные, curl кажется более эффективным и легким способом выполнения задачи, чем Python (учитывая, что GIL Python делает параллельную обработку немного трудной) ,

В приведенном ниже коде vins.csv – это файл, содержащий большую выборку из 25 миллионов VIN, разбитых на куски по 100 VIN. Они передаются в GNU Parallel, который использует 4 ядра. В конце все сбрасывается в nhtsa_vin_data.csv .

 $ cat vins.csv | parallel -j10% curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /nas/BIGDATA/kemri/nhtsa_vin_data.csv 

Вначале этот процесс записывал около 3000 VIN-ов в минуту и ​​постепенно прогрессировал со временем (в настоящее время около 1200 в минуту).

Мои вопросы

  • Есть ли в моей команде что-нибудь, что будет увеличиваться из-за увеличения размера nhtsa_vin_data.csv ?
  • Это связано с тем, как Linux обрабатывает >> операции?

ОБНОВЛЕНИЕ № 1 – РЕШЕНИЯ

Первое решение для @slm – используйте параметры параллельного файла tmp, чтобы записать каждый вывод curl в свой собственный файл .par, объедините в конце:

 $ cat vins.csv | parallel \ --tmpdir /home/kemri/vin_scraper/temp_files \ --files \ -j10% curl -s \ --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ > /dev/null cat <(head -1 $(ls *.par|head -1))  all_data.csv 

Второе решение для @oletange – использовать –line-buffer для буферизации вывода в память вместо диска:

 $ cat test_new_mthd_vins.csv | parallel \ --line-buffer \ -j10% curl -s \ --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /home/kemri/vin_scraper/temp_files/nhtsa_vin_data.csv 

Вопросы производительности

Я нахожу оба решения, предложенные здесь, очень полезными и интересными и определенно буду использовать обе версии больше в будущем (как для сравнения производительности, так и для дополнительной работы API). Надеюсь, я смогу запустить несколько тестов, чтобы увидеть, какой из них лучше подходит для моего варианта использования.

Кроме того, было бы целесообразно запустить какой-нибудь тест производительности, такой как @oletange и @slm, так как вероятность того, что NHTSA станет узким местом, не является ничтожной.

Я подозреваю, что >> вызывает у вас конфликт по файлу nhtsa_vin_data.csv среди команд curl которые parallel распадается для сбора данных API.

Я бы настроил ваше приложение так:

 $ cat p.bash #!/bin/bash cat vins.csv | parallel --will-cite -j10% --progress --tmpdir . --files \ curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ 

Это даст вашим командам curl собственный изолированный файл для записи своих данных.

пример

Я взял эти 3 VIN, 1HGCR3F95FA017875;1HGCR3F83HA034135;3FA6P0T93GR335818; , что вы предоставили мне и поместили их в файл с именем vins.csv . Затем я скопировал их несколько раз, чтобы этот файл имел следующие характеристики:

VIN на строку

 $ tail -1 vins.csv | grep -o ';' | wc -l 26 

Количество строк

 $ wc -l vins.csv 15 vins.csv 

Затем я запустил свой скрипт, используя эти данные:

 $ ./p.bash Computers / CPU cores / Max jobs to run 1:local / 1 / 1 Computer:jobs running/jobs completed/%of started jobs/Average seconds to complete local:1/0/100%/0.0s ./pard9QD3.par local:1/1/100%/10.0s ./paruwK9L.par local:1/2/100%/8.5s ./parT6rCS.par local:1/3/100%/7.3s ./pardzT2g.par local:1/4/100%/6.8s ./parDAsaO.par local:1/5/100%/6.8s ./par9X2Na.par local:1/6/100%/6.7s ./par6aRla.par local:1/7/100%/6.7s ./parNR_r4.par local:1/8/100%/6.4s ./parVoa9k.par local:1/9/100%/6.1s ./parXJQTc.par local:1/10/100%/6.0s ./parDZZrp.par local:1/11/100%/6.0s ./part0tlA.par local:1/12/100%/5.9s ./parydQlI.par local:1/13/100%/5.8s ./par4hkSL.par local:1/14/100%/5.8s ./parbGwA2.par local:0/15/100%/5.4s 

Собираем вещи вместе

Когда все вышеперечисленное выполнено, вы можете объединить все файлы вместе, чтобы получить один файл .csv .

 $ cat *.par > all_data.csv 

Будьте внимательны при этом, поскольку каждый файл имеет собственную строку заголовка для данных CSV, которые содержатся внутри. Чтобы справиться с удалением заголовков из файлов результатов:

 $ cat <(head -1 $(ls *.par|head -1)) <(tail -q -n +2 *.par) > all_data.csv 

Ваше замедление производительности

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

Моя производительность на ноутбуке была следующей:

 $ seq 5 | parallel --will-cite --line-buffer 'yes {} | head -c 1G' | pv >> /dev/null 5GiB 0:00:51 [99.4MiB/s] [ <=> ] 

ПРИМЕЧАНИЕ: вышеприведенное заимствовано из ответа Оле Танге и изменено. Он записывает 5 ГБ данных через parallel и передает его в pv >> /dev/null . Используется pv поэтому мы можем отслеживать пропускную способность по каналу и получать измерения типа МБ / с.

Мой ноутбук смог набрать ~ 100 МБ / с пропускной способности.

FAQ по NHTSA API

API

Для «Декодировать VIN (плоский формат) в пакете» есть ли пример выполнения этого запроса по URL, аналогично другим действиям?

Для этого конкретного API вам просто нужно поместить в поле набор VIN, разделенных «;». Вы также можете указать модельный год до «;», разделенного «,». Существует верхний предел количества VIN-адресов, которые вы можете использовать с помощью этой услуги.

Пример в поле – образец: 5UXWX7C5 * BA, 2011; 5YJSA3DS * EF

Источник: https://vpic.nhtsa.dot.gov/MfrPortal/home/faq искал “рейтинг”

Выше упоминается, что есть верхний предел при использовании API:

Существует верхний предел количества VIN-адресов, которые вы можете использовать с помощью этой услуги.

Рекомендации

  • GNU Parallel man page
  • GNU Parallel Tutorial
  • Распечатать файл, пропустив первые X строк в Bash

Производительность обычно ограничена одним из них:

  1. Пропускная способность сети. Вы можете использовать sudo iftop чтобы увидеть, используется ли ваше сетевое соединение на 100%.
  2. Сетевая задержка. Если серверу на другом конце требуется много времени для ответа, то вы не увидите 100% использования полосы пропускания.
  3. Дисковый ввод / вывод. Вы можете использовать iostat -dkx 1 чтобы проверить, используется ли ввод-вывод любого из ваших дисков на 100%.
  4. ЦПУ. Вы можете использовать top если ваши процессоры загружены на 100%. Нажмите 1 чтобы увидеть отдельные streamи процессора. Если один из них на 100%, то у вас есть однопоточная программа, которая ограничена этим.

GNU Parallel хорош для параллельного выполнения заданий, чтобы использовать больше пропускной способности, дискового ввода-вывода и процессора.

Но это также имеет свои ограничения.

GNU Parallel обычно кеширует вывод в /tmp . Это означает, что ваш дисковый ввод / вывод в /tmp может быть узким местом.

К счастью, имея дело с CSV, вы редко заботитесь о порядке строк: хорошо, если строки смешиваются, если это целые строки.

Если вы используете --line-buffer от версии> 20170822, то GNU Parallel не буферизует вывод на диск – он только буферизует одну полную строку в памяти. Требуется немного больше ресурсов процессора, поэтому проверьте, использует ли parallel процессор на 100%. Если он использует меньше, то вы не достигли этого узкого места.

 $ cat vins.csv | parallel --line-buffer curl -s --data "format=csv" \ --data "data={1}" https://vpic.nhtsa.dot.gov/api/vehicles/DecodeVINValuesBatch/ \ >> /nas/BIGDATA/kemri/nhtsa_vin_data.csv 

Вы можете увидеть, есть ли у вас местное узкое место:

 $ seq 1000 | parallel --line-buffer 'yes {} | head -c 1G' | pv >> /nas/BIGDATA/test 

На моем паршивом ноутбуке я получаю около 100 МБ / с. Так что мой паршивый ноутбук сможет работать с 1 Гбит / с с dot.gov.