Pull to refresh
29
2.1
Send message

Мда. Во-первых, надо поработать над языком, написано ужасно. Во-вторых, надо поработать над оформлением, набор красно-чёрных картинок занимает 70% вертикального пространства статьи, нафиг не надо. В третьих, надо поработать над структурой.

Я расскажу в комментарии, что это не статья, а LLM-ный мусор для заманухи в телеграм-канал.

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

Про очистку строки и бит LP_DEAD - был неправ, мне причудилось, что написано "удалена или вышла за горизонт". Спасибо, что прояснили, что имеется в виду "очищенная" строка.

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

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

В первом абзаце есть вот такое:

Внутристраничная очистка (HOT cleanup) – это оптимизация, благодаря которой старые версии строк могут эффективно удаляться из блоков таблиц. Освобождённое место используется под размещение новой версии строки. Освобождается только место, занимаемое версиями строк, вышедшими за горизонт базы данных (xmin horizon)

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

А потом во втором абзаце уже идёт вот такое:

Алгоритм быстрой очистки табличной страницы реализован в файле pruneheap.c (heap page pruning and HOT-chain management code) исходного кода PostgreSQL. При удалении строки в блоке (странице) таблицы удаляющая транзакция проставляет свой номер в заголовок строки в поле xmax и пытается найти место под новую версию строки в том же самом блоке, при этом признак фиксации не проставляется.

Здесь уже, как я понял, речь совсем про другое: удаление строки из таблицы через DELETE в рамках пользовательской транзакции. Как это связано с "быстрой очисткой страницы" - непонятно и не объяснено.

Когда вы говорите, что бит LP_DEAD выставляется, когда index scan обнаружил, что "строка удалена", вы что имеете в виду? Какая-то транзакция могла пометить версию строки как "удалённая", но для параллельно выполняющихся repeatable read транзакций нужно возвращать эту строку, поэтому что-то сомнительно. А если имеется в виду запись, помеченная как "очищенная", тогда понятно.

Мусорная статья, написанная нейросетью.

А ну хотя чего я удивляюсь, часть про транзакции и заключение писала LLM, а от автора тут только часть про JOOQ и сохранялку из Kafka. Фу так писать.

Неудачная структура статьи: главная часть - это очень базовое объяснение транзакций, которое знакомо мало-мальски работающему с базами данных человеку. Потом перепрыгнули на JOOQ непонятно зачем, про его связь с транзакциями не сказано ничего. И дальше про сохранялку из Kafka. Меня вышибает термин "JDBC коннектор Kafka", я не могу воспринимать это иначе чем нечто, что реализует JDBC-интерфейс для данных, хранящихся в логах Kafka. Оказалось, имелся в виду Kafka Connect, который сливает в базу данные из топиков. Мне кажется, вы в объяснении где-то напутали, и хотели сказать, что read repeatable вам не подошёл, а подошёл read commited. Ну логично, там же только сохранение данных. В конце вы сами пишете, что read commited - уровень по-умолчанию, значит даже у человека, не понимающего в транзакциях, всё бы сработало.

Увидел в названии "философия", заинтересовался, прочитал. Мда, и правда "философия".

Люди добрые, помогите, пожалуйста? Читал году примерно в 2000-2001 в электронном виде фэнтези-произведение российского автора, забыл и автора и название. Сюжет таков: какого-то принца колдуны отправляют искать "дракона", забрав невесту в заложницы. После множества мощных приключений он попадает в пустыню, "дракон" оказывается летательным аппаратом, герой возвращается и мстит колдунам. По градации автора этой статьи это очень глупое чтение, не попаданство, но абсолютно безыдейное sword and sorcery, без worldbuilding-а, без характеров и без истории. Очень хочется перечитать.

Какие-то советы для начинающих индусов из года примерно 2010. Блог компании OTUS, наш девиз "похер на качество контента, мы берём количеством".

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

Не нужно size() выносить в переменную, компилятор это оптимизирует сам.

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

Автор-питонист хотел поджечь Java-жопы, и ему это удалось. При этом пытался немножко выглядеть объективными и профессиональным, но наличие мемасов в статье выдавало Штирлица. А потом в комментах начали поджигать жопу автору. Нравится!

Теперь совсем про другое: про реализацию quicksort на Java, которую автор привёл. Там в partition() два индекса, и для некоторого количества элементов в начале оба индекса будут совпадать, пока эти начальные элементы меньше pivot-а. Представленный алгоритм будет менять элемент самого с собой. В худшем случае, если исходный массив уже отсортирован, будет много лишней работы. Можно добавить if, но он будет напрасно исполняться на том этапе, когда i уже гарантированно меньше j, тоже неприятно.

    private static int partition(int[] arr, int low, int high) {
        int pivot = arr[high];
        int i = low ;

        for (int j = low; j < high; j++) {
            if (arr[j] <= pivot) {
                if (i < j) {
                    int temp = arr[i];
                    arr[i] = arr[j];
                    arr[j] = temp;
                }
                i++;
            }
        }

Прямо даже не знаю, хоть два цикла делай.

Ужасно. Один из абзацев присутствует в двух местах. Ничего толкового про кодировки не написано.

Скажите, Дмитрий, вот я открыл текст статьи на вашей wiki, начинаю скроллить мышкой вниз по полосе прокрутки, и через какое-то время начинается очень неприятное явление: ползунок перестаёт сдвигаться вниз, возвращается назад, из-за чего скроллить очень неудобно. Я догадываюсь, что это какая-то "оптимизация" рендера, но мне, как пользователю, очень не нравится. Браузер Chrome.

Мне кажется, что есть ещё третья ошибка, возникающая при программировании конечных автоматов, от которой спасают акторы. Я называю её "object reentrancy". Суть вот в чём: функция или метод, принимающая событие, должна сделать две вещи: поменять состояние, и выполнить всякие side effect-ы. Представим, что она это делает в таком порядке: сначала выполняет сайд-эффекты, а потом меняет состояние. Если side effect - это синхронный вызов, то в его процессе может породиться новое событие, и в том же потоке выполнения снова вызовется метод, принимающий событие. Но состояние-то осталось старым! Потом эта цепочка начнёт раскручиваться, и состояния начнут обновляться задом наперёд. Mutex-ы не спасут, они обычно позволяют себя повторно захватить потоку, который ими и так уже владеет.

В ООП есть понятие "class invariant". Это нормально, что внутри метода этот инвариант временно ломается, пока это не наблюдаемо извне. Но если метод временно передаёт управление, например в какой-нибудь callback, пока инвариант сломан, то возможна неожиданная жопа. Я с таким сталкивался, когда у меня несколько стейт-машин общались друг с другом.

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

Господа, каламбурчик:

Сидит девочка в песочнице, играет. Идёт мимо Дмитрий, подходит и говорит:

- Я Дмитрий Карловский, автор самого лучшего фреймворка $mol ! Живи с этим!

- С кем, с тобой что ли, козёл?

Извините

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

Как вы надоели со своим LLM-ным мусором. Нет у первого "языка" никакой "поддержки функций" и "стека вызовов". Оба примера фундаментально зависят от хост-языка.

Я почитал исходники. Питона не знаю, но что-то попробовал понять.

Лексер нужно улучшать. Во-первых, он принципиально неправильно написан: вы тупо пытаетесь регулярки применять к вводу, из-за чего, встретив, например, "iframe", он выделит "if" как ключевое слово. Правильный способ - конечный автомат, то есть у лексера появляется состояние. Ну и напоследок, вы бы хоть компиляцию регулярок не делали каждый раз, очень уж тормознуто.

С компилятором не понял вот чего: все функции, получается, инлайнятся?

С виртуальной машиной много непоняток. Почему-то FETCH, который у вас для сохранения глобальной переменной на стеке, в случае, если переменная неинициализированна (или тупо опечатка), пушит 0. А STORE наоборот, ругается, если глобальной переменной нет. Я бы сделал наоборот. Не очень понял смысла операции POP, и мне кажется, что она pc недостаточно увеличивает.

Information

Rating
1,229-th
Registered
Activity