LINUX.ORG.RU

Сообщения byko3y

 

Jira

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

Я имею в виду тот факт, что в нем не существует удобного вида в принципе, есть только неудобные и очень неудобные. Боже упаси вам в задачу вставить скриншот — вас все проклянут. Нужно только отдельным вложением, чтобы открывалось popup-ом, потому что абсолютно все прокрутки в Jira представляют собой катастрофу, особенно те, которые отображаются там, где на самом деле прокручивать нечего (привет горизонтальной прокрутке истории на 1700 пикселях ширины окна).

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

Я бы вспомнил еще претензию по поводу отсутствия возможности отменять изменения задачи, которые вносятся в онную одним кликом, но проблему можно решить отправив SMS на короткий номер приобрести расширение, которое добавляет отмену изменений: https://marketplace.atlassian.com/apps/1220176/action-undo-for-jira?hosting=s...

Я вот и не пойму, то ли это такой хитрый план по вытягиванию денег, как у докера, мол, «хотите работать нормально — покупайте наши расширения», то ли все-таки эти проблемы до конца не решаются, а сама Jira писалась как отчет о проведенной работе и не подразумевалась для применения конечным пользователем? Поясните, кто поопытнее.

 ,

byko3y ()

Многопоточный питон... снова

В продолжение: Многопоточный питон, PEP 554

По мере того, как я приближаюсь к релизу своей софтины для реализации многозадачности в питоне, у меня возникает вопрос: а на кой черт она вообще нужна? То есть, зачем нужна объектно ориентированная in-memory база данных с нулевым переключением контекстов. Какие задачи вообще можно решать с помощью большого числа процессов/потоков питона и общего хранилища?

Например, можно замутить многозадачную обработку событий в GUI, чтобы какой-нибудь очередной мессенжер на 8 ядрах мог не тормозить. Однако на текущий момент в подавляющем большинстве GUI фреймворков по сути отсутствует деление модель-вид, которое там скорее номинальное. При этом, под UWP есть питоновые биндинги, но будущее их мне не видится радужным.

Очевидная сфера применения - это веб сервера. Мы заменяем всякие там Redis, RabbitMQ, Celery на родные питоньи решения. То есть, например, энное число процессов получают запросы пользователей, скидывают их в родную питоновую очередь в виде родных питоновых объектов, а потом оттуда эм процессов питона достают объекты и обрабатывают их. Нынче для подобных задач у вас есть выбор межуд in-memory Redis с неродными объектами, либо какие-то более родные, но не in-memory решения:
https://github.com/nascheme/durus
https://pypi.org/project/dobbin/
http://www.zodb.org/en/latest/
http://www.garret.ru/dybase.html

Прикладной data mining и ML - это вообще дремучий лес для меня, к тому же, по моему первому впечатлению мне кажется, что проблему параллелизации непитоновыми методами там уже решили, вроде того же TensorFlow, где большая часть логики, в том числе многопотоков и вычислений на видеокартах, написано на C/C++.

 , ,

byko3y ()

Почему в индустрии победил стиль скобок Си на одной строке?

Как человек, который много писал на паскале, я довольно быстро пришел к форме:

if condition then
begin
  ...
end;
как наиболее универсальной записи, которая, к тому же, еще и каноничная. Если мы посмотрим на ядро линупса, то увидим довольно интересные вещи:
int crypto_register_acomps(struct acomp_alg *algs, int count)
{
	int i, ret;

	for (i = 0; i < count; i++) {
		ret = crypto_register_acomp(&algs[i]);
		if (ret)
			goto err;
	}
Эм-м-м, чо? Почему в одной функции скобка на новой строке и не на новой? Или, вот, например, стиль гугля для крестов:
int ClassName::ReallyLongFunctionName(int par_name1, int par_name2,
                                      int par_name3) {
  DoSomething();
  ...
}
Может я просто не знаком с крестами и не понимаю, как такая запись резонирует с привычками крестовиков, но на мой сишно-паскальный взгляд такая такой стиль вырвиглазен, поскольку в нем «DoSomething» непонятно к чему относится. Некоторые люди приходят к стилю:
int ClassName::ReallyLongFunctionName(int par_name1, int par_name2,
                                      int par_name3) {

  DoSomething();
  ...
}
который на самом деле так и просит перенести эту чертову скобку на новую строку, которую ты уже и так сделал.

Тот же Qt переносит скобку на новую строку для классов и функций, но не делает этого для условий-циклов.

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

 ,

byko3y ()

О чудесном сервере OpenResty

Наткнулся на статью:
https://habr.com/ru/post/321864/ - OpenResty: превращаем NGINX в полноценный сервер приложений

У меня сразу возникло два вопроса:

  • Мне одному кажется, что автора статьи - бородатый школьник, который сам не разбирается в теме статьи, и половину онной кидает гнилые понты про «я с пелёнок пишу хайлоад»?
  • В чем преимущество OpenResty над альтернативными решениями?

Для тех, кто не в курсе, кратко расскажу про OpenResty. Кому-то в Taobao стукнуло в голову, что будет очень хорошим решением взять nginx и засунуть в него LuaJIT. Именно «в него», а не «к нему». Так родился модуль Lua для nginx, на основе которого был сделан OpenResty и еще пару подобных проектов. Nginx однопоточен, LuaJIT однопоточен, вот они как бы в event-driven модели должны хорошо согласовываться. Питон/php/node.js тоже однопоточны, но пожирнее и помедленнее будут. С тех пор OpenResty распространился в основном по китаю, хоть и в остальной мир потихоньку проникает.
Мотивация создателей мне ясна: берем самый быстрый веб-сервер (пусть и неполноценный), берем самый быстрый скриптовый язык, которым на 2011 года действительно был именно Lua c его LuaJIT, скрещиваем их вместе, говорим волшебные слова - получаем замечательный полноценный веб-сервер. Правда, уже на момент 2017 года дистанция между V8 и LuaJIT неумолимо сокращалась, и сейчас они имеют похожую производительность выполнения кода.

Возникает еще один вопрос: а при чем тут nginx вообще? Смысл создания nginx заключался в том, чтобы сделать невидимую тонкую прослойку между системными вызовами ядра ОС, а посему функций у nginx может быть немного: статический контент, кэш, трансляция между двумя протоколами. На загрузках меньше 1000 запросов в секунду разница между nginx и каким-нибудь apache уже становится ничтожная. О чем думали создатели, засовывая в поток nginx скриптовый язык со сборкой мусора?

PS:

Если у вас, допустим, кодовая база на Perl, и вы не Booking, вы не найдёте перловых программистов. Потому что их нет, их всех забрали, а учить их долго и сложно

Палю годноту: Booking набирает кодеров без знания перла для работы с перлом. Так что если кто мечтает писать на перле - имейте в виду.

 , , ,

byko3y ()

Объектная модель питона

- Сколько нужно архитекторов, чтобы создать язык программирования?
- Сто. Один будет писать язык, а 99 - говорить, что могут сделать лучше.

Так скажем, я решил вспомнить обсуждение по теме треда: Generics в Python или помогите победить mypy

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

Прежде всего, я хотел бы вспомнить про RPython ( https://rpython.readthedocs.io/en/latest/rpython.html ).
Смысл особенностей языка прост - поддержка вывода типов. В частности, из языка убраны динамические определения классов и функций, динамическая типизация переменных, глобальные переменные стали константами, функции-генераторы транслируются в классы-итераторы и потеряли большую часть своих фич. У RPython есть большой минус - эти его ограничения сильно раздувают код, затрудняют писание и читание.
Итак, мои соображения:

1. Множественное наследование. Его нет даже на уровне C-функций в реализации питона и API расширений. «Но как же интерфейсы?» - возразите вы. Интерфейсы в C++ и Java нужны в роли объявления протоколов вызова методов объекта с целью последующей статической проверки этих протоколов при компиляции, а также для формирования таблиц методов, которые можно использовать независимо от объекта во время выполнения. Эти роли полностью потеряны в питоне, потому нет никакого оправдания их существованию. Мне нравится то, как сделаны интерфейсы в Go - это очень похоже на питоновые ABC: https://www.python.org/dev/peps/pep-3119

2. Генераторы - зло. Это прямо-таки запущенный случай GoTo, когда выполнение не просто бесконтрольно прыгает по коду - оно прыгает по стэкам. Особенно лютая дичь происходит, когда генераторы пересекаются с менеджерами контекста (привет PEP 567). В треде, скорее всего, опишу веселости реализации генераторов в PyPy/RPython. В питоне есть общая тенденция запутывать приложение в тесный клубок связанных изменяемых состояний, что не дает возможности параллелить и оптимизировать выполнение программы, а генераторы - вишенка на этом торте.

3. Изменение классов для существующих экземпляров объектов. Не, я понимаю, что класс в питоне объявляется во время выполнения. Но, блин, зачем в него совать изменяемые переменные? Зачем в старые объекты добавлять новые методы? Причем, попрошу обратить внимание на то, как нужно нагибаться раком для того, чтобы добавить аналогичные методы в сам объект, а не в класс - для этого нужны types.MethodType, function.__get__, functools.partial, и так далее. Методы в питоне вообще понадобились по простой причине - гвидо не придумал других способов сделать короткие имена функций (чтобы не было gtk_button_set_focus_on_click), поскольку не ясно, как выбирать из кучи похожих функций с коротким именем нужную под этот конкретный объект. Так в питоне появились len, iter, next, isinstance, slice, dict, dir, str, repr, hash, type - сейчас это обертки над соответствующими методами классов с подчеркиваниями в имени, а когда-то встроенные простые типы не являлись классами и работали только через эти функции. Так-то, я не вижу особой разницы между записью method(object) и object.method - особенно если method является статичной функцией, которой, в общем-то, все равно, какой первый аргумент (self) принимать.

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

 , ,

byko3y ()

Многопоточный питон, PEP 554

Как вы могли знать, уже два года идет вялотекущий перевод питона на поддержку независимых интерпретаторов в одном процессе.

https://github.com/ericsnowcurrently/multi-core-python
https://www.python.org/dev/peps/pep-0554/

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

Теперь главный вопрос: зачем? PEP 554 предлагает обращаться за помощью к каналам, как в Go, но:
- каналы как средство взаимодействия потоков убоги даже в Go;
- в питоне уже есть multiprocessing, который по сути и есть развитая идея каналов с возможностью прокинуть в обе стороны вызов функции и запрос атрибутов объекта, вплоть до итераторов, но не более того.

Для людей, которые уже готовы отвечать «ну дык есть же многопроцессы, есть форк на никсах - вот и используйте их», напомню, что реализация форка процесса на уровне ОС-и в действительности мало помогает многоПРОЦЕССовости питона - машем ручкой сборщику мусора, который передергивает счетчики ссылок:
https://instagram-engineering.com/dismissing-python-garbage-collection-at-ins...

>>> import os, sys, gc
>>> len(gc.get_objects())
6888
Это весьма эффективная модель сборки мусора... если у вас ровно один процесс.

Допустим, у нас уже есть несколько независимых потоков интерпретатора. Логичное желание - придумать какие-то эффективные модели взаимодействия интерпретаторов, которыми кто-то захочет пользоваться.
Примитивные ячейки данных (вроде многопоточного bytearray или других настраиваемых структур) довольно бесполезны, потому что мы же пользуемся питоном для того, чтобы взмыть вверх по абстракциям. Если же мы надумаем передать через подобнюу структуру хотя бы элементарную функцию, вроде

def hello():
    return "hello world"
то окажется, что объект строки и объект функции сидят в другом интерпретаторе, а сборщик мусора принципиально не умеет работать более чем в одном потоке, потому просачивание объекта из одного потока в другой вызывает катастрофические последствия.

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

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

В итоге, на текущий момент, многопоточная разработка сводится к настройке внешних по отношению к питону потоков, как то сделано в NumPy, а потому разработать отзывчивый GUI на одном питоне не получится, например.

Кто-то видит свет в конце тонеля? Или же это предсмертные видения?

 ,

byko3y ()

Ищу интерсную работу Asm, C, Python

Я осознаю, что Python+ML или Django сейчас дают хороший доход и есть много вакансий. Проработав много лет над скучным проектом Delphi+Firebird у меня нет больше желания работать просто ради денег, вплоть до того, что я бы занялся неким общественно ценным проектом забесплатно.
Опыт: GSoC на C и GTK; разработка ARM-контроллера электропривода на C; многопоточные приложения Win32 API (не только VCL) и SQL (firebird). Говорю/слушаю/пишу/читаю english, примерно A2-B1, хуже всего говорю, хорошо слушаю. Хорошо знаком с экспериментальной орг. химей. Малообщителен, но имею склонности к решению сложных проблем, в частности, отладка. Из более поверхностных знаний Django, JS, Haskell, SQLite, OpenGL, Maemo, разработка модулей ядра Linux, настройка Linux серверов (bind, apache, nginx, postgresql).
Местоположение - глубинка, потому скорее всего удаленное взаимодействие.

 , , ,

byko3y ()

Испортил жесткий диск магнитом

Понравилось, как неодимовый магнит магнитится ко всему. Жесткому диску это, по-видимому, ни разу не понравилось.

# ddrescue /dev/sdc2 /dev/null
rescued:   157181 MB,  errsize:       0 B,  current rate:   75169 kB/s
   ipos:   157181 MB,   errors:       0,    average rate:   93942 kB/s
   opos:   157181 MB,     time from last successful read:       0 s
Finished
# ddrescue /dev/sdc3 /dev/null
rescued:     2716 MB,  errsize:    325 kB,  current rate:     7948 B/s
   ipos:     2716 MB,   errors:       2,    average rate:   15346 kB/s
   opos:     2716 MB,     time from last successful read:       0 s
Interrupted by user
# ddrescue -i 3000M /dev/sdc3 /dev/null
rescued:    983552 B,  errsize:       0 B,  current rate:    51765 B/s
   ipos:        3 GB,   errors:       0,    average rate:    51765 B/s
   opos:        3 GB,     time from last successful read:       0 s
Interrupted by user
# ddrescue -b 1024 -i 4000M /dev/sdc3 /dev/null
rescued:    456704 B,  errsize:   68608 B,  current rate:     8617 B/s
   ipos:        4 GB,   errors:       1,    average rate:     8617 B/s
   opos:        4 GB,     time from last successful read:       0 s
Interrupted by user
#ddrescue -b 1024 -i 60000M /dev/sdc3 /dev/null
rescued:     1358 kB,  errsize:    215 kB,  current rate:    11355 B/s
   ipos:    60001 MB,   errors:       2,    average rate:    12132 B/s
   opos:    60001 MB,     time from last successful read:       0 s
Interrupted by user
Могу запостить смарт, но там всё довольно очевидно, разве что значение Spin Up Time странное, но я не знаю, как его интерпретировать:
ID# ATTRIBUTE_NAME          FLAG     VALUE WORST THRESH TYPE      UPDATED  WHEN_FAILED RAW_VALUE
  1 Raw_Read_Error_Rate     0x002f   200   200   051    Pre-fail  Always       -       411
  3 Spin_Up_Time            0x0027   154   151   021    Pre-fail  Always       -       1266
PS: я тут че подумал: может обратной стороной магнита поводить, а то я только одной стороной водил, он наверное намагнитился у шпинделя, и при приближении к центру диска отказывает.

byko3y ()

RSS подписка на новые темы