Как стать автором
Обновить
2
0

Пользователь

Отправить сообщение

Если не сложно, можете пожалуйста объяснить что каждая настройка делает?

Добавить описание из доки Apple - хорошая идея. Спасибо.

Но в остальном - он даже не сказал что это замена примитивам синхронизации, и более производительная. Думаю 99% людей, прочитав такое описание, подумали бы "ну и нафиг это надо, можно просто каналы использовать")

зачем то (с)

в рамках одного треда

Ну как то вам не помогло все таки)

аналог Task.Run и Dispatcher.BeginInvoke

А это он вообще писал про Concurrent и Main queues)

В статье много посылов, но по части синхронизации - имеют смысл только два механизма, спинлоки примерно до 0.1 мс и очереди для остальных.

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

Они применимы для любого языка, так как имеют O(1) по времени от длины операции, в отличие от блокирующих способов. Боюсь что вы, во первых, не совсем поняли о чем в статье речь, во вторых написали плохие тесты.

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

И это полностью соответствует тому, что написано в статье, и результатам моего бенчмарка.

А теперь замените во втором тесте counter++ на операцию длиной 5 мс.

Понял проблему, добавил примеры использования в статью сразу после секции "Написание библиотеки".

Последовательные очереди асинхронны так как не блокируют поток в ожидании очереди. Поэтому нельзя заменить Monitor на SerialQueue не добавляя асинхронность. Можно конечно вызвать синхронную операцию DispatchSync, но тогда потеряется весь смысл.

Эффективная синхронизация не может быть синхронной, только для супер коротких операций со SpinLock.

Про это статья и написана. И прочитайте секцию "выводы" еще раз.

асинхронную\многопоточную без понятия как измерять

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

Я уже не знаю как еще ответить вам, кинул и ссылку на бенчмарки, и ссылку на readme где после примеров с очередями указано:

Previous examples do the same as the next one with Monitor (lock):

readonly object locker = new object();

async Task SomeAsyncMethod()
{
    lock(locker) {
         // synchronized code
    }
}

Что переводится как "Предыдущие примеры (с очередями) делают то же самое, что следующий с Monitor (lock):"

Даже на C# уже асинхронность встроена во все фреймворки, является стандартом и отличается от синхронного кода лишь словом await.

Еще раз, на NodeJS и Go это не оверинжинеринг а самый обычный код, не требующий никаких дополнительных усилий, и «по плохому» либо не написать, либо надо сильно заморочиться.

Если на Java «по хорошему» требует невероятных усилий, то это плохая технология, от которой следует отказаться.

Принцип KISS.

Отвечу сразу на оба коммента.

Даже на спринге можно написать вполне себе неплохое реактивное приложение. Все для это есть. И я видел много примеров в том числе на работе.

...

По поводу r2dbc. postgres https://www.postgresql.org/docs/current/libpq-async.html имеет интерфейсы для асинхронной работы. 

Да, не обратил внимание что речь про r2dbc, у него можно, но почему то мало кто его использует, и в интернете для продакшена часто не советуют использовать. Если "можно написать вполне себе" то почему большинство так не делает? Я говорил про стандарты разработки, то есть то, как делает большинство в продакшене.

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

То есть можно "говнокодить" на уровне приложения и не следить за его производительностью? Не согласен совсем. И я привел пример почему, на основе опыта Paypal.

И как может переход на nodejs что то дать вообще не ясно. Или там какой то другой асинхрон?

Тоже про это писал, там стандартом является честная (неблокирующая) асинхронность IO операций и количество потоков строго по количеству ядер (за редким, не очень нужным исключением). И все это без удаления гланд через задний проход элементарно и из коробки.

То есть у вас есть допустим пул объектов которые хотим шарить между потоками. Тут получается нужно делать n single thread executor и на каждом запускать задачи и как то потоки задач разделять по этим n экзекьюторам.

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

readonly SerialQueue serialQueue = new SerialQueue()

// функция вызывается параллельно в пуле потоков для каждого запроса
async Task<Response> HandleRequest(Request request) {
  ...
  await serialQueue.Enqueue(() => {
    // обработка состояния, требующего синхронизации
  });
  ...
}

Еще раз, с тем же Monitor, когда в секцию lock пытаются войти 1000 потоков в секунду а выходит оттуда 10, 990 потоков в секунду будут блокироваться и пул будет создавать новые пока не закончится память.

Это ситуация не здоровая в любом случае, и возникла скорей всего из за критического бага.

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

...добавляются так же баги, влияющие на стабильность приложений, например такие

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

...когда синхронизировать вообще ничего не нужно (функциональный подход). Его часто ещё совмещают с реактивным программированием.

Про "вообще ничего не нужно" пожалуй не соглашусь, что то да нужно.

Хотел бы добавить про то, почему стоит выбирать слабый девайс на android - это самая медленная платформа. Если на android все ок, то на iOS и Web будет вообще летать.

Более того, по моим замерам то же самое приложение в браузере (react-native-web) может работать даже немного быстрее, чем нативное на андроиде, что очень странно. Кажется все эти Java-прослойки прям сильно тормозят.

Про процессор - проблема в 99.9% случаев в JS потоке, я бы сказал что это главное узкое горлышко React Native. Но если писать код грамотно то все будет ок.

Ну и конечно в реальности найти причину по профилировщику не так просто как в данных примерах, мне иногда проще просто глянуть на код и все становится ясно. Но инструменты 100% нужные.

PS. "Перформанс", "ворнинги" ?

...механизмом синхронизации.

Информация

В рейтинге
5 647-й
Зарегистрирован
Активность

Специализация

Frontend Developer, Mobile Application Developer
Lead