LINUX.ORG.RU
ФорумTalks

А давайте померяемся

 libyaml, ,


1

1

Тут знакомый парсил ямловский файл на несколько мегабайт, и получил странные результаты

js-yaml (https://github.com/nodeca/js-yaml) - около 1 секунды
ruby/python нативные биндинги к libyaml - около 30 секунд

Колесо пинал, дверь хлопал, гудок жал, глаза протирал. Прошу подтвердить. Я был в курсе, что pyyaml не до конца вменяем, но насчет libyaml не подозревал.

Данные https://gist.github.com/anonymous/5028302

Запускался просто импорт, с разными библиотеками.

time ruby -r yaml -e "YAML.load_file 'data.yml'"
time ruby -r psych -e "Psych.load_file 'data.yml'"
time python -c "import yaml; yaml.load(open('data.yml'))"
time js-yaml -j data.yml > /dev/null
time ruby -r syck -e "Syck.load_file 'data.yml'"

Update

После разбора и улучшений выяснилось, что libyaml медленнее «всего лишь» в 2-4 раза нативного JS. Оказывается, у поциента не открытый, а закрытый перелом. Что не снимает вопроса «какого хрена?»

time js-yaml -j data.yml > /dev/null

real	0m1.420s
user	0m1.272s
sys	0m0.148s

то же самое, но без cli:

time node -e "var yaml=require('js-yaml'), text=require('fs').readFileSync('data.yml', 'utf-8'); yaml.load(text);"

real	0m0.984s
user	0m0.940s
sys	0m0.040s

нода с libyaml:

time node -e "require('libyaml').readFileSync('data.yml');"

real	0m3.424s
user	0m3.300s
sys	0m0.136s

питон с libyaml:

time python -c "import yaml; from yaml import CLoader as Loader; yaml.load(open('data.yml'),Loader=Loader)"

real	0m5.530s
user	0m5.268s
sys	0m0.212s

Perl (хм, неплохо, перепроверил)

time perl -MYAML::XS -e 'YAML::XS::LoadFile "data.yml"'

real	0m0.484s
user	0m0.456s
sys	0m0.024s

PHP (ну раз перл быстрый, наверное и PHP может быть)

time php -r 'yaml_parse_file("/Users/olegchiruhin/Documents/data.yml");'
php -r 'yaml_parse_file("/Users/olegchiruhin/Documents/data.yml");'  

0,49s user 
0,04s system 
99% cpu 
0,537 total

В рубях 2.0 ~ как в питоне, 6 секунд.

syck в рубях (не полная реализация, биндинги) - 0.9 секунд

java (snakeyaml) - 1.7 секунды без прогревва и 0.9 с прогревом ( А давайте померяемся (комментарий) и А давайте померяемся (комментарий) )

JSON node.js (просто для сравнения)

time node -e "var text=require('fs').readFileSync('data.json', 'utf-8'); JSON.parse(text);"

real	0m0.265s
user	0m0.152s
sys	0m0.040s

Итого

Даже в php/perl, где (возможно) дешевое создание объектов или качественные биндинги, профит от libyaml всего в 2 раза. По сравнению с чистым яваскриптом, который еще не до конца оптимизирован.

Что-то тут не так.

★★★★★

Последнее исправление: Vit (всего исправлений: 9)

итересно было бы посмотреть сравнение с C/C++

ZuBB ★★★★★
()
Ответ на: комментарий от winddos

Вполне ожидаемо, что V8 быстрее любого из скриптовых языков.

libyaml

baverman ★★★
()
Ответ на: комментарий от drakmail

Ну так причем тут биндинги, если просадку дает запуск среды исполнения.
Если на скриптовых языках запустить с JIT или скомпилировав в нативщину, то вполне могут получиться и другие результаты.

winddos ★★★
()

Посоны не качайте т...

zolden ★★★★★
()
Ответ на: комментарий от winddos

Ну так причем тут биндинги, если просадку дает запуск среды исполнения.

Ты такую ахинею сейчас порешь.

30c

baverman ★★★
()
Ответ на: комментарий от baverman

Там сиды проприетарные, не могу.

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

Vit ★★★★★
() автор топика
Ответ на: комментарий от winddos

запустить с JIT

LibYAML is a YAML 1.1 parser and emitter written in C.

Одна история удивительнее другой.

dmfd
()
Ответ на: комментарий от winddos

Ну так причем тут биндинги, если просадку дает запуск среды исполнения.

ахаха, ты зачем меня так смешишь?

maloi ★★★★★
()
Ответ на: комментарий от baverman

Ты такую ахинею сейчас порешь.

Почему 30с это другой вопрос, но то что уже загруженный в память код быстрее обрабаотает чем стартующий скрипт это вполне очевидно.

winddos ★★★
()
Ответ на: комментарий от Vit

Ну так привел бы для начала методику тестирования.
Проблема ведь может быть совсем не в нативной библиотеке, а какой то специфической баге среды.
Скажем в php в некоторых ситуациях (работа с объектами) просадка бывала и в 200 раз, просто потому что 64-битный интерпритатор криво работал, или из за того что данные подгужались неоптимально.

winddos ★★★
()
Ответ на: комментарий от winddos

Блеат... уйди, праативный...

Vit ★★★★★
() автор топика

Так это, пусть исходник тестов дает, иначе нифига не понять. Какие могут быть мысли:

  • В руби/питоне долго создаются объекты которые парсит ямл (но что настолько я не верю)
  • Что передается на вход функции парсинга? Если не имя файла, а объект, то будет для чтения постоянно зваться питоновский код из С, что медленно
  • В JS, т.к. хеш-таблицы и манипуляции со строками очень часты, то операции с ними заоптимизированы до предела, в то время как сишный код мог работать со словарями не оптимально, что и сказалось на таком объеме. Например, в с++ хеш-таблица из STL работает _значительно_ медленнее на строках чем HashMap в Java.
theos ★★★
()
Ответ на: комментарий от Vit

ШОК!

import sys
import yaml

from random import randint, sample
from string import ascii_letters

def get_key(size=10):
    return ''.join(sample(ascii_letters, size))

def generate():
    data = {}
    for _ in xrange(100000):
        d = data
        for _ in xrange(randint(0, 4)):
            d = d.setdefault(get_key(), {})

        d[get_key()] = get_key(30)

    yaml.dump(data, sys.stdout)


def load():
    data = yaml.load(sys.stdin)
    print len(data)

#generate()
load()

http://rghost.net/download/44094011/783b9891c6ad2ca7709c80c6f75037d48bd072f5/...

(test)/tmp$ time python2 boo.py < data.yaml
100000

real	2m26.527s
user	2m25.417s
sys	0m0.930s

Причем оно еще и память жрет как не в себя.

baverman ★★★
()
Ответ на: комментарий от theos

Данные https://gist.github.com/anonymous/5028302

time ruby -r yaml -e «YAML.load_file 'purge.yml'»
time ruby -r psych -e «Psych.load_file 'purge.yml'»
time python -c «import yaml; yaml.load(open('purge.yml'))»

кросафчег:

time js-yaml -j purge.yml > /dev/null

вот этот в полтора раза быстрее JS, но там парсер нативный и обкоцаный:

time ruby -r syck -e «Syck.load_file 'purge.yml'»

Vit ★★★★★
() автор топика
Ответ на: комментарий от baverman

Я выше привёл варианты, которые слабали на скорую руку. Ну типа, в 10 раз ошибки быть не должно, а остальное не принципиально.

Теперь я понимаю людей, которые пишут, что ямл пипец какой тормозной. Дык libyaml везде воткнут, гы-гы.

Vit ★★★★★
() автор топика
Ответ на: комментарий от buddhist

пруф оф концепт - это PyYAML. Но он был очень медленным, и поэтому сделали libyaml. Быстрый, гы-гы.

При этом я точно знаю, что js-yaml не везде оптимизирован.

Vit ★★★★★
() автор топика

в PHP сравнивал реализацию Symfony и биндинг libyaml. Либямл победил больше чем на порядок (может даже больше, чем на два порядка, но за это уже не отвечаю ))

stevejobs ★★★★☆
()
Ответ на: комментарий от baverman

libyaml тупо тормоз.

Эээ, вообще то я это и написал в третьем пункте, просто я воспользовался либастралом и предположил причины его тормозов.

theos ★★★
()
Ответ на: комментарий от AITap

This module is a Perl XS binding to libyaml which offers Perl the best YAML support to date.

Что-то здесь не чисто.

baverman ★★★
()
Ответ на: комментарий от AITap

Очень странно. Может вы не все данные вытянули?

А вот яваскрипт на мелком mb air:

time js-yaml -j data.yml > /dev/null

real	0m1.420s
user	0m1.272s
sys	0m0.148s
Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

Upd. Я, оказывается использовал питонолоадер, вот обновленные цифры:

Мои данные.

(test)/tmp$ time python2 boo.py < data.yaml
100000

real	0m22.265s
user	0m21.953s
sys	0m0.283s

Твои.

(test)/tmp$ time python2 boo.py < boo.yaml
5

real	0m10.498s
user	0m10.397s
sys	0m0.090s

Что тоже не фонтан.

baverman ★★★
()
Ответ на: комментарий от baverman

Сорри, я перл не умею читать.

Но у него 100 000, а в моем примере 266 000 строк. Тогда JS все равно получается быстрее, хотя не до конца понятно, почему перловый вариант тупит намного меньше.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit
➜  ~  time php -r 'yaml_parse("/Users/olegchiruhin/Documents/data.yml");'
php -r 'yaml_parse("/Users/olegchiruhin/Documents/data.yml");'  

0,03s user 
0,01s system 
94% cpu 
0,051 total
➜  ~  
➜  ~  uname -a
Darwin narnia 12.1.1 Darwin Kernel Version 12.1.1: Fri Aug 10 16:12:30 PDT 2012; root:xnu-2050.15.57~1/RELEASE_X86_64 x86_64
➜  ~  php --version
PHP 5.4.8 (cli) (built: Nov 19 2012 20:44:28) 
Copyright (c) 1997-2012 The PHP Group
Zend Engine v2.4.0, Copyright (c) 1998-2012 Zend Technologies
    with Xdebug v2.2.1, Copyright (c) 2002-2012, by Derick Rethans
➜  ~  system_profiler | grep Processor
      Processor Name: Intel Core i7
      Processor Speed: 2,3 GHz
      Number of Processors: 1

AITap

real 1,154s

PERL FAIL

stevejobs ★★★★☆
()
Ответ на: комментарий от Vit

Я его уже разоблачил.

Хотя на моих фалах php тоже предельно шустр. Секунда с лишкой.

baverman ★★★
()
Последнее исправление: baverman (всего исправлений: 1)
Ответ на: комментарий от baverman

мне очень стыдно :(

забыл добавить _file

➜  ~  time php -r 'yaml_parse_file("/Users/olegchiruhin/Documents/data.yml");'
php -r 'yaml_parse_file("/Users/olegchiruhin/Documents/data.yml");'  

0,49s user 
0,04s system 
99% cpu 
0,537 total

c var_dump отрабатывает за 0,9 - но ему же еще срать в консольку. (и возвращает array(5))

FAIL PERL FAIL

ждем-с следующий этап разоблачений :)

stevejobs ★★★★☆
()
Ответ на: комментарий от baverman

Нашел биндинги libyaml для ноды. Внутрь не смотрел :)

time node -e "require('libyaml').readFileSync('data.yml');"

real	0m3.424s
user	0m3.300s
sys	0m0.136s

Все равно чистый жабаскрипт получается быстрее. При том что его при желании можно еще ускорить.

Vit ★★★★★
() автор топика
Ответ на: комментарий от Vit

питон песец

просто на компе ничего не выполняется вообще, кроме хромиума с парой десяток вкладок

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

системник - макмини-2012.

вот спека из system report:

Hardware Overview:

  Model Name:	Mac mini
  Model Identifier:	Macmini6,2
  Processor Name:	Intel Core i7
  Processor Speed:	2,3 GHz
  Number of Processors:	1
  Total Number of Cores:	4
  L2 Cache (per Core):	256 KB
  L3 Cache:	6 MB
  Memory:	16 GB

В общем, попробовал твои тесты:

➜  Documents  time ruby -r yaml -e "YAML.load_file 'data.yml'" 
ruby -r yaml -e "YAML.load_file 'data.yml'"  0,48s user 0,02s system 99% cpu 0,504 total

короче, примерно так же как похапэ

с психом запустить не могу, потому что придется пересобрать новый руби из исходников (у мну только 1.8), а это долго

а вот Пейтон очканул

➜  Documents  time python -c "import yaml; yaml.load(open('data.yml'))" 

python -c "import yaml; yaml.load(open('data.yml'))"  36,50s user 0,63s system 99% cpu 37,125 total

Вначале я подумал, что он завис, и побежал смотреть top. В топе висел процесс пейтона и жрал 100% процессора. Через 30 секунд он разродился вот этой строчкой.

stevejobs ★★★★☆
()

YAML

Сжечь напалмом.

shahid ★★★★★
()
Ответ на: питон песец от stevejobs
import java.io.{File, FileInputStream}
import org.yaml.snakeyaml.Yaml

object yamlBnch {
  def main(args:Array[String]){
    val input = new FileInputStream(new File("data.yml"))
    val yaml = new Yaml()
    val data = yaml.load(input).asInstanceOf[java.util.LinkedHashMap[String, String]]
    println(data.keySet().size())
  }
}
time java -jar -client yamlbench.jar 
5

real	0m1.795s
user	0m2.728s
sys	0m0.148s

без libyaml

time python -c "import yaml; yaml.load(open('data.yml'))" 

real	0m26.399s
user	0m25.890s
sys	0m0.440s
с libyaml
time python -c "import yaml; yaml.load(open('data.yml'))" 

real	0m26.272s
user	0m25.782s
sys	0m0.416s

чудеса просто, что там в этом пистоне такого, если неповоротливая жаба запускается и отрабатывает быстрее? а что там с биндингами к libyaml? Мутная какая-то история.

RedPossum ★★★★★
()

Тут пейтонщики предполагают, что libyaml по умолчанию просто не используется, если даже имеется.

И нужно выполнить что-то вроде:

time python -c "import yaml; from yaml import CLoader as Loader; yaml.load(open('data.yml'),Loader=Loader)"

У меня оно не видит CLoader, что, наверное, означает, что pyyaml собран без опции --with-libyaml. Как быстро впилить это на маке - не знаю, попробуй сам ;)

А проверить это можно посмотрев значение yaml.__with_libyaml__ сразу после импорта ямла

stevejobs ★★★★☆
()
Последнее исправление: stevejobs (всего исправлений: 1)
Ответ на: комментарий от RedPossum

Ну вот мы и разгадали тормознутость пйтона у Vit! На тред можно ставить галку «решено»!

//четыре секунды. Офигеть. Поспать и поесть можно. Чо они там такого понаписали...

stevejobs ★★★★☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.