Почему мой сервер работает отлично, когда упакован в инструмент командной строки, но не работает при запуске внутри NSApplication? - PullRequest
0 голосов
/ 16 мая 2019

Среда: macOS Mojave, 6-ядерный I7 Mac mini.

Я написал сервер ModBus, использующий LibModbus для обеспечения Modbus-логики, и GCD-файл-дескриптор-источник отправки для реализации логики сервера,

При запуске внутри простой цели командной строки, используя dispatch_main() в main.c, как рекомендовано, сервер работает отлично - легко обрабатывает непрерывные тысячи запросов ModBus в секунду.Внутреннее использование неблокирующих сокетов и SO_REUSEADDR позволяет серверу успешно перерабатывать один и тот же сокет бесконечно.Он практически не использует процессор и незначительную оперативную память.

Если я возьму точно того же исходного кода и вызову его в оболочке приложения NSApplication, он станет бесполезным pig , неспособным надежно обрабатывать десяткизапросов в секунду без удушья после 256 запросов (интересное число, но что это означает ?).В оболочке приложения больше ничего не происходит - его единственная задача - разместить сервер.

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

Чтобы подчеркнуть элементарную природу версии приложения, вот все содержимое файла AppDelegate.m:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{

    [self performSelectorOnMainThread: @selector(applicationDidBeginRunLoop:)
                           withObject: nil
                        waitUntilDone: NO
     ];
}

- (void) applicationDidBeginRunLoop: (id) ignored
{
    self.server = [GCDModbusSlave modbusSlave];
    [self.server run];
}

- а вот main () из версии инструмента:

int main(void)
{
    modbusSlave = [GCDModbusSlave modbusSlave];
    [modbusSlave run];
    dispatch_main();
}

Я надеюсь, что только что забыл что-то глупое, и я ищу хорошие вопросы.

1 Ответ

0 голосов
/ 23 мая 2019

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

Я вернулся и переписал серверный цикл, исключив вызовы ModBus и заменив простейший протокол сокетов, чтобы упростить структуру. У меня довольно скоро был сервер, который работал бы стабильно при скорости доступа 5K / сек и не отставал от потока запросов. На 10K не может идти в ногу, но все еще работает без проблем. Он работает практически без памяти и процессора при 5K.

Далее я подклассифицирую сервер для выполнения ModBus вместо элементарного протокола. Поскольку код библиотеки ModBus - просто vanilla C, без потоков или вызовов GCD, я надеюсь, что эта часть будет без происшествий.

...