Вы пришли сюда получить ответ на вопрос или потролить? Если вам нужна модель памяти .NET, я не понимаю зачем вы расспрашивали про барьеры в async/await и давали ссылку на код Task.
ээ… Вы сослались на java в предыдущем вопросе. Я сослался на ответ и задал вопрос по вашему ответу. Мне просто не особо нравится, что все ссылаются на правило адекватности асинхронных примитивов, когда у нас нет первоисточника на это. Поэтому я испрашивал про конкретно те барьеры, которые решают обсуждаемые выше проблемы.
Барьеры памяти — глобальны. Поток, прочитавший из volatile поля, увидит все изменения, сделанные другим потоком до записи в любое volatile поле.
Все так. Вы хотите сказать, что в этом коде нет явных барьеров для до/после async/await, и мы просто пользуемся барьерами, которые ставятся для работы с состоянием Task?
По поводу же того какие изменения другие потоки гарантированно увидят — лично я пользуюсь следующим правилом, которое я называю правилом адекватности асинхронных примитивов:
Эти правила, что вы сказали, звучат адекватно, и все их копируют из раза в раз на stackoverflow. Проблема в том, что это нигде не сказано в официальной документации.
Ага, я вижу там большое количество volatile и тд. Но все случаи, что я вижу — относятся к работе к самому Task, или его состоянию. Выше же мы обсуждали барьеры для того, чтобы код в других потоках увидел изменения, сделанные внутри async/await, а также для того, чтобы новый код, запущенный через async/await, видел изменения, сделанные до его создания.
В целом, можно пробовать смотреть JIT ASM в условном https://sharplab.io/, но это не выглядит как надежный способ изучения вопроса, при условии что в sharplab даже Арма нет, где более слабые гарантии памяти. Еще можно в сорцы dotnet смотреть, но это про текущее состояние, а не спецификацию поведения.
А вот в ваших рукописных реализациях async/await ничего нет про барьеры памяти. Но они же иногда должны быть, иначе бы мы иногда не видели изменений, сделанных из асинхронного метода в методе, где мы ждем результат. Интересно, что и в официальных доках я тоже ничего про это не вижу, только в ответах на stackoverflow.
Возникает вопрос, зачем делать пул managed-объектов, вместо перехода на нативный аллокатор?
А кто-нибудь использовал такой подход в реальных проектах? А то например jemalloc.NET не особо обновляется в последние годы. В теории, даже API нужное есть в виде MemoryManager, надо только его реализовать.
То есть, мы получили span, который взят из оригинальной строки. Потом допустим хотим удалить последние 2 символа строки, условно говоря мой newSpan из кода выше. Сам по себе слайс ничего не сделает, просто выставит новые границы. Вот и было интересно, можно ли как-то в оригинальной строке, которую мы поменяли одним из небезопастных способов, потом еще и откусить суффикс, тем самым удалив несколько символов в конце.
Вопрос про второй способ (Span), ну, или вообще любой.
Допустим я получил из строки Span, поменял что-то, или вообще хочу взять слайс, потому что мне не нужны последние 2 символа. Если я вызову .ToString(), для того чтобы обратно получить строку, я получу в лоб аллокацию. Выглядит так, что весь смысл string -> span -> string потерялся.
Было бы еще интересно послушать, зачем поступать в китайский университет на магистратуру? Какая после этого доступна траектория жизни? С таким требованием к английскому языку должно быть возможным поступить также либо в северную америку, либо в европу. Соответственно, у нас есть довольно много выбора.
Привет, спасибо за рассказ. Возникла пара вопросов:
4000 разработчиков в штате — пугающая цифра. Есть ли возможность немного описать разбиение людей по каким-то продуктам/группам? Или это не только Озон, но и какие-то другие проекты вашей фирмы?
Платформенные команды забрали к себе все вкусные задачи, позволив продуктовым командам только разрабатывать бизнесовые фичи. Как вы боритесь с выгоранием людей в продуктовых командах, где нет никаких технологических челленджей, и нужно просто использовать готовые managed сервисы?
ээ… Вы сослались на java в предыдущем вопросе. Я сослался на ответ и задал вопрос по вашему ответу. Мне просто не особо нравится, что все ссылаются на правило адекватности асинхронных примитивов, когда у нас нет первоисточника на это. Поэтому я испрашивал про конкретно те барьеры, которые решают обсуждаемые выше проблемы.
Все так. Вы хотите сказать, что в этом коде нет явных барьеров для до/после async/await, и мы просто пользуемся барьерами, которые ставятся для работы с состоянием Task?
Эти правила, что вы сказали, звучат адекватно, и все их копируют из раза в раз на stackoverflow. Проблема в том, что это нигде не сказано в официальной документации.
В случае Java у нас есть https://docs.oracle.com/javase/specs/jls/se8/html/jls-17.html. Есть ли что-то подобное у dotnet?
Ага, я вижу там большое количество volatile и тд. Но все случаи, что я вижу — относятся к работе к самому Task, или его состоянию. Выше же мы обсуждали барьеры для того, чтобы код в других потоках увидел изменения, сделанные внутри async/await, а также для того, чтобы новый код, запущенный через async/await, видел изменения, сделанные до его создания.
Не могли бы вы подсказать, где находится код, делающий это? С первого взгляда не вижу этого.
https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Threading/Tasks/Task.cs
Как вы проверяете? Я вижу что строка изменяется и в случае
private const string Content
.https://dotnetfiddle.net/mHRNKR
Почему не меняется?
https://dotnetfiddle.net/0IMbZo
А зачем мы в этом способе выделяем новую строку (2), если мы уже поменяли исходную (1)?
создатель зио считает, что зио и лум должны существовать, где лум дает платформу, а зио — удобное, безопастное API поверх — https://www.youtube.com/watch?v=9I2xoQVzrhs
Примеры вот — https://stackoverflow.com/a/54413147/1756750, или https://stackoverflow.com/a/55139219/1756750
В целом, можно пробовать смотреть JIT ASM в условном https://sharplab.io/, но это не выглядит как надежный способ изучения вопроса, при условии что в sharplab даже Арма нет, где более слабые гарантии памяти. Еще можно в сорцы dotnet смотреть, но это про текущее состояние, а не спецификацию поведения.
А вот в ваших рукописных реализациях async/await ничего нет про барьеры памяти. Но они же иногда должны быть, иначе бы мы иногда не видели изменений, сделанных из асинхронного метода в методе, где мы ждем результат. Интересно, что и в официальных доках я тоже ничего про это не вижу, только в ответах на stackoverflow.
А кто-нибудь использовал такой подход в реальных проектах? А то например jemalloc.NET не особо обновляется в последние годы. В теории, даже API нужное есть в виде MemoryManager, надо только его реализовать.
Я думал про какой-то такой пример:
То есть, мы получили span, который взят из оригинальной строки. Потом допустим хотим удалить последние 2 символа строки, условно говоря мой newSpan из кода выше. Сам по себе слайс ничего не сделает, просто выставит новые границы. Вот и было интересно, можно ли как-то в оригинальной строке, которую мы поменяли одним из небезопастных способов, потом еще и откусить суффикс, тем самым удалив несколько символов в конце.
Допустим я получил из строки Span, поменял что-то, или вообще хочу взять слайс, потому что мне не нужны последние 2 символа. Если я вызову .ToString(), для того чтобы обратно получить строку, я получу в лоб аллокацию. Выглядит так, что весь смысл string -> span -> string потерялся.
Есть какой-то способ избежать аллокации тут, переиспользовав массив из оригинальной строки?
github.com/uber/piranha