Pull to refresh
3
Karma
0.1
Rating
  • Followers 2
  • Following

Связный список на Rust в стиле С/C++

А на что вы намекаете, говоря, что на С точно так же можно написать? Типа зачем тогда нужен Rust?

Написание программ состоит не только из написания списков. То что оптимальная (по скорости) реализация списков в Rust, посути копирует реализацию из C, не означает, что Rust безполезен и в нём в принципе нельзя писать быстрый код без сырых указателей, unsafe и обхода borrow-чекера.

Связный список на Rust в стиле С/C++

Рантайм ошибка? Т.к. очевидно что компилятор тут ничем не поможет - тип ноды не изменяется от того, что её добавили в список.

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

Связный список на Rust в стиле С/C++

А от куда node будет знать из какого именно списка надо удалиться? Судя по API ничто не мешает добавить его в несколько разных списков (и даже несколько раз в один и тот же).

Разве что list.push_back(node) будет "съедать" node и возвращать какой-то враппер вокруг него, тогда у враппера может быть метод remove().

Связный список на Rust в стиле С/C++

Я в принципе не понимаю зачем вы полезли в реализацию Box::new(), зачем решили использовать в своём коде box. И после этого сделали выводы как в анекдоте про сибирских лесорубов, которые засунули стальной лом в японскую лесопилку.

Почему нельзя было использовать Box::new()? Вам что-ли принципильно хотелось с самого начала оперировать только указателями, что бы "всё как в С"?

Связный список на Rust в стиле С/C++

Я лично уже запутался, какие у вас претензии к тому, что box не работает в пользовательсокм коде в стабильной версии Rust?

Вроде всё очевидно - интерфейс этого "оператора" ещё не стабилизирован. Всё ещё есть вероятность, что его могут поменять (например решат, что он должен возвращать Result<Box<T>>, вместо Box<T>).

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

Связный список на Rust в стиле С/C++

Вектор он и в африке вектор, отличаться может только название (например массивом могут называть) - "плоская" коллекция однотипных структур. Моя мысль была в том что однопоточность это не гарантия отсутствия проблем которые предотвращает borrow-чекер. Причём это зачастую не очень очевидные проблемы (как переаллокация вектора при добавлении в него элементов).

Связный список на Rust в стиле С/C++

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

Почему никто не понимает REST

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

Оригинальный REST по сути ближе всего к тому, как классический веб с его HTML-страничками, переходами и формами работает.

А как по вашему браузер понимает как правильно показывать странички, как рисовать формы и отправлять их на сервер?

Он делает это как раз за счёт "типа документа" + "спецификации для этого типа". Первое передаётся в заголовке Content-Type (в случае HTTP), а второе содержит описание того какие "поля" могут быть в документе этого типа и что с ними надо делать клиенту (или серверу).

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

Но я согласен, что в большинстве случаев мало кто использует разные "типы" документов. Обычно делают один, например application/json, а как именно обрабатывать данные с таким типом в клиенте - определяют на основе каких-то зашитых в клиенте эвристик. Наверное более правильно было бы использовать разные типы данных для реально разных ресурсов. Например application/product+json, application/order+json. Но как правило это не используют, т.к., в отличии от браузера, у самописного клиента несколько больше состояний. В зависимости от текущего состояния, клиент определяет каким образом ему обрабатывать получнный от сервера application/json.

Зашитые в клиент "эвристики", вместо повсеместного использования HATEOAS, могут компенсироваться использованием REST принципа "code-on-demand". Оно позволит обновлять и дополнять код клиента, что бы он мог корректно работать после каких-то изменений на сервере.

Современные "App Store" в мобилках и десктопах - это фактически этот самый code-on-demand. Только с ними есть "проблема" - пользователи могут отключить автоматическое обновление. И если это критично для приложения, тогда надо более широко использовать HATEOAS (и даже code-on-demand) внутри самого клиента. Тогда он сможет лучше работать в условиях изменения приложения на стороне сервера. В этом плане веб-браузеры - это наиболее гибкие клиенты для распределённых клиент-серверных приложений, которые у нас сейчас имеются.

Блеск и нищета Ansible

Если есть достпу через ssh, то что мешает пробросить тунель с ноды на котроллер и подключаться к постгрессу со стороны контроллера? Тогда достаточно будет только на контроллере один раз установить psycopg2 любым способом и не тащить его на ноды.

PS: Я сам с Ansible не работал, поэтому не знаю на сколько моя идея "запускать код на контролере" вписывается в его концепцию.

Применение Rust в разработке: страдания и высокий порог входа. Григорий Петров разбирается, когда этот язык необходим

Надо по осторожнее с формулировками вида "код, который не падает" и с противопоставлением С++ на котором сервисы "аварийно завершаются". А то создаётся ощущение, что Rust гарантирует отсутствие падений и аварийных завершений. Падений и аварий с точки зрения пользователя, для которого любое неожиданное завершение приложения - это падение.

Rust ничего такого не гарантирует - достаточно просто поделить число на 0 и приложение "упадёт" как и в других языках программирования. Практически все гарантии Rust связанны только с безопасной работой с памятью. А про "падения" надо всегда пояснять, что имеется ввиду корректное завершение приложения, при возникновении необработанных ошибок. Без вредных сайд-эффектов, вроде выполнения стороннего кода или утечки наружу каких-то приватных данных (но это неточно, т.к. через unsafe и указатели скорее всего можно поковыряться в стеке).

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

Как мы переносили аналитику из PostgreSQL в ClickHouse

Тоже хотел спросить про это.

В последних версиях Citus Data добавили колоночное хранилище. Ограничения у него плюс-минус такие же как у ClickHouse. Например нельзя обновлять данные. Но за счёт использования партицирования таблицы, можно "горячие" данные держать в part-е с обычным строковым хранилищем, а "холодные" part-ы переводить в колоночное хранилище с получением всех его преимуществ.

Парадокс Монти Холла не работает

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

Обработка ошибок в Rust

Тем, что невозможно заранее узнать, какие ошибки может возвращать функция.

В Rust как раз можно узнать какие ошибки возвращаются, ведь тип ошибки явно указывается в сигнатуре функции (если это не anyhow или трейт-объект). Ну или скажем так - можно узнать какие ошибки точно не будет возвращать функция, т.к. не факт, что она будет использовать все возможные значения enum-а, который используется как тип ошибки. Но это идеал к которому надо стремиться.

Асинхронный JSON-Logger для FastAPI

У вашего решения есть заметные недостатки:

  • Ваша миделвара полностью вычитывает тело запроса ещё до того как основной код примет решение о том нужно ли ему вообще это тело. Например приложение может вообще прервать обработку запроса (и не вычитывать его тело) из-за того, что он не прошёл проверку авторизации.
    А если клиент отправил 100500 МБ данных в теле? У вас это всё загрузится в память и пользователь вашей библиотеки даже не может на это повлиять. Ну и кроме того это ломает обработку заголовка запроса Expect: 100-continue

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

Когда я делал подобное логирование тела запроса и ответа, то я во первых проверял Content-Type, что бы он имел какое-то определённое значение. Например application/json, т.к. в контексте приложения нет смысла логировать что-то другое. И так же проверял Content-Length запроса и ответа, что бы он не превышал определённого лимита (а ещё его вообще может не быть, если тело передаётся чанками). Ну и тело запроса я достаю уже после того как запрос был обработан приложением.

Будущее Web это HTML через WebSockets

хранение состояние на сервере

Где-то в мире стало грустно Рою Филдингу.

Процессор Эльбрус — почему это тупик для развития отечественной линейки general-purpose CPU

С современными компиляторами очень даже приходится смотреть на ассемблер, т.к. нет уверенности, что компилятор "понял" как правильно оптимизировать код. Да, это требуется не так часто, и в основном только для тех, кто ведёт разработку на низкоуровневых языках. А ведут её преимущественно из-за скорости работы кода на этих языках. И если вдруг программа не выдаёт ожидаемой скорости, то рано или поздно (когда выверил все алгоритмы) добираешься до ассемблера и начинаешь искать в нём проблемы.

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

Начало работы с MongoDB и Redis на Rust

маловероятно, что что-то может пойти не так.

"Ты не поверишь" :)

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

  • кеш содержит неактульное значение

  • запрос клиента завершится ошибкой из-за проблем с вспомогательным сервисом (кешем), несмотря на то что полезная работа была выполнена без ошибок.

Второй вариант - приложение жёстко перезапустили ровно в момент между запросом к монге и запросом к редиске.

Начало работы с MongoDB и Redis на Rust

Не корректно реализована работа с кешом в редиске - в два запроса. Просто классический race-condition. Первым запросом вы проверяете наличие ключа в редиске, вторым читаете его значение. Только вы совсем проигнорировали то, что чтение может вернуть ошибку в том числе и потому, что ключа нет в базе, т.к. его удалили в промежутке между первым и вторым запросом. В итоге приложение выкинет ошибку на ровном месте. Кроме того, в остальное время, будет оверхед на запрос проверки наличия ключа. Надо сразу запрашивать значение ключа одним запросом и обрабатывать ошибку его отсутствия.

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

Почему PostgreSQL тормозит: индексы и корреляция данных

А почему скажется положительно? Добавление нового значения в "конец" индекса работает быстрее, чем добавление куда-то в середину?

Почему PostgreSQL тормозит: индексы и корреляция данных

а где вы увидели сортировку?

Видимо вы не внимательно прочитали статью. Речь не о поиске одной строки по её UUID. Речь о том как сделать так, что бы вычитка большого числа строк из таблицы работала ещё быстрее, при использовании индекса по полю с условно рандомным значением.
Для этого надо, что бы физически все строки, которые выдаёт индекс, находились как можно кучнее, рядом друг с другом. Я может ошибаюсь, но по моему только явная сортировка гарантирует, что мы будем читать строки в каком-то определённом порядке. Остаётся только сделать так, что бы физически строки на диске лежали в таком же прядке. И для этого предлагается добавить к "рандому" монотонно растущий префикс, который гарантирует нам, что индекс будет выдавать строки в том же порядке, в котором мы их создавали.


если время у них синхронизировано, то ulid, думается, будет неплохо работать

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

Information

Rating
2,495-th
Location
Россия
Registered
Activity