На синхронном сервере вы должны обрабатывать блокировки при доступе к вашим структурам данных (если имеются обновления), и это требует времени и кода (и является источником трудных для поиска ошибок). Кроме того, наличие множества (например, тысяч) потоков создает технические проблемы во многих реализациях (например, для выделения стека), и если сервер связан с вводом-выводом, эти потоки почти все спят (ожидают сеть) и просто тратят память.
Используя асинхронную модель в одном потоке, вы можете игнорировать проблему блокировки (это означает, что ваша обработка выполняется настолько быстро, насколько это возможно), и вы используете только ту память, которая фактически необходима для клиентов (имеется только один стек).
Однако теперь многоядерные машины довольно распространены, поэтому часть преимущества теряется (потому что вам придется блокироваться при изменении общей структуры данных). Вероятно, лучшую эффективность можно получить, используя балансировщик перед N асинхронными серверами, где N - оптимальное количество потоков для вашей среды.
Плохая сторона асинхронного подхода заключается в том, что в зависимости от ваших инструментов код может быть довольно уродливым и трудным для понимания, и что если вычисления не являются тривиальными и по ошибке ваша обработка входит в бесконечный цикл, весь асинхронный сервер будет не отвечать ( так что, вероятно, следует добавить сторожевой таймер).