Некоторые факторы, чтобы добавить к превосходному совету Джереми:
1) Передача по значению работает только эффективно для небольших сообщений. Если у данных есть неиспользуемая область [кеш-строки] в начале, чтобы избежать ложного обмена, вы уже приближаетесь к размеру, где более эффективная передача по ссылке.
2) Большие очереди означают большее пространство, занятое очередями, влияющее на использование памяти.
3) Копирование данных в/из больших структур очереди требует времени. Помимо фактического использования ЦП при перемещении данных, очередь остается заблокированной во время копирования. Это увеличивает конкуренцию в очереди и приводит к общему результату, зависящему от ширины очереди. Если в вашем коде есть какой-либо тупиковый потенциал, сохранение блокировок на длительные периоды не поможет.
4) Передача по значению имеет тенденцию приводить к коду, специфичному для размера данных, т.е. фиксируется во время компиляции. Помимо неприятного заражения шаблонами, это очень затрудняет настройку размеров буфера и т. Д. Во время выполнения.
5) Если сообщения передаются по ссылке и malloced/freed/newed/disposed/GC'd, это может привести к чрезмерному соперничеству с менеджером памяти и частым, расточительным GC. Обычно я использую фиксированные пулы сообщений, выделяемых при запуске, в частности, чтобы избежать этого.
6) Обработка байтовых потоков может быть неудобной при передаче по ссылке. Если байт-поток характеризуется частыми поставками одиночных байтов, передача по ссылке является разумной только в том случае, если байты чередуются. Это может привести к необходимости тайм-аутов для обеспечения своевременного отправки частично заполненных сообщений в следующий поток. Это приводит к осложнениям и задержкам.
7) Конструкции с перекрестными ссылками, по своей природе, скорее всего, будут протекать. Это может привести к увеличению времени тестирования и передозировки на valgrind - особенно болезненной зависимости (еще одна причина, по которой я использую пулы объектов фиксированного размера).
8) Комплексные сообщения, например. те, которые содержат ссылки на другие объекты, могут вызвать ужасающие проблемы с владением и пожизненным управлением, если они передаются по значению. Пример. Объект сокета сервера имеет ссылку на объект списка буфера, содержащий массив буферов-экземпляров разного размера (реальный пример с сервера IOCP). Попробуйте передать это значение.
9) Многие вызовы ОС не могут обрабатывать ничего, кроме указателя. Вы не можете PostMessage (это Windows API, для всех вас счастливы), даже 256-байтовая структура по стоимости с одним вызовом (у вас есть только 2 wParam, lParam целые числа). Вызовы, которые настраивают асинхронные обратные вызовы, часто позволяют передавать «контекстные данные» на обратный вызов - почти всегда только один указатель.Любое приложение, которое собирается использовать такую функциональность ОС, почти вынуждено прибегать к использованию по ссылке.
Что архитектуры вы используете? SMP, NUMA, кластер? – Tudor
У меня сейчас нет проблемы, которую я сейчас решаю, но если бы я был, я бы нацелился на систему SMP + NUMA. – Bengie
Я думаю, что единственный достаточный короткий ответ на эти вопросы: «Это зависит от вас», и единственный достаточный более длинный ответ на эти вопросы: «Оцените различные варианты вашей целевой системы и посмотрите, какую производительность вы получите за каждую ». Производительность зависит так много (и часто контр-интуитивно) от архитектурных деталей системы, на которой вы будете работать, что существует не так много общих правил, которые могли бы надежно применяться в разных системах. Разумеется, вы не должны доверять никакому полученному вами ответу, даже не измеряя его в своем приложении. –