Общие указатели и производительность

Взгляд cSounds и PureData.

8
задан Guest 12 October 2009 в 07:09
поделиться

7 ответов

Если ваше приложение передает около 700 байтов XML-сообщений, которые могут содержаться в 65-байтовых сообщениях протокола Google или 85-байтовых сообщениях ASN.1, то это, вероятно, не имеет значения. Но если он обрабатывает миллион чего-то в секунду, я бы не отказался от затрат на добавление 2 циклов полного чтения, модификации и записи (RMW) к передаче указателя.

Полная запись с изменением чтения занимает порядка 50 нс, поэтому два - 100 нс. Эта стоимость равна стоимости одного замка и одного замка - столько же, сколько и 2 CAS. Это половина резерва и выпуска критического раздела Windows. Это сравнивается с одним нажатием на один машинный цикл (400 секунд PICO на машине с частотой 2,5 ГГц)

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

Передача интеллектуальных указателей по константной ссылке почти ВСЕГДА является предпочтительной. Если вызываемый объект не создает новый совместно используемый указатель, когда он хочет гарантировать или контролировать время жизни указателя , то это ошибка вызываемого объекта . Волей-неволей передавать потокобезопасные интеллектуальные указатели с подсчетом ссылок по значению - это просто запрос на снижение производительности.

Использование указателей с подсчетом ссылок упрощает время жизни, без сомнения, но передавать общие указатели по значению, чтобы попытаться защитить от дефектов в вызываемый - полнейший вздор.

Чрезмерное использование подсчета ссылок может в короткие сроки превратить изящную программу, которая может обрабатывать 1 мм сообщений в секунду (mps), в толстую, которая обрабатывает 150k mps на том же оборудовании. Внезапно вам понадобится половина стойки серверов и 10000 долларов в год на электроэнергию.

13
ответ дан 3 November 2019 в 12:49
поделиться

Правильно ответить на этот вопрос с учетом данных практически невозможно. Единственный способ точно определить, что вызывает проблемы с производительностью в вашем приложении, - это запустить профилировщик программы и изучить выходные данные.

При этом очень маловероятно, что shared_ptr вызывает замедление. Тип shared_ptr и многие ранние отечественные варианты используются во все возрастающем количестве программ на C ++. Я сам использую их в своей работе (профессионально дома). Я потратил много времени на профилирование своих рабочих приложений, и shared_ptr никогда не был даже близко к проблеме в моем коде или любом другом коде, работающем в приложении. Гораздо более вероятно, что ошибка в другом месте.

10
ответ дан 3 November 2019 в 12:49
поделиться

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.

5
ответ дан 3 November 2019 в 12:49
поделиться

Общие указатели подсчитываются по ссылкам. В частности, когда вы используете многопоточность, увеличение и уменьшение счетчика ссылок может занять значительное время. Причина, по которой многопоточность здесь мешает, заключается в том, что , если вы передали общий указатель между потоками, счетчик ссылок в конечном итоге стал бы общим для этих потоков, поэтому любые манипуляции должны быть синхронизированы между потоками. Это может немного замедлить работу.

Редактировать: Для тех, кто заботится о том, насколько медленная блокировка потоков может выполнять некоторые довольно простые операции, см. Тестирование Херба Саттера с несколькими реализациями CoW Strings . Хотя его тестирование далеко от совершенства (например, он тестировал только в Windows), оно все же дает некоторое представление о том, какое замедление вы можете ожидать. Для большинства практических целей

4
ответ дан 3 November 2019 в 12:49
поделиться

Очень маловероятно - вам придется тратить большую часть своего времени на передачу указателей.

Влияние общих ptrs обычно незначительно, и трудно даже создать крайний случай, когда они станут проблемой (при условии правильной реализации и правильно оптимизирующего компилятора).

Влияние общего ptr:

  • увеличенный размер выделения.
    Это будет иметь значение, только если у вас есть много общих указателей на очень маленькие объекты (скажем, десятки миллионов shared_ptr ) и / или работают почти на пределе памяти. Существует небольшой потенциал для заметного снижения производительности, если дополнительные выделения превышают уровень кэша / NUMA во внутреннем цикле

  • увеличенное число выделений
    shared_ptr all покрывает объект отслеживания (счетчик ссылок, слабый счетчик и удаление) . Этого можно избежать, используя make_shared , помещая референт и объект отслеживания в одно выделение

  • подсчет ссылок
    увеличивает стоимость копии указателя. В однопоточном приложении вы заметите, что только из вас в любом случае тратит большую часть своего времени на копирование указателей. В многопоточном приложении вам все равно потребуется высокая конкуренция за одни и те же указатели.
    Во многих случаях можно избежать затрат на копирование, передав shared_ptr const & , например, в качестве аргумента функции.

  • разыменование
    Дополнительная стоимость разыменования равна нулю в сборке версии оптимизирующего компилятора. Сборки отладки часто приравниваются к вызовам функций и дополнительным проверкам NULL. Тем не менее, особенно в отладочных сборках, вам придется потратить большую часть времени на разыменование указателей, чтобы это изменило ситуацию.


Без дополнительной информации мы не сможем вам помочь. Вам необходимо описать, что такое «проблемы с производительностью» (общая медлительность, определенные операции, занимающие много времени, большое количество подкачки), и некоторые ключевые цифры - что делает ваше приложение, сколько там интеллектуальных указателей, как часто они копируются, и какие еще операции вы выполняете, не считая умных указателей.

Или вы научитесь использовать монитор производительности и / или профилировщик, чтобы выяснить, что вызывает замедление и есть ли определенные узкие места.

3
ответ дан 3 November 2019 в 12:49
поделиться

Не догадывайтесь о производительности: Профиль ваш код.

0
ответ дан 3 November 2019 в 12:49
поделиться

Одна вещь, которая может снизить производительность, - это чрезмерная передача shared_ptr в качестве параметров функции. Решением для этого будет передача ссылок на shared_ptr. Однако это микро-оптимизация, поэтому делайте это только тогда, когда это действительно необходимо

править: Если подумать об этом, есть более эффективные способы оптимизации:

  • При чрезмерной передаче указателя вы, вероятно, должны позволить объекту что-то делать вместо того, чтобы перетаскивать его.
  • Вы можете передать (const) ссылку на объект вместо указатель
  • передает ссылку на указатель, когда указатель необходимо изменить
1
ответ дан 3 November 2019 в 12:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: