Пытаюсь замутить свой симулятор.
| |
V9 | Дата: Пятница, 07.06.2024, 13:26 | Сообщение # 181 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Цитата V9 ( ![Ссылка на цитируемый текст](/.s/img/fr/ic/12/lastpost.gif) ) Есть у меня психологическая проблема. Я сам себе ставлю некие задачи повышенной сложности которые сам же потом не могу решить. Из-за чего общий прогресс замедляется или стоит на месте. Надеюсь, я смогу это побороть в себе.
Встрял на проблеме "параллельной работы двух потоков - Модели и Графики - и передачи данных между ними без задержек".
upd. Практически сразу нашлось правильное решение. Я на этой задаче месяц сидел, если без шуток. Поставил сам себе ограничения и не мог решить задачу в этих ограничениях. Но решил почти сразу, как выложил жалобу на форум.Добавлено (10.06.2024, 12:51) --------------------------------------------- В негативном ахрене от Java.
Суть. Обработка(программа) в DSim идет в два потока:
1. Поток №1 постоянно читает данные из GID.txt, разбирает их и должен отправить в поток №2. сигнализирует потоку №2 о поступлении новых данных. 2. Поток №2 занят отрисовкой графики на экране. Он вызывается (косвенно) из потока №1, а так же из операционки, если надо обновить окно (скажем, была другая прога над моим окном, убралась,надо отрисовать наше окно) или же как следствие действий пользователя. Скажем, пользователь изменил размеры, подвигал по окну мышкой, нажал клавиши и т.п.
По идее, ни поток №1, ни поток №2 никогда не должны тормозиться "обо что-то". Первый - потому что в будущем это должна быть Модель Мира, где будут ехать поезда и она должна в режиме реального времи все обсчитывать. Второй - потому что будет выглядеть как "тормозной интерфейс": пользователь максимизировал окно, прога задумалась, зависла, потом "раздуплилась".
Поэтому я ставил сам себе задачу написать передачу данных "без блокировок". 1. не должны использоваться мьютексы (mutex) - https://ru.wikipedia.org/wiki/%D0%9C%D1%8C%D1%8E%D1%82%D0%B5%D0%BA%D1%81 2. не должны использоваться volatile переменные, которые вызывают "атомарные операции" - https://ru.wikipedia.org/wiki/%D0%90%D1%82%D0%BE%D0%BC%D0%B0%D1%80%D0%BD%D0%B0%D1%8F_%D0%BE%D0%BF%D0%B5%D1%80%D0%B0%D1%86%D0%B8%D1%8F 3. Какой бы большой пакет данных не пришел, он должен быть передан "за один цикл". 4. Прога должна минимизировать "удаление устаревших аднных", данные должны правиться, а не удаляться. Это означает, что требуется еще и передача "использованных данных" обратно из потока №2 в поток №1 под будущие данные из GID.txt.
Задача была очень сложной и интересной, я перебрал что-то около 100 вариантов прежде чем смог сделать. И....
Оффтоп. В современных компах много процессоров на одном ядре. У каждого процессора есть своя кэш-память https://ru.wikipedia.org/wiki/%D0%9A%D1%8D%D1%88_%D0%BF%D1%80%D0%BE%D1%86%D0%B5%D1%81%D1%81%D0%BE%D1%80%D0%B0
Если процессор поменял значение ячейки памяти, это значение остется только в кэше этого процессора. Но другой процессор может тоже захотеть "ознакомиться" с этой ячейкой. И вот чтобы другой процессор не увидел "старое значение" ячейки, существует специальный протокол MESI - https://habr.com/ru/articles/183834/
Т.е., в худшем случае, через пикосекундную задержку все другие процессоры ознакомятся с новым значением этой ячейки памяти, при этом само значение возможно и не покинет сам процессор никогда, никогда не будет записано в оперативную память.
"Переменные" в Java - это отсылки на ячейки оперативной памяти, которые, при работе, тоже будут сидеть в кэш-памяти. То есть, я рассчитываю, что записав некоторое значение в память с потока №1, через несколько пикосекунд я смогу ознакомиться со значением в другом потоке.
Конец оффтопа.
Моя задача так написать алгоритм, чтобы при любой модификации не получилось так, что одна и та же ячейка пишется одновременно из двух потоков. Он хорошо отработал на "старой джаве", которая тут лежит и которую я рекомендую качать. Но у пользователя может быть новая джава. Поэтому я проверил алгоритм на новой джаве, заодно проверив "однозначность алгоритма" т.е. последовательность передачи-приема.
И врезался в ошибку... Алгоритм иногда(!) работал, иногда(!) нет. Ошибка была только на поздних релизах. Начал разбираться...
И в шоке выяснил, что в Java есть "оптимизатор": если "оптимизатор", условно, 1000 раз прочел ячейку и там наблюдал одно и то же значение, он делал "предположение", что в этой ячейке ВСЕГДА будет храниться одно и то же значение. И перекомпилировал код так, чтобы в программу всегда передавалось одно и то же "считанное" значение, без обращения к памяти.
То есть, я запускаю два потока. 1. Если "генератор" запускается раньше, чем "потребитель", то оптимизатор "потребителя" видит, что значения в ячейке постояно меняются "генератором": "генератор" запустился раньше и начал "срать" данными. Оптимизатор ничего не оптимизирует, продолжает читать из памяти. 2. Если "потребитель" запустился раньше "генератора", то "потребитель", условно, 1000 раз "крутанется", увидит, что 1000 раз там "ничего нет", запустится "оптимизатор" и отныне и до конца работы проги я буду получать "ничего нет!". "Потребитель", после отработки "оптимизатора" уже ничего не будет читать из памяти, просто будет "крутиться" в пустом цикле и ничего не будет делать. Только занимать процессор и греть воздух. Добавлено (10.06.2024, 16:12) --------------------------------------------- Что же предлагает джава,чтобы не нарваться на "оптимизатор"? По факту - "для передачи данных между потоками используйте переменные типа volatile!"
Volatile-переменные - дико медленные. При их использовании процессор блокирует шину передачи данных командой LOCK для остальных процессоров, а сведения отправляются напрямую из процессора в оперативную память. Все остальные процессоры в этот момент сосут чупа-чупс стоят, если только не используют сведения из своей кэш-памяти. Команда LOCK используется для того, чтобы безопасно эксклюзивно обновить некую ячейку памяти. Но у меня специально было спроектировано так, чтобы этого не требовалось!
Сообщение отредактировал V9 - Пятница, 07.06.2024, 21:19
| |
| |
V9 | Дата: Вторник, 25.06.2024, 09:05 | Сообщение # 182 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Вернулся к разработке. Выяснилось, что я не знал, что такое поведение характерно для более высоких версий Java, где они, да, могут прятать переменные памяти в регистры. Но это потому, что для разрабов Java, в Java 9 ввели класс с методами VarHandle.setOpaque() и VarHandle.getOpaque(), которые может использовать программист чтобы приказать компилятору - "Так, Java! Вот конкретно вот тут фигней не страдаем, а пишем/читаем строго в(из) память(-ти)!
| |
| |
olegpersh999 | Дата: Вторник, 25.06.2024, 09:21 | Сообщение # 183 |
Начальник станции
Группа: Пользователи
Сообщений: 181
Награды: 3
Репутация: 0
Статус: Offline
| V9, надеюсь всё получится у тебя!
| |
| |
V9 | Дата: Вторник, 25.06.2024, 12:50 | Сообщение # 184 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Ё! Первый поезд показался! V.0.0.6.13/
![](/_fr/3/1457461.png) Это с поездной ситуации Сургута, отправился 380й поезд.
![](/_fr/3/3151980.png)
Пока что там делается отбор только по Сургуту и только по поездам отправления. Нечетные на юг не показались потому что GID.txt у меня был обрезанный. ps. Релиз прикладывать? Он почти не работает и в разработке.
| |
| |
V9 | Дата: Вторник, 25.06.2024, 13:25 | Сообщение # 185 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| ![](/_fr/3/4538573.png)
Картинка релиза DSim с одной из моих реальных игр. Должно было отрисовываться и вниз, но до этого еще надо дойти =)
| |
| |
V9 | Дата: Вторник, 25.06.2024, 13:50 | Сообщение # 186 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| ![](/_fr/3/5977783.png) V.0.0.6.14. Отрисовались все поезда по Сургуту. В данный момент отрисоывается один час, последний оперативный. Убрал одну ошибку, когда обработка падала на "+" и "-" поезда (формируемые и расформируемые). Пока что не тестировалось динамическое взаимодействие с pult.exe в процессе игры. Релиз прикладываю. Запускать Startup.bat. upd. v.0.0.6.15 Hotfix. аварийный вылет когда запускалась параллельная работа с Pult.exe. Исправлено. Теперь работает.
Сообщение отредактировал V9 - Вторник, 25.06.2024, 14:46
| |
| |
olegpersh999 | Дата: Среда, 26.06.2024, 10:16 | Сообщение # 187 |
Начальник станции
Группа: Пользователи
Сообщений: 181
Награды: 3
Репутация: 0
Статус: Offline
| Что-то не рисует или я что-то не так делаю?
| |
| |
V9 | Дата: Среда, 26.06.2024, 13:41 | Сообщение # 188 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Сорри! Не сказал. Это не релиз в смысле "Релиза" как "готовый продукт", это некая жуткая пре-пре-альфа в самой начальной разработке. Не удержался, выложил. "Зачем?" - честно сказать, сам не понял.
| |
| |
V9 | Дата: Среда, 26.06.2024, 16:07 | Сообщение # 189 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Pre-alpha релиз 0.0.6.16
![](/_fr/3/s6110390.jpg)
За часик работы сделал отрисовку всех станций пульта. Пока поезда не соединяются по линиям движения, нет маркировок и т.п. Это все будет решаться. Тут нет Ингу-ягуна и Покачей, как и нет Черного Мыса и нет Сургут-Порта так как эти станции вообще не пишутся в GID.txt. Рабочие комбинации клавиш: 1. Ctrl-влево и Ctrl-вправо меняют цветовую схему. 2. Ctrl-i инвертирует график, четные начинают ехать вниз. Это случай olegpersh999.
upd. Подобрал размеры, че-то даже подсовпало.
Сообщение отредактировал V9 - Среда, 26.06.2024, 18:51
| |
| |
olegpersh999 | Дата: Четверг, 27.06.2024, 09:28 | Сообщение # 190 |
Начальник станции
Группа: Пользователи
Сообщений: 181
Награды: 3
Репутация: 0
Статус: Offline
| У меня что-то совсем ничего не рисует
| |
| |
V9 | Дата: Четверг, 27.06.2024, 10:46 | Сообщение # 191 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| gid.txt приложите, плиз, из каталога territory\1
| |
| |
olegpersh999 | Дата: Четверг, 27.06.2024, 13:04 | Сообщение # 192 |
Начальник станции
Группа: Пользователи
Сообщений: 181
Награды: 3
Репутация: 0
Статус: Offline
| Прикладываю
| |
| |
olegpersh999 | Дата: Четверг, 27.06.2024, 13:04 | Сообщение # 193 |
Начальник станции
Группа: Пользователи
Сообщений: 181
Награды: 3
Репутация: 0
Статус: Offline
| ...
| |
| |
V9 | Дата: Четверг, 27.06.2024, 17:28 | Сообщение # 194 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Цитата olegpersh999 ( ![Ссылка на цитируемый текст](/.s/img/fr/ic/12/lastpost.gif) ) Прикладываю ![](/_fr/3/s0827223.jpg)
Хм, у меня вот так ваш гид отрисовался. Возможный некий глюк при совместной работе с pult.exe. ps. Такая возможность может быть если pult.exe сделал "рваную" строку, записав полстроки. DSim глюканет в такой ситуации. Надо будет обдумать.
| |
| |
V9 | Дата: Пятница, 28.06.2024, 04:55 | Сообщение # 195 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| ![](/_fr/3/s1390926.jpg) Уже похоже на правду. Сделана отрисовка "между-станциями". Одна линия на чертеже выглядит багом(ошибкой), но это так разные поезда наложились на участке УЯ-Чу
Сообщение отредактировал V9 - Пятница, 28.06.2024, 06:27
| |
| |
V9 | Дата: Пятница, 28.06.2024, 06:29 | Сообщение # 196 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Ветка 0.0.6 заканчивается, начинается ветка 0.0.7. В новой ветки планируется:
- Отрисовка двух часов вместо одного, автоматический сдвиг картинки при переходе в новый час
- Линии часовые, минутные
- Отрисовка последней минуты отправления/прибытия.
| |
| |
V9 | Дата: Пятница, 28.06.2024, 12:43 | Сообщение # 197 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| ![](/_fr/3/s2824611.jpg)
Красота, правда? Релиз 0.0.7.0. Клавиши управления: Ctrl-i - инверсия по вертикали. Ctrl-o - увеличить количество демонстрируемого времени на экране Ctrl-p - уменьшить -------------------- // --------------------- // ------------------------
Ctrl+ стрелка влево (стрелка вправо) - сменить графику.
| |
| |
V9 | Дата: Суббота, 29.06.2024, 20:24 | Сообщение # 198 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| ![](/_fr/3/5099937.png)
Присутствуют косяки в цифрах. Прибытие накладывается на отправление или же транзит. Это будет исправляться, поэтому релиз не выложил.
Сообщение отредактировал V9 - Суббота, 29.06.2024, 21:07
| |
| |
V9 | Дата: Суббота, 29.06.2024, 22:38 | Сообщение # 199 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
| Релиз пре-Альфа 0.0.7.3. Добавлена отрисовка минутных линий, добавлена возможность "отмотать" командой ctrl-o до 24 часов назад (до начала суток). Добавлена отрисовка "хвостовых" минутных цифр отправления/прибытия. Ошибка "наложения" цифр с предыдущей картинки исправлена. "Минутные цифры" можно отключить комбинацией клавиш Ctrl-m (Ctrl-M)
Важно! Не тестировалось функционирование совместно с Pult.exe! Особенной глючным может быть "перелом" суток.
| |
| |
V9 | Дата: Воскресенье, 30.06.2024, 08:33 | Сообщение # 200 |
Поездной диспетчер
Группа: Пользователи
Сообщений: 484
Награды: 9
Репутация: 0
Статус: Online
|
| |
| |
|