Хостинг серверов Minecraft playvds.com
  1. Вы находитесь в русском сообществе Bukkit. Мы - администраторы серверов Minecraft, разрабатываем собственные плагины и переводим на русский язык плагины наших собратьев из других стран.
    Dismiss Notice

Идея CPU Affinity

Discussion in 'Запросы на разработку плагинов' started by Reality_SC, Jan 13, 2016.

  1. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Trophy Points:
    123
    Имя в Minecraft:
    Reality_SC
    Все в курсе, что нынче все компы имеют по несколько параллельно работающих ядер.
    Чаще всего половина ядер это виртуальные процессоры (Intel Hyper-Threading), которые являются фронт-эндом к совместным логическим устройствам ядра.
    Примем в дальнейшем, что у нас всегда процессор с HT.

    Если HT отключить, 1 поток на рассматриваемом ядре будет идти со своей обычной скоростью 100%.

    Если HT включить, ядро сможет обрабатывать параллельно 2 потока, но при этом их суммарная производительность не будет выше 125% (личный опыт), Википедия пишет, что 115-130%. При этом отдельная задача на одном виртуальном процессоре работает медленнее (125%/2 = 62.5%). Это относится к случаю, когда на втором CPU этого же ядра работает ресурсоёмкая задача. Если её нет, то в общем-то грамотная микросхема переносит все силы на тот первый поток, который работает, и можно считать, что HT не работает для одного выделенного ядра.
    Конечно, в целом HT положительно влияет на работу многозадачной системы с кучей потоков.

    Серверу Minecraft всегда требовалась максимальная производительность, по крайней мере его основному циклу. С другой стороны, нельзя сказать, что сервера совсем однопоточные — сегодня лишь самый ленивый автор плагинов не использует параллельные потоки для того, чтобы выполнять какие-то вычисления.

    Отсюда встаёт задача: как эффективно распределить потоки по ядрам?

    Интуитивно, сразу напрашивается такая схема (на примере 2-ядерного/4-поточного CPU):
    1. ЯДРО:
      1. Для нужд ОС, других программ и параллельных потоков mc-сервера.
      2. Для нужд ОС, других программ и параллельных потоков mc-сервера.
    2. ЯДРО:
      1. Только для главного цикла mc-сервера.
      2. Никому.
    Предполагаю, что в такой ситуации сервер станет способен обрабатывать немного больше эвентов при тех же своих 20 TPS.

    Для достаточно частого случая 4-ядерного CPU (8 потоков) предлагаю также отдать ядро под серверный цикл, а остальные 3 ядра поделить по 3 потока на ОС и серверные параллельные потоки.

    Ко всему RuBukkit-у: имеют ли мои размышления достаточное основание, чтобы написать такой плагин? Или это заблуждение, и планировщик процессов уже всё сделал до меня?
    @HoShiMin @alexandrage @Shevchik @fromgate кто ещё? :)
    @MySt1k
    Может быть это уже кто-то делал у себя, тестировал, и может поделиться результатом?

    Предлагается накидать плагин, а в конфиге указывать две маски cpu affinity: для основного потока и для остальных потоков текущего процесса Java. OpenHFT в помощь, возможно есть другие библиотеки.
    Предположить, что остальные процессы займут остальные ядра. Можно, конечно, заморочиться, и пройтись по всем остальным процессам и выставить им третью маску, но я хз как это сделать под Linux, под Windows вроде как легко, достаточно иметь админские права.
     
    Last edited: Jan 13, 2016
  2. Хостинг MineCraft
    <
  3. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Ты забыл про GC и про то что Netty использует свой пул потоков. В итоге потоков больше чем ядер полюбому. Так что смысл есть. С другой стороны есть куча потоков которым нужны ядра, и их ограничивать плохо.
    Так что ожно попробовать, но может так оказаться что просядет сеть и будет высокий пинг у всех, либо просядет GC и JVM будет встревать надолго пытаясь вычистить память. Это всё надо проверять на практике для многих разных конфигураций.
    Но в принципе при 4 реальных ядах на 1 сервер пруфит должен быть. (При условии использования G1GC, либо хорошо затвиканного CMSGC).
    Короче пойду чейчас набросаю, а дальше посмотрим как оно получится.
    UPD: Библиотеку пришлось сильно порезать из-за ограничений накладываемых на плагины баккитом, но работать будет,

    P.S. Раз уж заговорили о системных твиках, то стоит упомянуть что в Linux есть ещё и файловый кэш и имеет смысл загонять туда все файлы из папки plugins, а также world/playerdata. Вот это реально помогает.
     
    Last edited: Jan 13, 2016
  4. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Trophy Points:
    123
    Имя в Minecraft:
    Reality_SC
    Для теста по-хорошему нужен сервер, где из-за нагруженности tps меньше 20, чтобы можно было вычислить профит. Я не представляю пока, как замерить прирост скорости, если tps и до и после равен 20 :)[DOUBLEPOST=1452675919,1452675549][/DOUBLEPOST]
    Как вариант для четырёх ядер:
    CPU 0/1/2/3/4/5 — всем потокам кроме главного, маска 00111111b, 0x37.
    CPU 6 — только главному циклу, маска 01000000b, 0x40.
    CPU 7 — никому.
    При допущении, что на машине нет MySQL или чего-то такого объёмного, а только сервер, должен быть профит.
    Code:
    for(Thread thread : Thread.getAllStackTraces().keySet()) /* выставить всем 0x37 */
    ...
    /* выставить Thread.currentThread 0x40 */
    
     
  5. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    А если у сервера > 20 тпс, то значит у главного потока есть время спать, что значит мы отбираем доступную мощность и других потоков.
     
  6. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Trophy Points:
    123
    Имя в Minecraft:
    Reality_SC
    Главное, чтобы остальным хватало ядер, что при суммарных 4 (реальных) вполне правда.
     
  7. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    У OpenHFT немного другой апи позволяющий локнуть тред к ядру. Так что достаточно вызвать 1 функцию.

    Но при меньше чем 4х ядерном процессоре все это не имеет смысла. На 2х ядрах ни один из сборщиков мусора не вытягивает сервер без огромных задержек на остановку jvm. Впрочем у двухядерников начиная с 1.8 все итак плохо.
     
    Last edited: Jan 13, 2016
  8. Автор темы
    Reality_SC

    Reality_SC Старожил Пользователь

    Trophy Points:
    123
    Имя в Minecraft:
    Reality_SC
    Насчёт опытного образца, ты попробуешь?
     
  9. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Уже запилил сейчас тестирую. Пришлось поменять немного вещйе в библиотеке правда, но в общем работает (1 ядро остаётся не нагруженным пока сервер работает что бы я не делал снаружи). На локальном компе естественно разницы нет ибо 1 игрок нагрузки никакой не даёт. Осталось только как-то замерить пруфит от этого, поставлю ближе к вечеру на сервер и посмотрим как оно себя поведёт.

    P.S. HT - полная шняга, потому что когда нагрузка падаёт на одно виртуальное ядро, то оно не выдаёт столько же как оно же, но без HT, хрен его знает почему. Походу при 4х и больше реальных ядрах HT только мешает.
     
    Last edited: Jan 13, 2016
  10. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Надо использовать по 2 потока на 1 задачу, тогда и есть прирост.(~20%)
     
  11. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Это понятно, я говорю про то что со включённым HT, одно из логических ядер не жмёт столько же как если бы HT был отключён (Логическое ядро выброшено из шедулера чтобы оно точно не использовалось). Возможно дело в TurboBoost, надо будет замерить как TurboBoost работает с HyperThreading.[DOUBLEPOST=1452689127,1452688891][/DOUBLEPOST]Кстати над TurboBoost тоже покурить, у кого ядер много, тому точно будет выгоднее одно вырубить, чтобы другое к которому привязан главный поток работало быстрее.
     
  12. Larin

    Larin Старожил Пользователь

    Trophy Points:
    103
    Зачем так окостыляться? Просто подождём, когда jeb перепишет сервер(если перепишет).
     
  13. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Ага...
     
  14. GoodCoder

    GoodCoder Активный участник Пользователь

    Trophy Points:
    76
    Очень сомневаюсь, если они даже хотя бы миры распараллелить не могут... Приходится извращаться с bungee.
     
  15. Dereku

    Dereku Старожил

    Trophy Points:
    173
    Skype:
    derek_unavailable
    Имя в Minecraft:
    _Dereku
    Быстрее я с нуля напишу сервер, чем джеб напишет годный сервер.[DOUBLEPOST=1452717767,1452717684][/DOUBLEPOST]
    Не нужно. Ощутимого профита не выйдет в любом случае.
     
  16. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Основная проблема то что надо добавлять параметры в ядро чтобы можно было заизолировать CPU (чтобы его не пытались использовать другие процессы), а это не очень удобно хотелось бы всё-таки чтобы плагин можно было поставить и забыть.
    Можно конечно поллить все процессы в системе, и выставлять им affinity, но это глупо, но придётся так делать. Но тут ещё одна проблема, без рута можно выставить affinity только процессам которые были запущены пользователем.[DOUBLEPOST=1452748737,1452737001][/DOUBLEPOST]Ну вот короче написал, работает только на Linux 64bit.
    Сам по себе при запуске в качестве плагина локает главный поток сервера на указанное в конфиге ядро, но другие потоки всё ещё могут использовать это ядро. Для того чтобы этого избежать перед запуском сервер надо просто запустить этот джарник, как самый обычный джарник, но от рута. В качестве аргументов надо передать номер ядра которое вы хотите отобрать у всех потоков, при этом все остальные ядра буду возвращены. Если аргументы не указать то все ядра снова станут доступны всем потокам. Пример:
    Code:
    sudo java -jar MainThreadAffinity.jar 5
    - отбирает ядро номер 5 у всех потоков.

    Осталось только протестировать всё это, как в режиме я просто залочил главный поток на определённое ядро, так и в режиме я отдал всё ядро главному потоку.

    https://dl.dropboxusercontent.com/u/71299154/MainThreadAffinity.jar
     
    Last edited: Jan 14, 2016
  17. slavik123123123

    slavik123123123 Старожил Пользователь

    Trophy Points:
    143
    Имя в Minecraft:
    Leymooooooooooo
    В воскресенье протестим. 50+ плагинов. 70+ онлайн.
    Токо я не понял. Это плагин или приложение?
    Или то и то?
    Тоесть я должен закинуть это в плагины и создать отдельный скрин для java -jar ..... ... 5?
     
  18. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    И то и то. Должен и запихнуть как плагин, и запустить ка приложение, но как приложение его держать не обязательно, достаточно просто один раз запустить с нужными параметрами.[DOUBLEPOST=1452791560,1452784087][/DOUBLEPOST]Обновил джарник, чуть-чуть переделал внтуреннюю структуру чтобы было легче добавлять поддержку других OS. (Хотя лично я добавлять не буду, но другие смогут когда выложу на гитхаб).
     
  19. GoodCoder

    GoodCoder Активный участник Пользователь

    Trophy Points:
    76
    Неплохо было бы в плагин добавить опцию, позволяющую указать, на каких ядрах процессора будут выполняться все остальные потоки (ну все кроме "Server Thread") процесса. Мне не хочется ставить ограничение для системных процессов, да и нагрузка на процессор на них копеечная. Также это будет полезно тем, у кого нет root доступа.

    Ещё хотелось бы узнать, какие ядра у процессора с Hyper-Threading виртуальные, а какие физические (чётные/нечётные или первые/вторые 4 потока). Не хотелось бы чтобы два сервера работали на одном физическом ядре.
     
  20. Shevchik

    Shevchik Старожил Пользователь

    Trophy Points:
    173
    Имя в Minecraft:
    _Shevchik_
    Как повезёт, маппится ядра с HT могут по разному, так что лучше его отключить. Насчёт остальных потоков - подумаю что можно сделать. Сделаю чтобы в конфиге можно было памить главный поток, дефолт для всех остальных, и возможность настроить по имени потока.[DOUBLEPOST=1452806463,1452797397][/DOUBLEPOST]Нет, всё-таки не будет такой возможности, слишком много гемора в вытаскивании нативных айдишников потоков из жаба потоков так что только так пока-что.
     
  21. slavik123123123

    slavik123123123 Старожил Пользователь

    Trophy Points:
    143
    Имя в Minecraft:
    Leymooooooooooo
    [​IMG]
    И какое ядро блокировать?
    И будет ли робить на Debian 8 x64?
     

Share This Page