Skip to content

gh-161467: Enable __attribute__((hot)) for Clang - #161468

Merged
StanFromIreland merged 5 commits into
python:mainfrom
chenshanzhi:enable-hot-attr-for-clang
Nov 9, 2026
Merged

StanFromIreland merged 5 commits into
python:mainfrom
chenshanzhi:enable-hot-attr-for-clang

Conversation

@chenshanzhi

@chenshanzhi chenshanzhi commented Nov 6, 2026 •

Copy link
Copy Markdown
Contributor

The history of compiler support for the relevant features is as follows.

Therefore, __attribute__((hot)) is not enabled when building CPython with Clang's default configuration. And we can use _Py__has_attribute(hot) or GCC version >= 4.3 to determine whether the hot attribute is supported, and enable this attribute for Clang and other compilers that support it.

The history of compiler support for the relevant features is as follows.
* GCC introduced `__attribute__((hot))` in GCC 4.3.0.
  * https://gcc.gnu.org/pipermail/gcc-patches/2017-July/478580.html
* GCC has supported for `__has_attribute()` since GCC 5.
  * https://gcc.gnu.org/gcc-5/changes.html
* Clang has supported `__attribute__((hot))` since Clang 3.2.
  * llvm/llvm-project@29c2b43
* Clang has supported `__has_attribute()` since Clang 2.9.
  * llvm/llvm-project@274a70e
* By default, Clang defines `__GNUC__` as 4, `__GNUC_MINOR__` as 2, and
  `__GNUC_PATCHLEVEL__` as 1.
  * llvm/llvm-project#99804

Therefore, `__attribute__((hot))` is not enabled when building CPython
with Clang's default configuration. And we can use
`_Py__has_attribute(hot)` or `GCC version >= 4.3` to determine whether
the hot attribute is supported, and enable this attribute for Clang and
other compilers that support it.
@python-cla-bot

python-cla-bot Bot commented Nov 6, 2026 •

Copy link
Copy Markdown

All commit authors signed the Contributor License Agreement.

CLA signed

@bedevere-app

bedevere-app Bot commented Nov 6, 2026

Copy link
Copy Markdown

Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool.

If this change has little impact on Python users, wait for a maintainer to apply the skip news label instead.

@StanFromIreland

Copy link
Copy Markdown
Member

Can you please show PyPerformance changes with this, both on a release build and on a PGO build?

@bedevere-app bedevere-app Bot added the type-feature A feature request or enhancement label Nov 6, 2026
Comment thread Include/pyport.h Outdated
Comment on lines 314 to 319

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

GCC 5 was releasesd 11 years, IMO it's ok to drop this optimization on GCC 5 which shouldn't be used in the wild anymore. So I suggest to simplify the code (and add indentation for readability):

Suggested change
#if _Py__has_attribute(hot)
# define _Py_HOT_FUNCTION __attribute__((hot))
#else
# define _Py_HOT_FUNCTION
#endif

Note: I'm the one who added _Py_HOT_FUNCTION to Python a few years ago :-)

@vstinner

vstinner commented Nov 6, 2026

Copy link
Copy Markdown
Member

Can you please show PyPerformance changes with this, both on a release build and on a PGO build?

When using PGO, __attribute__((hot)) is not really interesting (I think that the compiler can ignore it, but I'm not sure).

I'm not sure that __attribute__((hot)) has a major impact on performance. I added it but later, I mostly relied on PGO when I really wanted to measure performance and test an optimization.

__attribute__((hot)) helps a little bit for quick & dirty benchmark session using ./configure (gcc -O3).

@StanFromIreland

Copy link
Copy Markdown
Member

The comment above says:

Issue #28618: This attribute must not be abused, otherwise it can have a negative effect on performance.

We don't know how Clang will behave/optimise, so I think we should be cautious and verify there is no regression before merging.

Comment thread Include/pyport.h Outdated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While you're here, can you update the issue number to issue gh-72804 please? See: #72804

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Addressed in 029c063

- Drop this optimization for GCC versions earlier than GCC5
- Update the issue number in comments
@chenshanzhi

Copy link
Copy Markdown
Contributor Author

Can you please show PyPerformance changes with this, both on a release build and on a PGO build?

Hi, I conducted the tests on an x86 PC. The results for default builds are shown below.

performance-default-baseline.json
performance-default-pr161468.json

performance-default-baseline-round2.json
performance-default-pr161468-round2.json

Note: For the results in xxx-round2.json, I originally intended to test the results of PGO+LTO. However, I just realized that I forgot to add the --enable-optimizations --with-lto option to the execution script, so the results actually still reflect a comparison of default builds.

Comparison of Default Builds (Round 1)

cs@cs-linux:~/src/PyPerformanceTest$ ~/python-venv/bin/pyperformance compare performance-default-baseline.json performance-default-pr161468.json
performance-default-baseline.json
=================================

Performance version: 1.14.0
Report on Linux-6.14.0-27-generic-x86_64-with-glibc2.39
Number of logical CPUs: 20
Start date: 2026-11-07 01:40:02.256192
End date: 2026-11-07 02:25:03.438141

performance-default-pr161468.json
=================================

Performance version: 1.14.0
Report on Linux-6.14.0-27-generic-x86_64-with-glibc2.39
Number of logical CPUs: 20
Start date: 2026-11-07 02:34:41.025590
End date: 2026-11-07 03:19:17.015934

### 2to3 ###
Mean +- std dev: 166 ms +- 3 ms -> 164 ms +- 3 ms: 1.01x faster
Not significant

### ascii85_large ###
Mean +- std dev: 11.3 ms +- 0.0 ms -> 11.3 ms +- 0.0 ms: 1.00x slower
Not significant

### ascii85_small ###
Mean +- std dev: 434 us +- 2 us -> 452 us +- 2 us: 1.04x slower
Significant (t=-45.08)

### async_generators ###
Mean +- std dev: 163 ms +- 2 ms -> 164 ms +- 2 ms: 1.00x slower
Not significant

### async_tree_cpu_io_mixed ###
Mean +- std dev: 327 ms +- 7 ms -> 329 ms +- 7 ms: 1.01x slower
Not significant

### async_tree_cpu_io_mixed_tg ###
Mean +- std dev: 341 ms +- 5 ms -> 343 ms +- 5 ms: 1.01x slower
Not significant

### async_tree_eager ###
Mean +- std dev: 64.8 ms +- 0.5 ms -> 65.1 ms +- 0.5 ms: 1.01x slower
Not significant

### async_tree_eager_cpu_io_mixed ###
Mean +- std dev: 262 ms +- 4 ms -> 262 ms +- 4 ms: 1.00x faster
Not significant

### async_tree_eager_cpu_io_mixed_tg ###
Mean +- std dev: 305 ms +- 7 ms -> 306 ms +- 7 ms: 1.00x slower
Not significant

### async_tree_eager_io ###
Mean +- std dev: 415 ms +- 6 ms -> 417 ms +- 6 ms: 1.00x slower
Not significant

### async_tree_eager_io_tg ###
Mean +- std dev: 436 ms +- 24 ms -> 441 ms +- 24 ms: 1.01x slower
Not significant

### async_tree_eager_memoization ###
Mean +- std dev: 148 ms +- 3 ms -> 148 ms +- 4 ms: 1.00x slower
Not significant

### async_tree_eager_memoization_tg ###
Mean +- std dev: 196 ms +- 8 ms -> 197 ms +- 8 ms: 1.01x slower
Not significant

### async_tree_eager_tg ###
Mean +- std dev: 154 ms +- 6 ms -> 155 ms +- 6 ms: 1.01x slower
Not significant

### async_tree_io ###
Mean +- std dev: 424 ms +- 7 ms -> 428 ms +- 7 ms: 1.01x slower
Not significant

### async_tree_io_tg ###
Mean +- std dev: 436 ms +- 12 ms -> 439 ms +- 12 ms: 1.01x slower
Not significant

### async_tree_memoization ###
Mean +- std dev: 223 ms +- 8 ms -> 225 ms +- 8 ms: 1.01x slower
Not significant

### async_tree_memoization_tg ###
Mean +- std dev: 225 ms +- 4 ms -> 226 ms +- 4 ms: 1.01x slower
Not significant

### async_tree_none ###
Mean +- std dev: 174 ms +- 6 ms -> 175 ms +- 6 ms: 1.01x slower
Not significant

### async_tree_none_tg ###
Mean +- std dev: 179 ms +- 8 ms -> 180 ms +- 8 ms: 1.01x slower
Not significant

### asyncio_tcp ###
Mean +- std dev: 218 ms +- 11 ms -> 202 ms +- 7 ms: 1.08x faster
Significant (t=9.86)

### asyncio_tcp_ssl ###
Mean +- std dev: 920 ms +- 4 ms -> 919 ms +- 3 ms: 1.00x faster
Not significant

### asyncio_websockets ###
Mean +- std dev: 234 ms +- 4 ms -> 234 ms +- 4 ms: 1.00x faster
Not significant

### base16_large ###
Mean +- std dev: 3.40 ms +- 0.01 ms -> 3.40 ms +- 0.01 ms: 1.00x faster
Not significant

### base16_small ###
Mean +- std dev: 231 us +- 4 us -> 233 us +- 1 us: 1.01x slower
Not significant

### base32_large ###
Mean +- std dev: 1.61 ms +- 0.01 ms -> 1.60 ms +- 0.01 ms: 1.00x faster
Not significant

### base32_small ###
Mean +- std dev: 171 us +- 2 us -> 174 us +- 1 us: 1.02x slower
Not significant

### base64_large ###
Mean +- std dev: 1.47 ms +- 0.01 ms -> 1.47 ms +- 0.00 ms: 1.00x slower
Not significant

### base64_small ###
Mean +- std dev: 194 us +- 1 us -> 196 us +- 1 us: 1.01x slower
Not significant

### base85_large ###
Mean +- std dev: 4.48 ms +- 0.02 ms -> 4.50 ms +- 0.02 ms: 1.00x slower
Not significant

### base85_small ###
Mean +- std dev: 175 us +- 1 us -> 180 us +- 1 us: 1.03x slower
Significant (t=-31.70)

### bench_mp_pool ###
Mean +- std dev: 101 ms +- 62 ms -> 114 ms +- 122 ms: 1.12x slower
Not significant

### bench_thread_pool ###
Mean +- std dev: 2.39 ms +- 0.14 ms -> 2.44 ms +- 0.08 ms: 1.02x slower
Significant (t=-2.40)

### bpe_tokeniser ###
Mean +- std dev: 2.72 sec +- 0.01 sec -> 2.72 sec +- 0.01 sec: 1.00x faster
Not significant

### chameleon ###
Mean +- std dev: 5.99 ms +- 0.04 ms -> 5.98 ms +- 0.04 ms: 1.00x faster
Not significant

### chaos ###
Mean +- std dev: 33.9 ms +- 0.2 ms -> 34.2 ms +- 0.2 ms: 1.01x slower
Not significant

### comprehensions ###
Mean +- std dev: 9.68 us +- 0.03 us -> 9.43 us +- 0.03 us: 1.03x faster
Significant (t=42.63)

### coroutines ###
Mean +- std dev: 11.9 ms +- 0.0 ms -> 12.0 ms +- 0.0 ms: 1.02x slower
Not significant

### create_gc_cycles ###
Mean +- std dev: 1.10 ms +- 0.00 ms -> 1.10 ms +- 0.01 ms: 1.00x slower
Not significant

### crypto_pyaes ###
Mean +- std dev: 44.0 ms +- 0.1 ms -> 44.4 ms +- 0.4 ms: 1.01x slower
Not significant

### deepcopy ###
Mean +- std dev: 146 us +- 1 us -> 145 us +- 1 us: 1.01x faster
Not significant

### deepcopy_memo ###
Mean +- std dev: 15.4 us +- 0.1 us -> 15.2 us +- 0.1 us: 1.02x faster
Not significant

### deepcopy_reduce ###
Mean +- std dev: 1.71 us +- 0.01 us -> 1.69 us +- 0.01 us: 1.01x faster
Not significant

### deltablue ###
Mean +- std dev: 1.74 ms +- 0.01 ms -> 1.74 ms +- 0.01 ms: 1.00x slower
Not significant

### django_template ###
Mean +- std dev: 22.6 ms +- 0.2 ms -> 22.9 ms +- 0.3 ms: 1.01x slower
Not significant

### docutils ###
Mean +- std dev: 1.42 sec +- 0.01 sec -> 1.42 sec +- 0.01 sec: 1.00x faster
Not significant

### dulwich_log ###
Mean +- std dev: 30.5 ms +- 0.3 ms -> 30.4 ms +- 0.3 ms: 1.00x faster
Not significant

### fannkuch ###
Mean +- std dev: 232 ms +- 1 ms -> 225 ms +- 1 ms: 1.03x faster
Significant (t=57.62)

### fastapi_http ###
Mean +- std dev: 170 ms +- 1 ms -> 168 ms +- 1 ms: 1.01x faster
Not significant

### float ###
Mean +- std dev: 42.3 ms +- 0.7 ms -> 41.7 ms +- 0.7 ms: 1.01x faster
Not significant

### gc_traversal ###
Mean +- std dev: 2.50 ms +- 0.02 ms -> 2.50 ms +- 0.03 ms: 1.00x faster
Not significant

### generators ###
Mean +- std dev: 17.4 ms +- 0.1 ms -> 17.6 ms +- 0.2 ms: 1.01x slower
Not significant

### go ###
Mean +- std dev: 61.9 ms +- 0.3 ms -> 62.3 ms +- 0.2 ms: 1.01x slower
Not significant

### hexiom ###
Mean +- std dev: 3.24 ms +- 0.01 ms -> 3.22 ms +- 0.01 ms: 1.00x faster
Not significant

### html5lib ###
Mean +- std dev: 34.9 ms +- 1.7 ms -> 35.0 ms +- 1.7 ms: 1.00x slower
Not significant

### json_dumps ###
Mean +- std dev: 5.90 ms +- 0.02 ms -> 5.97 ms +- 0.04 ms: 1.01x slower
Not significant

### json_loads ###
Mean +- std dev: 18.7 us +- 0.1 us -> 18.7 us +- 0.1 us: 1.00x slower
Not significant

### logging_format ###
Mean +- std dev: 3.78 us +- 0.03 us -> 3.79 us +- 0.05 us: 1.00x slower
Not significant

### logging_silent ###
Mean +- std dev: 53.9 ns +- 0.3 ns -> 53.9 ns +- 0.2 ns: 1.00x slower
Not significant

### logging_simple ###
Mean +- std dev: 3.36 us +- 0.03 us -> 3.36 us +- 0.02 us: 1.00x faster
Not significant

### mako ###
Mean +- std dev: 6.71 ms +- 0.07 ms -> 6.64 ms +- 0.09 ms: 1.01x faster
Not significant

### many_optionals ###
Mean +- std dev: 463 us +- 3 us -> 459 us +- 3 us: 1.01x faster
Not significant

### mdp ###
Mean +- std dev: 751 ms +- 4 ms -> 743 ms +- 4 ms: 1.01x faster
Not significant

### meteor_contest ###
Mean +- std dev: 66.8 ms +- 0.2 ms -> 67.0 ms +- 0.2 ms: 1.00x slower
Not significant

### nbody ###
Mean +- std dev: 51.2 ms +- 0.4 ms -> 50.3 ms +- 0.7 ms: 1.02x faster
Not significant

### nqueens ###
Mean +- std dev: 48.7 ms +- 0.2 ms -> 49.2 ms +- 0.3 ms: 1.01x slower
Not significant

### pathlib ###
Mean +- std dev: 8.67 ms +- 0.05 ms -> 8.61 ms +- 0.04 ms: 1.01x faster
Not significant

### pickle ###
Mean +- std dev: 6.66 us +- 0.04 us -> 6.70 us +- 0.15 us: 1.01x slower
Not significant

### pickle_dict ###
Mean +- std dev: 18.2 us +- 0.1 us -> 18.1 us +- 0.1 us: 1.00x faster
Not significant

### pickle_list ###
Mean +- std dev: 3.01 us +- 0.02 us -> 2.98 us +- 0.03 us: 1.01x faster
Not significant

### pickle_pure_python ###
Mean +- std dev: 194 us +- 2 us -> 196 us +- 3 us: 1.01x slower
Not significant

### pidigits ###
Mean +- std dev: 130 ms +- 0 ms -> 131 ms +- 0 ms: 1.00x slower
Not significant

### pprint_pformat ###
Mean +- std dev: 972 ms +- 4 ms -> 980 ms +- 4 ms: 1.01x slower
Not significant

### pprint_safe_repr ###
Mean +- std dev: 477 ms +- 2 ms -> 478 ms +- 2 ms: 1.00x slower
Not significant

### pyflate ###
Mean +- std dev: 225 ms +- 2 ms -> 221 ms +- 2 ms: 1.02x faster
Not significant

### python_startup ###
Mean +- std dev: 13.1 ms +- 2.0 ms -> 13.0 ms +- 1.8 ms: 1.01x faster
Not significant

### python_startup_no_site ###
Mean +- std dev: 10.4 ms +- 2.4 ms -> 10.9 ms +- 2.2 ms: 1.05x slower
Significant (t=-2.29)

### raytrace ###
Mean +- std dev: 157 ms +- 1 ms -> 157 ms +- 1 ms: 1.00x slower
Not significant

### regex_compile ###
Mean +- std dev: 89.7 ms +- 0.4 ms -> 89.5 ms +- 0.3 ms: 1.00x faster
Not significant

### regex_dna ###
Mean +- std dev: 120 ms +- 1 ms -> 121 ms +- 1 ms: 1.00x slower
Not significant

### regex_effbot ###
Mean +- std dev: 1.84 ms +- 0.10 ms -> 1.81 ms +- 0.01 ms: 1.02x faster
Not significant

### regex_v8 ###
Mean +- std dev: 13.7 ms +- 0.1 ms -> 13.7 ms +- 0.0 ms: 1.01x faster
Not significant

### richards ###
Mean +- std dev: 26.0 ms +- 0.2 ms -> 26.0 ms +- 0.1 ms: 1.00x faster
Not significant

### richards_super ###
Mean +- std dev: 30.0 ms +- 0.1 ms -> 30.0 ms +- 0.1 ms: 1.00x slower
Not significant

### scimark_fft ###
Mean +- std dev: 177 ms +- 0 ms -> 172 ms +- 1 ms: 1.03x faster
Significant (t=47.95)

### scimark_lu ###
Mean +- std dev: 64.2 ms +- 1.4 ms -> 62.2 ms +- 1.0 ms: 1.03x faster
Significant (t=9.13)

### scimark_monte_carlo ###
Mean +- std dev: 36.4 ms +- 0.3 ms -> 37.5 ms +- 0.1 ms: 1.03x slower
Significant (t=-24.04)

### scimark_sor ###
Mean +- std dev: 63.9 ms +- 0.2 ms -> 64.9 ms +- 1.0 ms: 1.02x slower
Not significant

### scimark_sparse_mat_mult ###
Mean +- std dev: 2.93 ms +- 0.01 ms -> 2.88 ms +- 0.01 ms: 1.02x faster
Not significant

### spectral_norm ###
Mean +- std dev: 53.0 ms +- 0.2 ms -> 51.7 ms +- 0.1 ms: 1.02x faster
Significant (t=47.83)

### sphinx ###
Mean +- std dev: 603 ms +- 24 ms -> 603 ms +- 24 ms: 1.00x faster
Not significant

### sqlglot_v2_normalize ###
Mean +- std dev: 66.5 ms +- 0.4 ms -> 67.0 ms +- 0.3 ms: 1.01x slower
Not significant

### sqlglot_v2_optimize ###
Mean +- std dev: 32.7 ms +- 0.2 ms -> 32.9 ms +- 0.2 ms: 1.00x slower
Not significant

### sqlglot_v2_parse ###
Mean +- std dev: 693 us +- 6 us -> 685 us +- 6 us: 1.01x faster
Not significant

### sqlglot_v2_transpile ###
Mean +- std dev: 874 us +- 4 us -> 870 us +- 5 us: 1.00x faster
Not significant

### subparsers ###
Mean +- std dev: 5.80 ms +- 0.08 ms -> 5.83 ms +- 0.07 ms: 1.01x slower
Not significant

### sympy_expand ###
Mean +- std dev: 295 ms +- 1 ms -> 293 ms +- 1 ms: 1.01x faster
Not significant

### sympy_integrate ###
Mean +- std dev: 12.1 ms +- 0.1 ms -> 12.0 ms +- 0.1 ms: 1.00x faster
Not significant

### sympy_str ###
Mean +- std dev: 171 ms +- 2 ms -> 170 ms +- 1 ms: 1.00x faster
Not significant

### sympy_sum ###
Mean +- std dev: 86.6 ms +- 0.6 ms -> 86.3 ms +- 0.7 ms: 1.00x faster
Not significant

### telco ###
Mean +- std dev: 88.7 ms +- 0.5 ms -> 87.7 ms +- 0.4 ms: 1.01x faster
Not significant

### tomli_loads ###
Mean +- std dev: 1.15 sec +- 0.01 sec -> 1.13 sec +- 0.02 sec: 1.02x faster
Not significant

### tornado_http ###
Mean +- std dev: 71.6 ms +- 1.6 ms -> 71.9 ms +- 1.7 ms: 1.00x slower
Not significant

### typing_runtime_protocols ###
Mean +- std dev: 75.0 us +- 1.1 us -> 74.3 us +- 1.0 us: 1.01x faster
Not significant

### unpack_sequence ###
Mean +- std dev: 21.9 ns +- 0.2 ns -> 20.0 ns +- 0.1 ns: 1.10x faster
Significant (t=82.56)

### unpickle ###
Mean +- std dev: 8.82 us +- 0.07 us -> 8.86 us +- 0.06 us: 1.00x slower
Not significant

### unpickle_list ###
Mean +- std dev: 2.67 us +- 0.02 us -> 2.66 us +- 0.01 us: 1.00x faster
Not significant

### unpickle_pure_python ###
Mean +- std dev: 130 us +- 1 us -> 129 us +- 1 us: 1.01x faster
Not significant

### urlsafe_base64_small ###
Mean +- std dev: 205 us +- 1 us -> 207 us +- 0 us: 1.01x slower
Not significant

### xdsl_constant_fold ###
Mean +- std dev: 29.0 ms +- 1.9 ms -> 28.9 ms +- 1.9 ms: 1.00x faster
Not significant

### xml_etree_generate ###
Mean +- std dev: 55.1 ms +- 0.5 ms -> 54.8 ms +- 0.4 ms: 1.00x faster
Not significant

### xml_etree_iterparse ###
Mean +- std dev: 59.5 ms +- 0.5 ms -> 59.5 ms +- 0.5 ms: 1.00x slower
Not significant

### xml_etree_parse ###
Mean +- std dev: 95.1 ms +- 1.8 ms -> 95.1 ms +- 0.7 ms: 1.00x slower
Not significant

### xml_etree_process ###
Mean +- std dev: 37.1 ms +- 0.3 ms -> 37.2 ms +- 0.4 ms: 1.00x slower
Not significant

@vstinner vstinner left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@vstinner

vstinner commented Nov 9, 2026

Copy link
Copy Markdown
Member

Tests / CIFuzz / cpython3 (address) (pull_request): Failing after 2m

Ah, apt failed with download errors: "Unable to connect to archive.ubuntu.com:http: [IP: 91.189.90.11 80]". Unrelated to this change.

@StanFromIreland
StanFromIreland merged commit 37b5cc4 into python:main Nov 9, 2026
58 of 60 checks passed
@StanFromIreland

Copy link
Copy Markdown
Member

Merged, thanks.

@chenshanzhi
chenshanzhi deleted the enable-hot-attr-for-clang branch November 10, 2026 01:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type-feature A feature request or enhancement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants