У нас есть система обработки сообщения с высокопроизводительными требованиями. Недавно мы заметили, что первое сообщение берет много раз дольше затем последующие сообщения. Набор преобразования и увеличения сообщения происходит, поскольку это проходит нашу систему, большую часть сделанного посредством внешнего lib.
Я просто представил эту проблему (использующий callgrind), сравнив "выполнение" всего одного сообщения с "выполнением" многих сообщений (обеспечение базовой линии сравнения).
Основным различием, которое я вижу, является функция "do_lookup_x" приведение в рабочее состояние огромного количества времени. Смотря на различные вызовы к этой функции, их всех, кажется, называет общая функция: _dl_runtime_resolve. Не уверенный, что эта функция делает, но мне, это похоже в первый раз, когда различными общими библиотеками пользуется и затем загружает в в память ld.
Действительно ли это - корректное предположение? То, что двоичный файл не загрузит общие библиотеки в в память, пока они не будут прошедшими предварительную подготовку для использования, поэтому мы будем видеть крупное замедление на первом сообщении, но ни на одном из последующих?
Как мы идем о предотвращении этого?
Примечание: Мы воздействуем на масштаб микросекунды.
Из ld.so(8)
man page, ENVIRONMENT section:
LD_BIND_NOW
(libc5; glibc since 2.1.1) If set to a non-empty string, causes
the dynamic linker to resolve all symbols at program startup
instead of deferring function call resolution to the point when
they are first referenced. This is useful when using a debug-
ger.
Итак, LD_BIND_NOW=y ./timesensitiveapp
.
В качестве альтернативы предложению Игнасио Васкеса-Абрамса во время выполнения вы можете сделать то же самое во время компоновки. При компоновке общей библиотеки передайте компоновщику флаг -z now
.