>>потом эту data парсишь заново
> Ну и что? Где-то будет иначе? Всё равно обходить всё заново.Нет. json парсится в хеш-таблички, поиск в хештабличке и вставка туда элемента -- это O(log N). Если ты выполняешь это N раз, то ты получаешь O(N*log(N)), что в принципе терпимо.
>>time
> Замерять по одному вызову такое себе, надо выполнить хотя бы 10 и
> брать среднее, и то может там в фоне что-то крутится эдакое.
Как показывает практика, если запустить один раз для прогрева, и потом второй раз для измерения, то ты получишь числа с точностью достаточной для бытовых нужд. Этот же результат был получен в результате четырёх запусков команды, выкидыванием первого результата, и выбора среднего из оставшихся трёх. И да, если бы эти оставшиеся три сильно различались бы, я бы так не стал делать, а начал бы здесь писать о недетерминированности времени выполнения jq, и о том, что его писали какие-то лохи, которых вообще нельзя допускать до программирования.
>>Что он там делает
> Емнип там интерпретатор байткода (много фишечек, да), так что не так и
> много. Весь питон со штатным json кстати столько же примерно инициализируется,
> поэтому заменять на него смысла и нет. Памяти точно в тысячи
> тысяч раз больше уйдёт, и скорее всего медленнее будет.
Если есть длинная инициализация, то напрашивающийся способ оптимизации -- выполнять эту инициализацию единожды. В этот jq можно засунуть сразу _все_ его команды, чтобы он их выполнил последовательно за один запуск процесса?
на пайтоне нет проблем написать скрипт, который будет читать строки вида ."key" += {"item":["value"]}, парсить их в три локальные переменные key, item и value, а потом делать data[key][item]=value. То есть весь код будет выглядеть так (warning: псевдокод, я не помню python'а и не знаю его API для работы с json'ом):
def read_input_line():
// тут мы читаем входную строку, парсим её в три строки и возвращаем их
while (key, item, value) = read_input_line():
data[key][item] = value
print(json_to_string(data))
> где-то есть более быстрый и удобный процессор жсона? Я просто
> раньше питон с этими целями использовал в скриптах, но jq более
> быстрый.
Для быстроты основной подход -- процессить не json, а структуры в памяти. В нативные для языка структуры в памяти. И после процессинга сериализовать в json. Если ты в bash напишешь скрипт, который соберёт все эти строчки в ассоциативный массив ассоциативных массивов, а потом сериализуешь эту конструкцию в json, у тебя получится быстрее чем 500 запусков jq, написанного на C. Но у bash, что-то мне подсказывает, есть проблемы с ассоциативными массивами ассоциативных массивов, потому как, видите ли, поддержка такого "ненужна", потому что всегда можно сделать что-то типа:
$data[$key@$item]=$value
Или это в awk так? Где-то такая офигительная оптимизация работы с хештабличками точно заботливо навязывалась программисту. Типа это быстрее. Я, за давностью лет, не помню где.
А насчёт удобства -- я не знаю, я с json'ом сталкиваюсь эпизодически, и поэтому не особо парюсь об удобстве, пишу на том языке, на котором столкнулся с json'ом.
Я бы, будучи на голову ушибленным rust'ом, написал бы всё на rust'е. Собственно, я и написал:
// сначала тут ~70 строк описывающих генерацию charset'а, и троек случайных строк в этом charset'е, и затем:
fn main() {
let mut rng = rand::thread_rng();
let charset = generate_charset("a-zA-Z0-9").expect("Invalid charset");
let mut data: HashMap<String, HashMap<String, String>> = HashMap::new();
for _ in 0..2000 {
let (key, item, value) = random_addition(&mut rng, &charset);
let entry = data.entry(key).or_insert(HashMap::new());
entry.insert(item, value);
}
println!("{}", serde_json::to_string(&data).expect("Fuck up"));
}
Тут генерится 2000 троек случайных строк (key, item, value), они добавляются в хеш-табличку хеш-табличек, и потом всё это сериализуется при помощи serde_json::to_string();
$ time cargo run >/dev/null
Compiling gen-strings v0.0.1 (/home/rgo/tmp/jq-test)
Finished dev [unoptimized + debuginfo] target(s) in 5.14s
Running `target/debug/gen-strings`
real 0m5,781s
user 0m1,961s
sys 0m0,412s
И это отработала версия собранная без особых оптимизаций в debug варианте. Что гораздо хуже, запущенная через cargo, который прежде чем запускать компилировал. Если эту логику написать на python, bash или чём угодно ещё, то оно будет в разы быстрее, потому что не нужна сложная компиляция.