BufWriter<Master<'_>> – Telegram
BufWriter<Master<'_>>
105 subscribers
451 photos
28 videos
34 files
1.7K links
https://www.patreon.com/alxe_master

Видео/статьи. Конспект и мои вольные комментарии по инженерии. тут только то, что считаю полезным для себя или других =)

#os, #cloud, #rust, #golang, #python, #javaScript, #cpp, etc
Download Telegram
Суперкомпилятор
принимает исходный код алгоритма плюс некоторые данные о входных параметрах и возвращает новый исходный код, который исполняет свою задачу на этих данных быстрее или является лучше исходного алгоритма по каким-то другим показателям

https://ru.wikipedia.org/wiki/%D0%A1%D1%83%D0%BF%D0%B5%D1%80%D0%BA%D0%BE%D0%BC%D0%BF%D0%B8%D0%BB%D1%8F%D1%86%D0%B8%D1%8F
Forwarded from Блог*
#prog #rust #моё

В Rust в некоторых случаях можно использовать анонимный лайфтайм ('_). Практика показывает, что эта фича некоторым не до конца понятна, поэтому я решил написать об этом подробнее.

Времена жизни — пожалуй, именно та фича, которая больше всего делает Rust непохожим на мейнстримные языки программирования. В частности, их синтаксис ('identifier) — это то, что приходит первым на ум тому, кто уверяет, что у Rust нечитаемый синтаксис. Тем не менее, если взглянуть на код программы на Rust, то этих времён жизни можно увидеть очень мало. Казалось бы, как так может быть, если учесть, что каждая ссылка параметризована временем жизни, а ссылки в Rust используются достаточно активно? Дело в том, что бо́льшая часть вариантов использования времён жизни подпадает под один из достаточно простых паттернов, для которых компилятор в состоянии вывести отсутствующие времена жизни сам. Это называется lifetime elision, и правила, по которым оно происходит, перечислены в растономиконе.

Раскрытие сокращённой записи начинается с введения нового явного параметра для каждого аргумента, тип которого параметризован временем жизни (далее ВЖ), но для которого конкретное значение ВЖ не указано. Например, если у нас функция

fn do_something(a: &mut u32, b: (&u32, &u32), c: Cow<str>) { ... }

, то после первого шага преобразования она выглядит так:

fn do_something<'lt1, 'lt2, 'lt3, 'lt4>(a: &'lt1 mut u32, b: (&'lt2 u32, &'lt3 u32), c: Cow<'lt4, str>) { ... }

Обратите внимание, это работает не только с ссылками.

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

fn first_and_second(arg: &(u32, u32, u32))- > (&u32, &u32) {
(&arg.0, &arg.1)
}

, то её развёрнутый тип будет

fn first_and_second<'a>(arg: &'a (u32, u32, u32))- > (&'a u32, &'a u32) {
(&arg.0, &arg.1)
}

Что же делать, если аргументов несколько? В случае, когда функция принимает &self или &mut self, ВЖ возвращаемого типа приравнивается ВЖ self. Из этого, кстати, следует несколько неожиданный результат, что нижеприведённый код не компилируется:

struct Foo;

impl Foo {
fn use_str(&self, s: &str) -> &str {
s
}
}

Если расписать тип полностью, то станет понятно, почему:

struct Foo;

impl Foo {
fn use_str<'foo, 's>(&'foo self, s: &'s str) -> &'foo str {
s
}
}

Действительно, lifetime elision приводит к тому, что возвращаемая строка имеет то же ВЖ, что и self, но в теле функции используется строка с другим ВЖ 's, которое никак не связано с 'foo. Для того, чтобы решить эту проблему, нужно явно ввести обобщённый параметр времени жизни и указать, что он один и тот же у аргумента и возвращаемого значения:

struct Foo;

impl Foo {
fn use_str<'s>(&self, s: &'s str) -> &'s str {
s
}
}

Такой код уже компилируется.
Forwarded from Блог*
Собственно, это все правила, которым подчиняется lifetime elision. Если описанные выше случаи не применимы, то компилятор скажет "я не могу, у меня лапки". Отчасти именно из-за этого начинающим настолько затруднительно усваивать концепцию времён жизни: в простых случаях их писать не надо, поэтому ситуации, в которых ВЖ действительно нужно писать, уже не очень тривиальны. Какое это имеет отношение к анонимным временам жизни? Само непосредственное: '_ можно указать вместо обобщённого параметра ВЖ, чтобы компилятор его вывел. Скажем, сигнатуру first_and_second можно написать и так: fn first_and_second(arg: &(u32, u32, u32))- > (&'_ u32, &'_ u32). Кажется, что это ненужное добавление, но есть случаи, когда это необходимо (при условии, что программист всё ещё не хочет писать ВЖ явно). Рассмотрим вот такой код (несколько надуманный, но достаточно наглядный);

fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32>> {
Box::new(slice.iter().filter(|&&n| n != 0))
}

Этот код не компилируется. Претензия компилятора сводится к несовпадению типов:

  = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = &u32> + 'static)>`
found `std::boxed::Box<dyn std::iter::Iterator<Item = &u32>>`

Да, тут есть ссылка в возвращаемом типе, и ей приписывается то же ВЖ, что и у slice, но мы не записали время жизни типа внутри коробки, то есть dyn Iterator. Компилятор предположил, что это владеющий тип и, следовательно, он имеет ВЖ 'static, которое является более долгоживущим, чем любое другое ВЖ. Но это не так: возвращаемый итератор содержит ссылку на слайс и потому не может пережить этот слайс. Один из способов исправить ошибку — это ввести новый параметр ВЖ и указать, что возвращаемый тип столько же и живёт, но... Мы ленивые программисты и не хотим писать много, поэтому мы напишем ровно столько, чтобы заставить компилятор работать за нас:

fn non_zero(slice: &[u32]) -> Box<dyn Iterator<Item = &u32> + '_> { ... }

Да, разница действительно всего в 3 символа, не считая пробелов. С такой сигнатурой код уже компилируется, потому теперь благодаря lifetime elision возвращаемому типу приписывается корректное ВЖ.

Но погодите-ка, это ещё не всё! Анонимное ВЖ можно также использовать и в блоке impl. Об этом написано в edition guide здесь и здесь. Порой в impl-блоке типа, параметризованного ВЖ, ничто не зависит от указанного ВЖ, поэтому вместо того, чтобы вводить явно ВЖ после impl и использовать его для типа, можно просто указать '_. Например, если у нас есть определение struct StrWrap<'a>(&'a str);, то можно написать блок методов так:

impl<'a> StrWrap<'a> { ...

, а можно — так:

impl StrWrap<'_>

Это работает и в том случае, если параметров ВЖ несколько: для struct StrPair<'a, 'b: 'a>('a str, &'b str); можно написать так;

impl StrPair<'_, '_> { ...

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

Недостатки у такого способа тоже есть. Каждое использование '_ в заголовке impl-блока создаёт новое ВЖ, что не всегда желательно. Например, в коде ниже

trait WithLifetime<'a> {}

impl WithLifetime<'_> for &str {}

реализация трейта эквивалентна

impl<'a, 'b> WithLifetime<'a> for &'b str {}

, а не

impl<'a> WithLifetime<'a> for &'a str {}

, как можно было подумать. Если требуется, чтобы двое ВЖ для методов было одинаковым, то их надо указывать (и вводить) явно — но только их, остальные можно заполнить анонимным ВЖ. Например, если у нас есть struct Triple<'a, 'b, 'c>(&'a u32, &'b u32, &'c u32);, то можно написать impl-блок так:

impl<'a> Triple<'a, 'a, '_> {}

Также, очевидно, в силу анонимности этих параметров на них нельзя напрямую ссылаться (но можно через псевдоним типа Self).

Подведём итоги:
* Анонимные времена жизни можно использовать в возращаемых типах и в заголовках impl-блоков
* В возвращаемых типах анонимные ВЖ заполняются с использованием нехитрых правил lifetime elision
* В impl-блоках анонимные ВЖ генерируют новые ВЖ на каждое упоминание
- В силу их анонимности их нельзя использовать напрямую
Forwarded from rusta::mann
Forwarded from Блог*
А вот ещё пример из Go. Мутабельных строк там нет (есть лишь string.Builder). Строка в рантайме — это структура с двумя полями: адрес и длина, а слайс — структура с тремя полями: адрес, длина и ёмкость. Технически ничто не мешает преобразовать слайс байт в строку, просто отбросив поле Cap (что, собственно говоря, и происходит в strings.Builder.String), но в общем случае это некорректная операция, потому что слайс мутабельный (всегда, иммутабельной версии слайса просто не существует), а строка — нет. Как результат, каст слайса байт в строку выделяет память в куче и копирует данные. Это лишняя работа, особенно если используемая строка почти сразу отбрасывается — например, если строка используется как ключ для map. В какой-то момент в компилятор Go запилили peephole-оптимизацию, которая распознавала паттерн someMap[string(bytesSlice)] и переписывала на реальный каст на фейковый, который просто копирует указатель и длину из слайса.
Никита Коваль — На пути к быстрой многопоточной хеш-таблице
https://www.youtube.com/watch?v=BpgL2LGEhP4
Хэштаблица самая популярная структура в разработке
#java

ConcurentHashMap
+ O(1)
- использует блокировки (сложно масштабируется)
- хранит списки при коллизии (лишние кэшмиссы)
+ вместо списков хранит дерево пр ипостоянных коллизиях

ConcurentSkipListMap
+ O(log N)
+ это дерево списков
- много лишних обьектов
- постоянные кэшмиссы
- нагружает GC
- не хэш таблица

NonBlocingHashMap
+ lock-free
И собственно в докладе примеры и понимание почему высокий профит от подхода
Introducing Domain-Oriented Microservice Architecture

https://eng.uber.com/microservice-architecture/

и перевод

https://habr.com/ru/company/flant/blog/514830/
https://ru.wikipedia.org/wiki/%D0%97%D0%B0%D0%BA%D0%BE%D0%BD_%D0%9A%D0%BE%D0%BD%D0%B2%D0%B5%D1%8F

«Организации проектируют системы, которые копируют структуру коммуникаций в этой организации»

ВАУ. прям немного шатает разум как трубу от этого)
https://www.the-paper-trail.org/post/2008-08-13-a-brief-tour-of-flp-impossibility/
Реальная система консенсуса не может быть одновременно
- асинхронна
- детерминирована
- отказоустойчива
Что бы она по-настоящему работала всегда надо хотябы в одном из пунктов иметь допущения. (Например рандомные таймеры)
#net вечно забываю
https://ru.wikipedia.org/wiki/Maximum_transmission_unit

MTU - максимальная единица передачи - максимальный размер полезного блока данных одного пакета, который может быть передан протоколом без фрагментации

увеличение пропускной способности в контексте длин пакетов:
- Уменьшение межкадрового интервала. Для Fast Ethernet он по умолчанию равен 0,96 мкс за который могло бы быть передано 12 байт.
- Сжатие заголовков. (сжатие заголовков TCP/IP Якобсона).
- Сжатие нагрузки низкого уровня. (IP Payload Compression Protocol)
- Решение проблемы передачи небольших данных (tinygram problem) за счёт придерживания в буфере малых данных, чтобы отправить один большой пакет. (алгоритм Нейгла)

Path MTU - наименьший MTU на пути следования пакета в сети.
Product Architecture Framework
A clear view of your product.

http://productframework.ru/

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

в видео очень хорошо представлено и обьяснены основны
https://www.youtube.com/watch?v=wRvAle3bXoU&feature=emb_logo

когда то собирал все это по крупицам. а тут все и сразу
тут соберу ссылки по Patroni

- собственно репо проекта
https://github.com/zalando/patroni

- Доклад Отказоустойчивый PostgreSQL кластер с Patroni
https://pgconf.ru/2017/93520

- PostgreSQL на базе Patroni, HAProxy и Keepalived
https://ru.bmstu.wiki/index.php?noscript=PostgreSQL_%D0%BD%D0%B0_%D0%B1%D0%B0%D0%B7%D0%B5_Patroni,_HAProxy_%D0%B8_Keepalived&mobileaction=toggle_view_mobile

- Как мы построили надёжный кластер PostgreSQL на Patroni
https://habr.com/ru/company/mailru/blog/452846/

- Отказоустойчивый кластер PostgreSQL + Patroni. Опыт внедрения https://habr.com/ru/company/miro/blog/457326/

- Построение кластера PostgreSQL высокой доступности с использованием Patroni, etcd, HAProxy https://habr.com/ru/post/482314/

- PostgreSQL на K8s в Zalando: два года в бою / Александр Кукушкин (Zalando SE) https://www.youtube.com/watch?v=33424uhD1ng&feature=emb_logo
https://99designs.com/
надо бы себе сохранить эту ссылку. можно решать вопросы с логотипами, вебдизайном проще, особенно когда не могу найти дизайнера. нужно описать задачу, накидать что нужно и как выглядит примерно. и 50 дизайнеров возьмуться за работу. лучшего - выбрать и заплатить денег. шикарно
#design