LINUX.ORG.RU
ФорумTalks

Код-инжекшены в убогом питон

 , ,


1

4

да выбрасывает ексепшен, но выброс ексепшена == борьба со следствиями, а именно с кодинжекшеном.

>>> class Foo():
...     def __init__(self, **kw):
...             print(kw)
... 
>>> d = {'self': 'abc', 'a': 1, 'b': 2}
>>> 
>>> Foo(**d)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: __init__() got multiple values for argument 'self'

Ща адепты мне расскажут что так делать нельзя.

Типа в шаблон jinja нельзя передавать self. Придумайте новое имя. Ага.

Для специалистов: если атаковать не первый параметр (self), а скажем опциональный, то будет весело:

>>> class Foo():
...     def __init__(self, a=None, **kw):
...             print('a=', a, kw)
... 
>>> d = {'self1': 'abc', 'a': 1, 'b': 2}
>>> 
>>> Foo(**d)
a= 1 {'self1': 'abc', 'b': 2}
<__main__.Foo object at 0x7f9a14ec5a58>
>>>
★★

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

Вот, зацени ещё.

Везде аналогичный код:

int fib(int n) {
	if (n < 2)
		return n;
	return fib(n - 1) + fib(n - 2);
}

Резльтаты проходок (0..X):

./all.sh 20
20 numbers: 10.779514 -> Bash
20 numbers: 0.000137 -> C (gcc)
20 numbers: 0.000101 -> C (tcc)
20 numbers: 0.000104 -> C (clang)
20 numbers: 0.000099 -> Go
20 numbers: 0.002158 -> Lua
20 numbers: 0.000396 -> Lua (luajit)
20 numbers: 0.00070905685424805 -> PHP
20 numbers: 0.002639 -> Python
20 numbers: 0.002428 -> Python3
20 numbers: 0.022080 -> PyPy
20 numbers: 0.009889 -> PyPy3
20 numbers: 0.000337 -> Cython
20 numbers: 0.000136086 -> Rust

./all.sh 38
38 numbers: skip -> Bash
38 numbers: 0.363439 -> C (gcc)
38 numbers: 0.546616 -> C (tcc)
38 numbers: 0.367560 -> C (clang)
38 numbers: 0.355349 -> Go
38 numbers: 7.999564 -> Lua
38 numbers: 0.444055 -> Lua (luajit)
38 numbers: 3.9458131790161 -> PHP
38 numbers: 13.326358 -> Python
38 numbers: 13.925325 -> Python3
38 numbers: 1.909800 -> PyPy
38 numbers: 1.820360 -> PyPy3
38 numbers: 1.886172 -> Cython
38 numbers: 0.534892106 -> Rust

./all.sh 42
42 numbers: skip -> Bash
42 numbers: 2.432211 -> C (gcc)
42 numbers: 3.779980 -> C (tcc)
42 numbers: 2.514717 -> C (clang)
42 numbers: 2.432347 -> Go
42 numbers: skip -> Lua
42 numbers: 2.973973 -> Lua (luajit)
42 numbers: skip -> PHP
42 numbers: skip -> Python
42 numbers: skip -> Python3
42 numbers: 11.460796 -> PyPy
42 numbers: 12.154052 -> PyPy3
42 numbers: 12.955405 -> Cython
42 numbers: 3.647002798 -> Rust
``
WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Хоть фибоначчи и тупой тепличный тест но я не ожидал, что у ржавого (который 0 оверхеда) и питона будет настолько всё плохо в сравнении с luajit, который нахер никому не нужен, а не pypy/cython сольёт даже php.

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

Спеца по фортрану бы ещё, а то я не осилил.

42 numbers: skip -> Bash
42 numbers: 2.435858 -> C (gcc)
42 numbers: 3.811757 -> C (tcc)
42 numbers: 2.524214 -> C (clang)
42 numbers: 2.522520 -> Go
42 numbers: 1.487000 -> Java !new
42 numbers: 4.186 -> JavaScript !new
42 numbers: skip -> Lua
42 numbers: 2.988807 -> Lua (luajit)
42 numbers: skip -> PHP
42 numbers: skip -> Python
42 numbers: skip -> Python3
42 numbers: 11.776281 -> PyPy
42 numbers: 12.003423 -> PyPy3
42 numbers: 13.134839 -> Cython
42 numbers: 3.764154956 -> Rust
WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

С -O3 для gcc, clang и cython (gcc):

42 numbers: skip -> Bash
42 numbers: 1.240676 -> C (gcc)
42 numbers: 3.732717 -> C (tcc)
42 numbers: 2.006991 -> C (clang)
42 numbers: 2.444796 -> Go
42 numbers: 1.484000 -> Java
42 numbers: 4.148 -> JavaScript
42 numbers: skip -> Lua
42 numbers: 2.976883 -> Lua (luajit)
42 numbers: skip -> PHP
42 numbers: skip -> Python
42 numbers: skip -> Python3
42 numbers: 11.500000 -> PyPy
42 numbers: 12.767176 -> PyPy3
42 numbers: 7.652135 -> Cython
42 numbers: 3.670548861 -> Rust
WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Ой вей. PyPy тормознее JS в *3 раза*, а тот не намного хуже ржавого и всего-то раза в 1.5 тормознее си. А от чего ява такая бодрая - не понятно. Я думал жс будет где-то между пхп питоном.

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

Так лучше, но ява уж сильно бодрая. Хотя это - простой тест. Если там будет какой-нибудь перебор по HashMap или дереву с сортировкой, обработкой объектов и сериализацией, то всё будет намного хуже у ДТ.

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

Я сам года два назад был в шоке. Мне коллега сказал, что JS быстрый, я ему ответил, что он сдурел. Погулили бенчмарки и оказалось, что с тех пор когда я последний раз смотрел на скорость V8, он ускорился на порядок, и, похоже, продолжает.

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

ява уж сильно бодрая

JIT ведь решает. Я с другом ещё в 2012 спорил про потенциал оптимизации в рантайме, скинул ему пруф наконец-то.

Как оказалось, у раста тоже можно указать уровни оптимизации -C opt-level=3:

42 numbers: 1.233279 -> C (gcc)
42 numbers: 2.012830 -> C (clang)
42 numbers: 2.437177 -> Go
42 numbers: 1.477000 -> Java
42 numbers: 4.35 -> JavaScript
42 numbers: 2.970207 -> Lua (luajit)
42 numbers: 7.603512 -> Cython
42 numbers: 1.883623534 -> Rust
WitcherGeralt ★★
()
Ответ на: комментарий от WitcherGeralt

Как оказалось, у раста тоже можно указать уровни оптимизации

Ну так - не плохо. А gcc тоже с -03?
Js и всю остальную скриптуху надо тоже тогда пересобирать с -03. А посыпаться может и jit, если он что-то там мутит с особыми инструкциями.

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

Аж захотелось посмотреть, чем там cython занимается.
Может, какая бабуйня, когда рекурсивная функция инициализируется на каждый вызов..

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

Вот из этого получается 3700 строк на C (в которые я даже не пытался смотреть):

import time
import sys


cdef fib(int n):
	if n < 2:
		return n
	return fib(n - 1) + fib(n - 2)


def run(iters):
	t = time.clock()
	i = 0

	while i < iters:
		print(fib(i))

		i += 1

	print("%i numbers: %f" % (i, time.clock() - t))


if __name__ == "__main__":
	run(int(sys.argv[1]))
WitcherGeralt ★★
()
Ответ на: комментарий от rsync

В любом языке есть зарезервированные слова, которые нельзя использовать как идентификатор. Просто считай, что в языке шаблонов - self зарезервированное слово. И не бомби.

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

Я не настоящий погромист, но вы C функцию из питона дёргаете в цикле. Сдаётся мне, тут коетекст гоняется между скриптотой и сями.

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

Пистон с модулями соснул даже у пыха?

А что вас удивляет? Пока пистонщики переписывали принты пхпшники оптимизировали интерпретатор.

bread
()
Ответ на: комментарий от crutch_master

PyPy тормознее JS в *3 раза*, а тот не намного хуже ржавого

Срывы покровов! В реальном коде все может быть еще забавней, там и cpp вполне может соснуть у «тормозного жабаскрипта», все зависит от радиуса кривизны рук.

bread
()
Ответ на: комментарий от Shadow

тут коетекст гоняется между скриптотой и сями

В данном случае всё превращается в сишный код, обложенный тоннами ненужных ему абстракций. А когда действительно дёргается сишный код из питона, проталкивание данных через ворох абстракций с приведением типов обойдётся всё равно сильно дешевле, чем кутить непосредственно питонячий код. На сишных модулях же и строится питон, без них он бы вообще еле шевелился.

WitcherGeralt ★★
()

got multiple values for argument 'self'

Неплохая иллюстрация тезиса о том, что питонисты запутались и утонули в своих 100500 фичах костылях.

no-such-file ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Я сам года два назад был в шоке

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

no-such-file ★★★★★
()
Ответ на: комментарий от crutch_master

Хоть фибоначчи и тупой тепличный тест но я не ожидал, что у ржавого (который 0 оверхеда) и питона будет настолько всё плохо в сравнении с luajit, который нахер никому не нужен, а не pypy/cython сольёт даже php.

Этот тест написан не с 0 оверхеда, а старый добрый императивный подход. Разница между С и Rust скрыта в LLVM, генерируется разный машкод.

$ time ./fib-gcc 42
42: 267914296

real	0m1,275s
user	0m1,274s
sys	0m0,000s

$ time ./fib-clang 42
42: 267914296

real	0m2,176s
user	0m2,176s
sys	0m0,000s

$ time ./fib-rs 42
42: 267914296

real	0m2,169s
user	0m2,169s
sys	0m0,000s

Вот пример 0 оверхеда.

$ time ./fib-loop 42
42: 267914296

real	0m0,001s
user	0m0,001s
sys	0m0,000s

$ time ./fib-fold-rs 42
42: 267914296

real	0m0,001s
user	0m0,001s
sys	0m0,000s

int fib(int n) {
    int x = 0, y = 1;

    while (n--) {
        int t = y;
        y = x + y;
        x = t;
    }

    return x;
}
fn fib(n: i32) -> i32 {
    (0..n).fold((0, 1), |(x, y), _| (y, x + y)).0
}
numas13
()
Ответ на: комментарий от bread

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

«читерства» упс...

$ gcc -O2 c/fib.c -o fib-gcc-nocheat -fno-optimize-sibling-calls 
$ time ./fib-gcc-nocheat 42
42: 267914296

real	0m2,305s
user	0m2,305s
sys	0m0,000s

$ rustc -C opt-level=2 -o fib-rs-o2 rs/fib.rs
$ time ./fib-rs-o2 42
42: 267914296

real	0m2,246s
user	0m2,246s
sys	0m0,000s
numas13
()
Ответ на: комментарий от numas13

Этот тест написан не с 0 оверхеда

Рядовой [быдло]код пишут тоже без 0 оверхеда, а намного больше.

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

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

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

просто все застряли на джанге/фласке.

4.2 очень много где торнадо/aiohttp например

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

Твой код

cat test.py
def fib(n):
    if n < 2:
        return n
    return fib(n-2) + fib(n-1)
print(fib(38))
> time python test.py
39088169
       15.50 real
> time pypy test.py
39088169
        0.65 real         0.50 user         0.07 sys
vs тот же код, но написанный нормально
cat test2.py
def fib(n: int) -> int:
    a, b = 0, 1
    for i in range(0, n):
        a, b = b, a + b
    return a

print(fib(38))

> time python test2.py
39088169
        0.07 real         0.02 user         0.01 sys
> scripts/mypyc test2.py
running build_ext
building 'test2' extension
> time python -c 'import test2'
39088169
        0.03 real         0.01 user         0.00 sys

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

В некоторых компиляторах есть оптимизация хвостовой рекурсии, в некоторых - нет. Это надо учитывать при написании кода.

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

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

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

Мимо кассы. Измеряем не то, кто лучше напишет функцию получения Фибоначчи, а то, где как работает одинаковый по сути код. Ну да, я тоже считаю, что лучше какой-нибудь парсер-обработка-вывод с замером обработки, где будут linkedlist, hashmap, array. Но это надо сидеть, писать тесты...

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

В некоторых компиляторах есть оптимизация хвостовой рекурсии, в некоторых - нет. Это надо учитывать при написании кода.

Ну да, надо бы отключать эту оптимизацию если возможно. Или тестировать везде итеративный алгоритм, но такой тест вовсе ни о чем.

bread
()
Ответ на: комментарий от pawnhearts

Прости, но ты — идиот?

Глазоньки открой и посмотри в код сначала, где ты увидишь импорты сишных функций. Потом посмотри в мой пост, где я целенаправленно сравниваю работу с ними и без.

Ну, а во-вторых, не совсем ясно было какой разницы можно ожидать. Я ожидал, что PyPy с чистым питоническим модулем окажется на порядок быстрее CPython, порядка не вышло.

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

Ты, всё же, — идиот, fib наиболее оптимально всё равно считается не так.

Как тут можно было не понять, что выбран cpu-bound код, дающий максимальную нагрузку на ровном месте, для теста производительности языка, а не его выразительных способностей или чего либо ещё? Этот код ложится на синтаксис всех вышеперечисленных языков без каких либо изменений.

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

выбран cpu-bound код, дающий максимальную нагрузку на ровном месте

Как минимум, в gcc и lua есть CTO. Так что этот код ни разу не равнозначный.

синтаксис

Но семантика разная.

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

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

На нормальные бенчмарки от спецов в этом деле я уже выше сослался.

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

CTO

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

Выше уже сказали, что задачи не всегда решаются оптимально. Способность языка показывать нормальную производительность при решении задач «в лоб» — важный фактор.

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

Использовать рекурсию там где не надо, это не «в лоб» это мегатупо. И дело даже не в производительности и диком потреблении памяти, а в том что она просто упадет с max recursion depth.

Вообще я конкретно фибоначи видел на собеседованиях, если человек пишет её рекурсивно, его заворачивали. Еще там был пример задачи, где хорошо ложилось slots, ожидалось что человек их заюзает.

В projecteuler много такого, на более поздних задачах, если решать их «в лоб» они просто не выполнятся за разумное время, неважно какой ты язык используешь.

Это проблема самого языка

т.е. ты знал про это и решил набросить, решив максимально бессмыссленную задачу максимально неэффективным способом. Но зачем так заморачиваться мог бы просто написать «питон говно, там нет TCO».

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

еще там был пример задачи, где хорошо ложилось slots, ожидалось что человек их заюзает

Лол, если уж давать это на собеседовании, то только проверить знает ли кандидат формулу Бине. Перебор может и новоиспечённый говнокодер сделать, который про рекурсию даже и не слышал. В питоне переполнение произойдёт довольно поздно, так что как минимум первую тысячу получится оптимизировать.

т.е. ты знал про это

Разумеется знал, я на этом языке пишу очень давно.

решил набросить

Такой задачи не было. Посмотри на начало ветки, я надеялся, что PyPy здесь окажется быстрее пыха. Мне было сравнить разные варианты с питоном (попробовал даже нуитку, хотя и забыл вставит в общий тест) и посмотреть где будет Go.

бессмыссленную задачу максимально неэффективным способом

Наоборот. Это самый эффективный способ зажарить проц на ровном месте, который первым пришел мне в голову. И, ещё раз, языки/компиляторы/интерпретаторы были с равных условиях, логика там одна, а оптимизировать или нет — это решение их разрабов и проблемы конечного пользователя, а не конкретного теста.

WitcherGeralt ★★
()
Ответ на: комментарий от pawnhearts
def binet(n):        
     sqrt5 = sqrt(5)
     phi = (sqrt5 + 1) / 2
     return (phi**n - (-phi)**(-n)) / sqrt5
     # return phi**n / sqrt5 # low
%timeit pawnhearts(1000)
10000 loops, best of 3: 46.5 µs per loop

%timeit binet(1000)
1000000 loops, best of 3: 330 ns per loop

%timeit binet_low(1000)
1000000 loops, best of 3: 203 ns per loop
WitcherGeralt ★★
()
Последнее исправление: WitcherGeralt (всего исправлений: 1)
Ответ на: комментарий от WitcherGeralt

Это уже другой алгоритм. Семантика хвостовой рекурсии разная в языках с TCO и без. В язык с TCO оно фактически превращается в цикл.

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

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

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

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

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

Для gcc можно собирать gcc -march=native -O3 .... Гулять так гулять. Раз мы тестим cython+gcc, то для go можно проверить gccgo -march=native -O3 ....

Конечно же, перед запуском теста надо отключить все экономии энергии, перевести cpufreq в режим performance, или что там ещё может быть включено. При выключенных экономиях разброс между соседними запусками вычислительных тестов должен быть до 1-2%. Если разброс 5-10% и выше, то в системе что-то не так.

PS: а ещё t184256 хочет numba.

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