anetto1502

anetto1502

Канал про разработку на python и не только https://t.me/+0JMEYBjpMDJiYTMy
На Пикабу
Дата рождения: 29 августа
в топе авторов на 701 месте
12К рейтинг 103 подписчика 133 подписки 51 пост 24 в горячем
Награды:
За участие в Авторской неделе5 лет на Пикабу

Методика измерения времени работы программы. Как загрузка CPU/memory/IO влияет на производительность кода

В комментариях к видео Идеальный скрипт на баш 2 мне сказали, что в bash в конструкции if надо использовать "<" вместо "-lt", который применял я. Давайте разберёмся, как вообще измерять время работы программы и что на это влияет. Вас ждёт фарш из кучи команд: htop, iotop, lscpu, time, xargs, yes, seq, sync, timeout и хтонический ужас однострочников на bash. Материал в видео, кому удобнее — ниже его текстовая версия.

Кроме ютуба, для удобства есть дзен / VK / rutube.

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

Сравним скорость -lt и < внутри if мы в следующем видео. Начать придётся издалека, через тернии к звёздам.

Что вообще важно для любого эксперимента? Описать методику эксперимента. Для измерения скорости обратите внимание на следующие нюансы:

0. На каком оборудовании мы работаем

1. Измерять секунды и десятки секунд, а не наносекунды

2. Фиксировать условия по загрузка ядер и видеокарты, оперативной памяти, вводу/выводу

3. И сколько измерений проводить и как усреднять, средняя или медиана, что делать с выбросами и подобное

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

В начале про оборудование. Посмотрим на доступные ядра нашей системы с помощью команды lscpu. Видим 4 интелловых ядра i7-3770 с гипертредингом в 2 потока каждое, то есть 8 виртуальных ядер. Запомним - это наше оборудование

lscpu

...
CPU(s): 8

Потоков на ядро: 2

Ядер на сокет: 4

Имя модели: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz

...

Для длительных временных промежутков достаточно встроенной в bash команды time:

type time

time — это ключевое слово командного процессора

Справка нас обманывает, потому что показывает информацию о бинарнике /usr/bin/time

man time

А это не то, что нужно. Это справка по такой команде:

which time

/usr/bin/time

Вот пример её вывода:

/usr/bin/time sleep 1

0.00user 0.00system 0:01.00elapsed 0%CPU (0avgtext+0avgdata 2260maxresident)k

72inputs+0outputs (1major+95minor)pagefaults 0swaps

Мне такой вывод непривычен, поэтому вернёмся к встроенному time:

time sleep 1

real 0m1,002s — общее время работы программы

user 0m0,002s — время в пользовательском режиме

sys 0m0,000s — время в режиме ядра или системных вызовов

До эры искуственного интеллекта в виде ChatGPT был популярен stackoverflow, детали смотрите там. Важно обратить внимание, что real — это про общее время работы, а user и sys — время процессорное. Для них 10 будет означать, что программа работала 10 ядросекунд — при этом неважно, 10 секунд на 1 ядро или 1 секунда на 10 ядрах

Для примера попробуем посчитать уникальные строки в большом файлике на 130 мегабайт и 14 млн уникальных строк.

time sort -u rockyou.txt | wc -l

14341564

real 0m34,771s

user 1m7,906s

sys 0m0,931s

Вот тут наглядно видно, что real — это совсем не сумма user и sys. Кстати, вам интересно, как можно изящно ускорить подсчёт уникальных строк за счёт магии баша? Их есть у меня! Лайкните этот пост, и я сниму отдельный ролик про всякие хаки и оптимизации на этом поприще.

Про встроенную команду time мы можем найти в справке по самому bash

man bash

Ищем там с помощью ввода /time (слеш, потом time), дальше сильно промотав вниз с помощью кнопки n (сокращение от next, следующий поиск). Тут и описание вывода, и переменная окружения TIMEFORMAT, с помощью которой можно настроить вывод time.

Больше о переменных окружения в нашем бесплатном курсе на степике под названием Командная строка для разработчиков – cli-for-dev.

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

TIMEFORMAT="%R"; time sleep 1

Запомнили, это пригодится позднее. Дальше о фиксированных условиях.

С этим пунктом мы надолго. Теперь посмотрим на загрузку системы и как она влияет на время работы команды. Мне нравится команда htop за наглядность. Тут показывается загрузка каждого ядра в режиме реального времени и многое другое. Строку load average мы с вами разбирали в видео про атаку forkbomb в docker-контейнере. Посмотрите, если пропустили.

Методика измерения времени работы программы. Как загрузка CPU/memory/IO влияет на производительность кода Telegram (ссылка), Программирование, Командная оболочка bash, Обучение, Производительность, Методика, IT, YouTube, Разработка, Программа, Видео, Длиннопост

Пример работы htop

Загрузим вычислитель. Нам нужно взять "тяжёлую" для процессора команду и запустить её, загрузив все логические ядра системы. Согласно философии Unix, программа должна решать одну задачу и решать её хорошо. Команда xargs умеет параллелить. Она берёт входную строку и преобразует её в одну или несколько команд. Для наглядности покажу, как xargs работает в связке с echo:

echo 123 | xargs echo my arg is

Если аргументов несколько, по умолчанию они все пойдут указанной команде:

echo 1 2 3 | xargs echo my arg is

С помощью флага -n можно настроить, сколько аргументов пойдёт в одну команду. Если указать один, то наши три числа превратятся в три разные команды:

echo 1 2 3 | xargs -n1 echo my arg is

Если указать два, то первые два аргумента пойдут в первую команду, оставшийся третий аргумент пойдёт во вторую:

echo 1 2 3 | xargs -n2 echo my arg is

Вернёмся к одному аргументу на команду. И теперь магия - укажем, что надо запускаться параллельно на всех ядрах с помощью P0

echo 1 2 3 | xargs -P0 -n1 echo my arg is

Блеск. Дело за малым - нам надо загрузить всю систему. В моем случае, как мы выяснили в lscpu, надо 8 потоков. Воспользуемся командой seq, сокращение от sequence

seq 8

seq 8 | xargs -P0 -n1 echo hello process

Чудо. Мы умеем параллельно запускать 8 команд. Теперь надо сделать так, чтобы эти команды сурово грузили процессор. Можно использовать сторонние тулзы нагрузочного тестирования типа stress, но зачем?

Методика измерения времени работы программы. Как загрузка CPU/memory/IO влияет на производительность кода Telegram (ссылка), Программирование, Командная оболочка bash, Обучение, Производительность, Методика, IT, YouTube, Разработка, Программа, Видео, Длиннопост

Пойдём рабоче-крестьянским путём

Есть команда yes, которая умеет адски спамить. По умолчанию она спамит буквой y, то есть всегда говорит да, прямо как Джим Керри в комедии 2008 года:

yes

Может спамить любой строкой:

yes hello world

Прикол в том, что этот спам сильно грузить процессор, что нам и нужно. Направляем вывод команды yes в чёрную дыру dev null:

yes > /dev/null

После чего смотрим в htop на загрузку. И получаем отличную жужалку, которая нагружает ядро. Но только одно. Постойте, мы же умеем параллелить!

seq 8 | xargs -P0 -n1 yes > /dev/null

Всё хорошо, но эта команда работает, пока мы её не прервём. А нам бы добавить немного удобства. Пусть система загрузится на 10 секунд. Линукс и так умеет. Команда timeout прервёт запущенную команду, если она сама не завершиться за указанное время, в моём примере 1 секунду:

timeout 1 yes

И мы ещё time можем сюда навесить. Измерим время команды yes, которую прервёт по таймауту:

time timeout 1 yes

Я вас ещё не совсем замучил? Теперь объединим всё это безобразие. На 10 секунд загрузим 8 ядер системы собранной нами на коленке жужжалкой:

seq 8 | xargs -P0 -n1 timeout 10 yes > /dev/null

В рамках нашего примера есть два сходных варианта:

seq 8 | xargs -P0 -n1 timeout 10 yes > /dev/null # Грузим sys

seq 8 | xargs -P0 -n1 timeout 10 md5sum /dev/zero # Грузим user

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

a=$(seq 10)

echo $a

a=$(seq 100 000 000)

Но совершенно неудобно оценивать размер. Поэтому воспользуемся питоном. Незатейливо создадим большую строку, благо звёздочка удобно переопределена для строк. Один английский символ занимает один байт плюс накладные расходы на переменную, берём их "кило", то есть 1024 и получим килобайт.

python3.10

var = "a"*10

В IDLE можно не писать print, результат работы команды выводится на экран:

var

Кстати, в питоне накладные расходы на переменную довольно велики. В случае строки это 49 байт:

import sys

var = ""

sys.getsizeof(var) # 49

var = "a"

sys.getsizeof(var) # 50

var = "a" * 100

sys.getsizeof(var) # 149

Возведём 1024 в степень. Вторая степень даст мегабайт, третья - гигабайт. То есть такая переменная займёт в памяти около гигабайта, плюс 49 байт на служебную информацию.

var = "a"*1024**3

У нас свободно около 5 гигабайт, займём их все. Пока не удалим эту переменную или не завершим интерпретатор питона, память будет загружена.

var = "a"*5*1024**3

Для просмотра загруженности подсистемы ввода-вывода есть команда iotop, которой требуются права суперпользователя. Нам нужны только первые две строки

sudo iotop

Для загрузки ввода-вывода возьмём псевдогенератор случайных чисел и будем записывать его в файл:

cat /dev/urandom > /tmp/1

Зачастую проблема не в самом вводе-выводе, а в его буферизации. Так называется отложенная запись на диск. Операционная система для более эффективной работы с оборудованием пишет не сразу. Например, после записи файла на флешку на самом деле он там окажется не сразу, а через некоторое время. Для этого существует (или существовало? кто видел флешку в 2024 году?) безопасное извлечение флешки – как раз, чтобы операционка корректно дописала отложенный буфер.

В линуксе есть команда sync, которая завершиться, когда весь буфер запишется на диск.

sync

Пробовать измерять время будем на примере цикла в баше:

i=0; while [[ $i -lt 10 ]]; do i=$(( $i+1 )); echo $i ; done; echo $i

Увеличим число нулей:

i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )); done; echo $i

Добавим time. Если просто добавить time, то мы измерим время только присваивания:

time i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i

Чтобы измерить время всей конструкции, оформим цикл в виде отдельного процесса с помощью доллара и скобок:

time $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

Ещё ошибка: результат подпроцесса - число, а команда time пытается это число выполнить как команду. Добавим echo:

time echo $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

Теперь посмотрим, как на этот цикл влияет загрузку системы. Запустим монитор ресурсов htop и загрузим ядро:

seq 8 | xargs -P0 -n1 timeout 10 yes > /dev/null

Попробуем запустить наш цикл. Потом загрузим оперативную память:

python3.10

var = "a"*5*1024**3

И снова цикл. Осталось загрузить ввод-вывод:

sudo iotop

cat /dev/urandom > /tmp/1

И снова запустим цикл.

Одного измерения недостаточно. Собственно, примеры загрузки системы выше были призваны проиллюстрировать влияние внешних факторов на запуск вашего кода. Для минимизации этого влияния следует измерить несколько раз. Можно ручками внести результаты в таблицу. Но, во-первых, мы люди ленивые. А во-вторых, ручная обработка всегда чревата ошибками. Соберём всё в табличку.

А с этим есть проблема. Для вывода time в файл придётся немного извратиться. Дело в том, что перенаправление будет работать для команды выполняемой команды, то есть для всего справа от time. На помощь придёт логическое объединение в виде group command с помощью фигурных скобочек:

man bash

Ищем такую конструкцию /\{

Слеш для поиска, потом экранирование обратным слешом фигурной скобки. Как видно из справки, нужно добавить фигурные скобки и точку с запятой в конце, и только потом перенаправить. При этом time пишет в стандартный поток ошибок, то есть нужно перенаправлять второй дескриптор. Получается вот так:

TIMEFORMAT="%R"; { time $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; ) ; } 2>> res.csv;

tail -f res.csv # для проверки, что пишет

libreoffice res.csv # для обработки итоговой таблицы после завершения

Если запустить libreoffice с английским языком, то запятая будет считаться разделителем разрядов и удалится, мы получим неверное время (4567 вместо 4,567).

Закроем файл и откроем снова. Переключим язык на русский, чтобы запятая стала десятичным разделителем. Впишем формулы СРЗНАЧ и СТОТКЛ.

Если запускать скрипт 10 раз лень, можно накинуть ещё цикл (больше циклов богу циклов):

for i in $( seq 2 ); do TIMEFORMAT="%R"; { time $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; ) ; } 2>> res.csv; done

Резюмируем. Наша методика экспериментального исследования времени работы программы выглядит так:

берём 8-ядерный i7-3770

проводим 10 измерений командой time

запускаем много циклов "-lt" vs "<"

рассчитываем среднее арифметическое и среднеквадратичное отклонение

В следующем видео заодно интереса ради посмотрим на другие языки.

Теперь вы знаете, как можно загрузить процессор, оперативную память или подсистему ввода-вывода, как посмотреть на эту загрузку и как она может влиять на программу. Такие дела.

В телеграм-канале DevFM пишу о полезном для разработчика: инструментах, например, postgres_dba для анализа узких мест базы данных или fcron, интересных хаках вроде запуска LLM прямо в шрифте, или о Google design docs. А ещё у нас есть бесплатный курс cli-for-dev по Linux на степике, немного подкастов и видео.

Показать полностью 2

Кастомизация блюд в доставке — как жить с аллергией

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

Как же я радовался, когда всякие фаст-фудные ребята добавили кастомизацию блюд в приложениях! Можно убрать ингредиент без проблем. Начал, насколько я помню, эту моду Бургер Кинг, за что ему огромное спасибо. Он позволял убирать ингредиенты ещё 10 лет назад. Фишкой БК является возможность ещё и добавлять разные ингредиенты.

В Бургеркинге можно и удалять любой ингредиент, и добавлять новый за деньги (см. карусель)

Создатель БК, Джим МакЛамор, в своей книге "Burger King. Как построить империю" рассказывал, что возможность кастомизации блюда была одной из фишек БК. Правда, эта кастомизация создавала логистические трудности, поскольку почти переводила фаст-фуд в разряд индивидуальной подачи блюд, как в кафе. В книге есть интересные моменты, хотя она довольно "ни о чём". Например, забавный факт, что в США существенную прибыть БК приносила отдельная компания, которая занималась строительством новых ресторанов для франчайзи.

Но я о другом. Потом другие приложения подтянулись, Макдональдс (Вкусно и точка? ресторан Золотые Дуги?) тоже умеет убирать любые ингредиенты. Добавлять обычно не умеет:

Кастомизация блюд в доставке — как жить с аллергией Telegram (ссылка), Истории из жизни, Еда, Блогеры, Аллергия, Длиннопост

В маке можно убирать любой ингредиент

Может убирать некоторые ингредиенты и KFC (старый добрый Ростикс!).

Кастомизация блюд в доставке — как жить с аллергией Telegram (ссылка), Истории из жизни, Еда, Блогеры, Аллергия, Длиннопост

В KFC можно убирать часть ингредиентов. Раньше список был общим, и можно было убрать условный томат из блюда, где и не было томата... Сейчас починили, и список у каждого товара свой

Долгое время был переходный период — когда, например, ингредиент убрать можно, но не в акционном блюде. Постепенно это доработали и почти у всех почти всё можно настроить, хотя бы "не кладите Х" работает. В теории. На практике с этим тяжелее, периодически случаются ошибки, и, видимо, по привычке делают классическое блюдо. Или путают при формировании заказа. В случае аллергии такая ошибка может быть очень чревата.

У агрегаторов доставки тоже сделали возможность кастомизации. Видимо, это настраивает заведение, поэтому изменение состава есть не у всех. Вот Макдональдс в Деливери Клабе

Кастомизация блюд в доставке — как жить с аллергией Telegram (ссылка), Истории из жизни, Еда, Блогеры, Аллергия, Длиннопост

Мак в деливери. Цена биг хита уже 224р вместо 189. Плюс доставка, плюс сервисный сбор, плюс на пиво... Я очень не люблю, когда цена товара в агрегаторе отличается

В Купере аналогично

Кастомизация блюд в доставке — как жить с аллергией Telegram (ссылка), Истории из жизни, Еда, Блогеры, Аллергия, Длиннопост

Тот же биг хит из мака в купере. Уже 210р. Приятнее. Видимо, они вынуждены демпинговать для борьбы с монополистом

Для учёта пожеланий вне настроек кафе агрегаторы пошли разными путями: кто-то сделал поле комментария (Деливери), кто-то (Купер) даёт возможность обратиться через техподдержку.

Если настроить блюдо нельзя, в купере можно через техподдержку написать. Мой вопрос на второй фотке

И знаете, кто будет отвечать, если что-то пойдёт не так? Никто. Расскажу об этой чудесной истории в следующем посте.

Вообще я пишу о полезном для разработчика в телеграм-канале DevFM: обсуждали замену slack и TimescaleDB, как правильно покидать компанию, запуск LLM прямо в шрифте. А ещё у нас есть бесплатный курс cli-for-dev по Linux на степике, немного подкастов и видео.

Показать полностью 8

Мой взгляд на новые фичи python3.10-3.12

Стабильные минорные версии Python выходят ежегодно, последние 5 лет – в октябре. Мажорные версии, будем надеяться, выходить больше не будут, хватило ада переезда с python2 на python3. В этом октябре нас ожидает python3.13 (мажоная версия 3, минорная 13). Подумалось мне порефлексировать – какие новые фичи питона вошли в мой повседневный код. Пойдём со свежего и будем погружаться в пучины истории, в этой статье дойдём до 3.10. Запускаться будем в докере на python:3.12.5-slim. Код всех примеров лежит тут.

Пример 1: python3.12 – f-строки

В 3.12 меня зацепило обновление f-строк в PEP701. Вообще за много итераций f-строки превратились в мега-удобную штуку. Теперь внутри можно почти что угодно, в том числе вложенные вызовы f-строк с кавычками. Выведем в f-строке значение словаря по ключу:

Мой взгляд на новые фичи python3.10-3.12 Python, Telegram (ссылка), Программирование, Длиннопост

Пример 1. f-строки на стероидах

В выводе будет значение ключа:

# при запуске в python3.12

Settings: green

Для старых версий покажу, какая возникает ошибка. Полезно для "насмотренности", когда вы визуально будете отличать, это баг в коде или кто-то использует старый интерпретатор. Раньше так было нельзя, python3.11 и ранее выдаёт ошибку

# при запуске в python3.11 и ранее

print(f"Settings: {settings["color"]}")

^^^^^

SyntaxError: f-string: unmatched '['

Можно вставлять многострочные f-строки и внутри указывать любые валидные python-выражения. Красивое. Это как в 3.8 добавили мега-удобную мелочь: с помощью знака равно после переменной в f-строке мы получаем вывод в формате "название_переменной=значение". Типа

user='Gvido'

>>> print(f"{user=}")

# вывод

user='Gvido'

Пример 2: python3.11 – дополнение к исключениям

У исключений теперь есть метод add_note, с помощью которого можно дополнять порождённое исключение дополнительной информацией. Раньше нужно было либо отдельно логгировать нужное, либо колдовать над классом исключений. Укажем время возникновения исключения:

Мой взгляд на новые фичи python3.10-3.12 Python, Telegram (ссылка), Программирование, Длиннопост

Пример 2. Дополняем исключения информацией

В 3.11 дополнение (note) будет выведена после самого исключения. Выглядит так:

# при запуске в python3.11

File "/app/examples.py", line 17, in main

1/0

~^~

ZeroDivisionError: division by zero

Except at 2024-08-25 11:14:18.920230

До 3.11 метода add_note не существовало:

# при запуске в python3.10 и ранее

err.add_note(f"Except at {datetime.datetime.now()}")

AttributeError: 'ZeroDivisionError' object has no attribute 'add_note'

В 3.11 также ввели Exception Groups PEP654, но мне синтаксис не очень зашёл. Вы используете?

Пример 3: python3.10 – объединение контекстных менеджеров

Починили объединение контекстных менеджеров (parenthesized context managers). Как я понял, в теории так можно было изначально, на практике это был баг. Под одним with теперь можно собирать множество сущностей:

Мой взгляд на новые фичи python3.10-3.12 Python, Telegram (ссылка), Программирование, Длиннопост

Пример 3. Объединение внутри with

В 3.10 работает

# при запуске в python3.10

<_io.TextIOWrapper name='/tmp/1' mode='w+' encoding='UTF-8'> <_io.TextIOWrapper name='/tmp/2' mode='w+' encoding='UTF-8'>

А в 3.9 и раньше жалуется на рандомную часть выражения

# при запуске в python3.9 и ранее

with (open("/tmp/1", "w+") as file1,

^

SyntaxError: invalid syntax

Пример 4: python3.10 – pattern matching

Основным нововведением 3.10 считается введение Structural Pattern Matching. В питоне изначально не было switch/case, и вопрос решался либо цепочками elif, либо с помощью словаря. Пример такого словаря можете посмотреть в полном коде к этой статье внизу. Попытка внедрить switch/case была ещё в 2006 году, но тогда решили не вводить. В 2020 году Гвидо ван Россум презентовал новую реализацию, и ещё какую. В case запихнули сразу регулярки. Встречайте: PEP636. Ну, технически 634 вводит этот функционал, а в 636 предлагается туториал. Что теперь можно сделать? Представим, что мы парсим команду, состоящую из действия и объекта, вроде "нажать кнопка"

Мой взгляд на новые фичи python3.10-3.12 Python, Telegram (ссылка), Программирование, Длиннопост

При запуске в 3.10 после ввода двух слов получаем верный ответ

# при запуске в python3.10

Example 4. Python3.10, PEP636 https://peps.python.org/pep-0636/

Write action and object (example 'push button'): push button

You did 'push' on 'button'

На более старых версиях match не известно

# при запуске в python3.9 и ранее

match command.split():

^

SyntaxError: invalid syntax

В case можно фиксировать какие-то блоки, использовать логическое "или" и переменные

# обработчик для направления или варианта go направление

case ["north"] | ["go", "north"]:

# обработчик для разных вариантов получения объекта get, pick up, pick ... up, при этом сам объект попадёт в переменную obj

case ["get", obj] | ["pick", "up", obj] | ["pick", obj, "up"]:

И в этом match/case ещё много разных вариантов и нюансов. Это и хорошо (потому что мощь), и плохо (потому что разбирать чужой код может быть больно). Про детали у нас в канале был отличный пост.

Какие фичи показались важными вам? Я намеренно опустил всё про типы, это заслуживает отдельной статьи.

Весь проект "на потыкать" лежит тут.

В телеграм-канале DevFM пишу о полезном для разработчика: инструментах вроде parabol или fcron, интересных хаках вроде запуска LLM прямо в шрифте, оптимизаторе join в PostgreSQL. А ещё у нас есть бесплатный курс cli-for-dev по Linux на степике, немного подкастов и видео.

Показать полностью 3

Telegram stars

Два дня назад, 14.08.2024 Дуров включил несколько интересных механик для авторов каналов. Речь про звёздочки – Star reaction. Их можно использовать для платной подписки, показа медиа после доната или для платных реакций в качестве "спасибо" автору. Последняя фича в канале выглядит так:

Telegram stars Telegram (ссылка), Telegram, Telegram Stars, Telegram каналы, Видео, Без звука, Вертикальное видео, Длиннопост

Пример в канале DevFM. Если звёзд не видно, нужно обновиться

Эти реакции анимированные (две минуты забавно, дальше могут подбешивать) и всегда стоят первыми, независимо от количества. В админке канала у владельца появляется доп вкладка со звёздами:

Telegram stars Telegram (ссылка), Telegram, Telegram Stars, Telegram каналы, Видео, Без звука, Вертикальное видео, Длиннопост

В статистике есть статистика (ура, рекурсия), старые бусты и новые звёзды

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

Отменить звёзды можно в течение 5 секунд. Если вы донатить первый, интерфейс другой:

Telegram stars Telegram (ссылка), Telegram, Telegram Stars, Telegram каналы, Видео, Без звука, Вертикальное видео, Длиннопост

Указываете количество, галочку анонимности и вперёд

Вот с галочкой анонимности неочевидно. Оказывается, если зажать реакцию звезды, вы попадёте в доп меню:

Telegram stars Telegram (ссылка), Telegram, Telegram Stars, Telegram каналы, Видео, Без звука, Вертикальное видео, Длиннопост

Лидерборд донатеров, где вы можете управлять анонимностью

Если звёзд у вас нет, то при нажатии на звезду вам предложат их купить

Для андроида цена ниже iOS (см. второе фото), 189 за 100 звёзд против 225 для iOS. Видимо, налог App Store, хотя процент у меня не бьётся

Что же, ТГ предложил интересный заход на монетизацию контента. Чувствую вайб древних голосов ВКонтакте. В рубрике 18+ донат за отдельные фото точно найдет своё место. У остальных – увидим.

В телеграм-канале DevFM пишу о полезном для разработчика: инструментах вроде parabol или fcron, интересных хаках вроде запуска LLM прямо в шрифте, оптимизаторе join в PostgreSQL. А ещё у нас есть бесплатный курс cli-for-dev по Linux на степике, немного подкастов и видео.

Показать полностью 6 1

Ответ на пост «Протеин в насекомых»5

Ответ на пост «Протеин в насекомых» Насекомые, Протеины, Здоровое питание, Скриншот, Ответ на пост, Упоротые расчеты, Комментарии на Пикабу, Волна постов

Здоровое питание #comment_318261228

Показать полностью 1

Ответ Аноним в «Пучков про переход на Rutube »12

Хотите ещё пример бездарности рутуба? У меня есть такое относительно неплохо залетевшее видео на ютубе, называется идеальный скрипт на bash https://youtu.be/FuOgKi8XPkw?si=9FsRBw_TX75NhQ-J

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

Ответ Аноним в «Пучков про переход на Rutube » YouTube, RUTUBE, Telegram (ссылка), Ответ на пост, Текст, Волна постов, Блокировка YouTube, Мат, YouTube (ссылка)

И факс, блеать

Показать полностью 1

Идеальный скрипт на bash 2 | Bash ideal script 2

Сегодня продолжим изучать наш идеальный скрипт из предыдущего видео (видео прошлой части). Разберёмся с непонятными конструкциями в bash [] и [[]] и обсудим, когда можно не ставить кавычки вокруг переменных. Ниже видео с разбором, а кому удобнее текстовый вариант — добро пожаловать ниже.

Давайте разбираться. Двойные квадратные скобки в современном bash - это ключевое слово, такое же, как for. Проверить это можно с помощью команды type. Одинарные квадратные скобки - это встроенная команда, такая же, как test. Что из этого следует? Да фиг знает, по факту. Просто интересно. А вот внутри одинарных и двойных квадратных скобок можно использовать разные конструкции.

Для сравнения [[ и [ нашёл для вас очень наглядную таблицу

Идеальный скрипт на bash 2 | Bash ideal script 2 Telegram, Программирование, Разработка, IT, Обучение, Командная оболочка bash, YouTube, Видео, Длиннопост

Источник: https://mywiki.wooledge.org/BashFAQ/031

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

Но про переносимость куда мы говорим? Действительно, двойные квадратные скобки появились не сразу. В разделе 7.1 книги Advanced Bash-Scripting Guide (версия на русском) написано, что конструкция появилась в bash версии 2.02. Кстати, это очень большая и вкусная книжка по bash, рекомендую её, если вы зачем-то решили стать в баше экспертом. Там под тысячу страниц, материал не для слабых духом. Есть и на русском, и на английском.

Так когда появились двойные скобки? Проверим changelog баша, там можно найти первое упоминание конструкции [[]] в версии 2.02. А потом можно найти релиз, и это 1998 год. 1998, Карл. Надеюсь, все обновились с тех пор.

В man bash можно найти описание [[]], лучше посмотрите в видео этот фрагмент.

Соберём на коленке пример демонстрации важности двойных кавычек.

a="hello world"

if [[ $a == "hello world" ]]

then

echo "success"

fi

# в видео показан однострочник ниже

if [[ $a == "hello world" ]]; then echo "success"; fi

И всё хорошо, внутри [[]] действительно можно не применять кавычки, bash всё сделает корректно. Но потом модифицируем пример

# так неправильно!

if [[ $a == "hello world" ]]; then echo "success"; touch $a; fi

И вот этот код уже ломается. Вместо создания одного файла "hello world" создаются два отдельных файла. Потому что в touch надо кавычками защищать переменную

# так нормально, но тяжело объяснить, где нужны кавычки

if [[ $a == "hello world" ]]; then echo "success"; touch "$a"; fi

А теперь объясните джуну, где надо ставить кавычки, а где не надо. Самое простое правило - кавычки должны быть везде. Великий и ужасный Гудвин, ой, то есть баш, очень неустойчив к разного рода ошибкам. По опыту жить проще с ядрёным стайл-гайдом, по которому чисто визуально можно выявить ошибку. Есть переменная? Должны быть кавычки.

# так безопаснее всего

if [[ "$a" == "hello world" ]]; then echo "success"; touch "$a"; fi

Давайте попробуем сконструировать выражение для оценки времени выполнения. Как корретно измерять время выполнения я планирую снять отдельное видео. Пока не будем вдаваться в детали и попробуем собрать нужную конструкцию

Утилита time выдаёт временные характеристики работы программы. Сейчас нас интересует блок real, где указано общее время работы программы согласно системному таймеру, то есть время от запуска команды до её завершения

time echo $( i=0; while [[ $i -lt 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

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

Вернёмся к замене -lt на треугольный знак меньше. Попробуем

# ОШИБОЧНОЕ 2 итерации вместо 1кк

time echo $( i=0; while [[ $i < 1000000 ]]; do i=$(( $i+1 )) ; done; echo $i )

Вау! Отработало мгновенно. Но неправильно. Обратите внимание на вывод - прошло только 2 итерации. Потому что два больше миллиона, если смотреть на них как на строки. Строковое сравнение идёт посимвольно, и два больше 1 - истина, дальше смотреть не требуется.

По факту, нужно использовать арифметическое выполнение

time echo $( i=0; while (( $i < 1000000 )); do i=$(( $i+1 )) ; done; echo $i )

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

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

Заходите в наш канал DevFm в телеграмм, где выходят годные материалы для middle плюс python разработчика. Если хотите разобраться с азами Linux, то добро пожаловать в наш бесплатный курс cli-for-dev на степике. Буду рад, если вы поддержите нас позитивными оценками и обратной связью по курсу.

Показать полностью 1

Ответ Аноним в «Press F to respect или "еще один автор фсе"»3

Ответ Аноним в «Press F to respect или "еще один автор фсе"» Скриншот, Ответ на пост, Комментарии на Пикабу, Длиннопост, Мат

Миролюбивые

Показать полностью 1
Отличная работа, все прочитано!