Если ваше приложение передает около 700 байтов XML-сообщений, которые могут содержаться в 65-байтовых сообщениях протокола Google или 85-байтовых сообщениях ASN.1, то это, вероятно, не имеет значения. Но если он обрабатывает миллион чего-то в секунду, я бы не отказался от затрат на добавление 2 циклов полного чтения, модификации и записи (RMW) к передаче указателя.
Полная запись с изменением чтения занимает порядка 50 нс, поэтому два - 100 нс. Эта стоимость равна стоимости одного замка и одного замка - столько же, сколько и 2 CAS. Это половина резерва и выпуска критического раздела Windows. Это сравнивается с одним нажатием на один машинный цикл (400 секунд PICO на машине с частотой 2,5 ГГц)
. И это даже не включает другие затраты на признание недействительной строки кэша, которая фактически содержит счетчик, влияние блокировки шины на другие процессоры и т. д.
Передача интеллектуальных указателей по константной ссылке почти ВСЕГДА является предпочтительной. Если вызываемый объект не создает новый совместно используемый указатель, когда он хочет гарантировать или контролировать время жизни указателя , то это ошибка вызываемого объекта . Волей-неволей передавать потокобезопасные интеллектуальные указатели с подсчетом ссылок по значению - это просто запрос на снижение производительности.
Использование указателей с подсчетом ссылок упрощает время жизни, без сомнения, но передавать общие указатели по значению, чтобы попытаться защитить от дефектов в вызываемый - полнейший вздор.
Чрезмерное использование подсчета ссылок может в короткие сроки превратить изящную программу, которая может обрабатывать 1 мм сообщений в секунду (mps), в толстую, которая обрабатывает 150k mps на том же оборудовании. Внезапно вам понадобится половина стойки серверов и 10000 долларов в год на электроэнергию.
Правильно ответить на этот вопрос с учетом данных практически невозможно. Единственный способ точно определить, что вызывает проблемы с производительностью в вашем приложении, - это запустить профилировщик программы и изучить выходные данные.
При этом очень маловероятно, что shared_ptr вызывает замедление. Тип shared_ptr и многие ранние отечественные варианты используются во все возрастающем количестве программ на C ++. Я сам использую их в своей работе (профессионально дома). Я потратил много времени на профилирование своих рабочих приложений, и shared_ptr никогда не был даже близко к проблеме в моем коде или любом другом коде, работающем в приложении. Гораздо более вероятно, что ошибка в другом месте.
If your program appears to have a performance problem, it is perfectly natural to start guessing what the problem could be, but if you want to place a bet, it is almost 100% likely to be something else entirely. Profiling may find the problem. This is the method I use.
Общие указатели подсчитываются по ссылкам. В частности, когда вы используете многопоточность, увеличение и уменьшение счетчика ссылок может занять значительное время. Причина, по которой многопоточность здесь мешает, заключается в том, что , если вы передали общий указатель между потоками, счетчик ссылок в конечном итоге стал бы общим для этих потоков, поэтому любые манипуляции должны быть синхронизированы между потоками. Это может немного замедлить работу.
Редактировать: Для тех, кто заботится о том, насколько медленная блокировка потоков может выполнять некоторые довольно простые операции, см. Тестирование Херба Саттера с несколькими реализациями CoW Strings . Хотя его тестирование далеко от совершенства (например, он тестировал только в Windows), оно все же дает некоторое представление о том, какое замедление вы можете ожидать. Для большинства практических целей
Очень маловероятно - вам придется тратить большую часть своего времени на передачу указателей.
Влияние общих ptrs обычно незначительно, и трудно даже создать крайний случай, когда они станут проблемой (при условии правильной реализации и правильно оптимизирующего компилятора).
Влияние общего ptr:
увеличенный размер выделения.
Это будет иметь значение, только если у вас есть много общих указателей на очень маленькие объекты (скажем, десятки миллионов shared_ptr
) и / или работают почти на пределе памяти. Существует небольшой потенциал для заметного снижения производительности, если дополнительные выделения превышают уровень кэша / NUMA во внутреннем цикле
увеличенное число выделений
shared_ptr
all покрывает объект отслеживания (счетчик ссылок, слабый счетчик и удаление) .
Этого можно избежать, используя make_shared
, помещая референт и объект отслеживания в одно выделение
подсчет ссылок
увеличивает стоимость копии указателя. В однопоточном приложении вы заметите, что только из вас в любом случае тратит большую часть своего времени на копирование указателей. В многопоточном приложении вам все равно потребуется высокая конкуренция за одни и те же указатели.
Во многих случаях можно избежать затрат на копирование, передав shared_ptr
, например, в качестве аргумента функции.
разыменование
Дополнительная стоимость разыменования равна нулю в сборке версии оптимизирующего компилятора. Сборки отладки часто приравниваются к вызовам функций и дополнительным проверкам NULL. Тем не менее, особенно в отладочных сборках, вам придется потратить большую часть времени на разыменование указателей, чтобы это изменило ситуацию.
Без дополнительной информации мы не сможем вам помочь. Вам необходимо описать, что такое «проблемы с производительностью» (общая медлительность, определенные операции, занимающие много времени, большое количество подкачки), и некоторые ключевые цифры - что делает ваше приложение, сколько там интеллектуальных указателей, как часто они копируются, и какие еще операции вы выполняете, не считая умных указателей.
Или вы научитесь использовать монитор производительности и / или профилировщик, чтобы выяснить, что вызывает замедление и есть ли определенные узкие места.
Не догадывайтесь о производительности: Профиль ваш код.
Одна вещь, которая может снизить производительность, - это чрезмерная передача shared_ptr в качестве параметров функции. Решением для этого будет передача ссылок на shared_ptr. Однако это микро-оптимизация, поэтому делайте это только тогда, когда это действительно необходимо
править: Если подумать об этом, есть более эффективные способы оптимизации: