This commit is contained in:
nlohmann committed 2026-10-04 15:46:44 +00:00
1 parent 19f538472d
commit c51ca275d0
374 files changed
+1998 -551

No files matched your search

+22
View File
@@ -0,0 +1,22 @@
<!doctype html><html lang=en class=no-js> <head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta name=author content="Niels Lohmann"><link href="https://json.nlohmann.me/integration/compile_times/" rel="canonical"><link href=../pkg-config/ rel=prev><link href=../../api/basic_json/ rel=next><link rel=icon href=../../assets/images/favicon.png><meta name=generator content="mkdocs-1.6.1, mkdocs-material-9.7.7"><title>Compile times - JSON for Modern C++</title><link rel=stylesheet href=../../assets/stylesheets/main.ec1eaa64.min.css><link rel=stylesheet href=../../assets/stylesheets/palette.ab4e12ef.min.css><link rel="stylesheet" href="../../assets/external/fonts.googleapis.com/css.61a430c9.css"><style>:root{--md-text-font:"Roboto";--md-code-font:"JetBrains Mono"}</style><link rel=stylesheet href=../../css/custom.css><script>__md_scope=new URL("../..",location),__md_hash=e=>[...e].reduce(((e,_)=>(e<<5)-e+_.charCodeAt(0)),0),__md_get=(e,_=localStorage,t=__md_scope)=>JSON.parse(_.getItem(t.pathname+"."+e)),__md_set=(e,_,t=localStorage,a=__md_scope)=>{try{t.setItem(a.pathname+"."+e,JSON.stringify(_))}catch(e){}}</script></head> <body dir=ltr data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo> <input class=md-toggle data-md-toggle=drawer type=checkbox id=__drawer autocomplete=off> <input class=md-toggle data-md-toggle=search type=checkbox id=__search autocomplete=off> <label class=md-overlay for=__drawer></label> <div data-md-component=skip> <a href=#compile-times class=md-skip> Skip to content </a> </div> <div data-md-component=announce> </div> <header class=md-header data-md-component=header> <nav class="md-header__inner md-grid" aria-label=Header> <a href=../.. title="JSON for Modern C++" class="md-header__button md-logo" aria-label="JSON for Modern C++" data-md-component=logo> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a3 3 0 0 0 3-3 3 3 0 0 0-3-3 3 3 0 0 0-3 3 3 3 0 0 0 3 3m0 3.54C9.64 9.35 6.5 8 3 8v11c3.5 0 6.64 1.35 9 3.54 2.36-2.19 5.5-3.54 9-3.54V8c-3.5 0-6.64 1.35-9 3.54"/></svg> </a> <label class="md-header__button md-icon" for=__drawer> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M3 6h18v2H3zm0 5h18v2H3zm0 5h18v2H3z"/></svg> </label> <div class=md-header__title data-md-component=header-title> <div class=md-header__ellipsis> <div class=md-header__topic> <span class=md-ellipsis> JSON for Modern C++ </span> </div> <div class=md-header__topic data-md-component=header-topic> <span class=md-ellipsis> Compile times </span> </div> </div> </div> <form class=md-header__option data-md-component=palette> <input class=md-option data-md-color-media="(prefers-color-scheme: light)" data-md-color-scheme=default data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to dark mode" type=radio name=__palette id=__palette_0> <label class="md-header__button md-icon" title="Switch to dark mode" for=__palette_1 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 8a4 4 0 0 0-4 4 4 4 0 0 0 4 4 4 4 0 0 0 4-4 4 4 0 0 0-4-4m0 10a6 6 0 0 1-6-6 6 6 0 0 1 6-6 6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> <input class=md-option data-md-color-media="(prefers-color-scheme: dark)" data-md-color-scheme=slate data-md-color-primary=indigo data-md-color-accent=indigo aria-label="Switch to light mode" type=radio name=__palette id=__palette_1> <label class="md-header__button md-icon" title="Switch to light mode" for=__palette_0 hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M12 18c-.89 0-1.74-.2-2.5-.55C11.56 16.5 13 14.42 13 12s-1.44-4.5-3.5-5.45C10.26 6.2 11.11 6 12 6a6 6 0 0 1 6 6 6 6 0 0 1-6 6m8-9.31V4h-4.69L12 .69 8.69 4H4v4.69L.69 12 4 15.31V20h4.69L12 23.31 15.31 20H20v-4.69L23.31 12z"/></svg> </label> </form> <script>var palette=__md_get("__palette");if(palette&&palette.color){if("(prefers-color-scheme)"===palette.color.media){var media=matchMedia("(prefers-color-scheme: light)"),input=document.querySelector(media.matches?"[data-md-color-media='(prefers-color-scheme: light)']":"[data-md-color-media='(prefers-color-scheme: dark)']");palette.color.media=input.getAttribute("data-md-color-media"),palette.color.scheme=input.getAttribute("data-md-color-scheme"),palette.color.primary=input.getAttribute("data-md-color-primary"),palette.color.accent=input.getAttribute("data-md-color-accent")}for(var[key,value]of Object.entries(palette.color))document.body.setAttribute("data-md-color-"+key,value)}</script> <label class="md-header__button md-icon" for=__search> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M9.5 3A6.5 6.5 0 0 1 16 9.5c0 1.61-.59 3.09-1.56 4.23l.27.27h.79l5 5-1.5 1.5-5-5v-.79l-.27-.27A6.52 6.52 0 0 1 9.5 16 6.5 6.5 0 0 1 3 9.5 6.5 6.5 0 0 1 9.5 3m0 2C7 5 5 7 5 9.5S7 14 9.5 14 14 12 14 9.5 12 5 9.5 5"/></svg> </label> Line truncated
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json_fwd.hpp&gt;</span>
<span class=k>struct</span><span class=w> </span><span class=nc>person</span><span class=p>;</span>
<span class=kt>void</span><span class=w> </span><span class=nf>to_json</span><span class=p>(</span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=o>&amp;</span><span class=w> </span><span class=n>j</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>person</span><span class=o>&amp;</span><span class=w> </span><span class=n>p</span><span class=p>);</span>
<span class=kt>void</span><span class=w> </span><span class=nf>from_json</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=o>&amp;</span><span class=w> </span><span class=n>j</span><span class=p>,</span><span class=w> </span><span class=n>person</span><span class=o>&amp;</span><span class=w> </span><span class=n>p</span><span class=p>);</span>
</code></pre></div> <div class=highlight><span class=filename>person.cpp</span><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>"person.hpp"</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=kt>void</span><span class=w> </span><span class=nf>to_json</span><span class=p>(</span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=o>&amp;</span><span class=w> </span><span class=n>j</span><span class=p>,</span><span class=w> </span><span class=k>const</span><span class=w> </span><span class=n>person</span><span class=o>&amp;</span><span class=w> </span><span class=n>p</span><span class=p>)</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
<span class=kt>void</span><span class=w> </span><span class=nf>from_json</span><span class=p>(</span><span class=k>const</span><span class=w> </span><span class=n>nlohmann</span><span class=o>::</span><span class=n>json</span><span class=o>&amp;</span><span class=w> </span><span class=n>j</span><span class=p>,</span><span class=w> </span><span class=n>person</span><span class=o>&amp;</span><span class=w> </span><span class=n>p</span><span class=p>)</span><span class=w> </span><span class=p>{</span><span class=w> </span><span class=cm>/* ... */</span><span class=w> </span><span class=p>}</span>
</code></pre></div> <table> <thead> <tr> <th>Compiler</th> <th style="text-align: right;"><code>json.hpp</code> (<code>-O0</code>)</th> <th style="text-align: right;"><code>json_fwd.hpp</code> (<code>-O0</code>)</th> <th style="text-align: right;">Change</th> </tr> </thead> <tbody> <tr> <td>Apple clang</td> <td style="text-align: right;">704 ms</td> <td style="text-align: right;">329 ms</td> <td style="text-align: right;">−53%</td> </tr> <tr> <td><abbr title="GNU Compiler Collection">GCC</abbr> 16</td> <td style="text-align: right;">779 ms</td> <td style="text-align: right;">242 ms</td> <td style="text-align: right;">−69%</td> </tr> </tbody> </table> <p>This is the most effective option, because it avoids the full header in every translation unit that includes <em>your</em> headers.</p> <h2 id=opt-out-of-the-automatic-user-defined-string-literals>Opt out of the automatic user-defined string literals<a class=headerlink href=#opt-out-of-the-automatic-user-defined-string-literals title="Permanent link">&para;</a></h2> <p>The user-defined string literals <a href=../../api/operator_literal_json/ ><code>operator""_json</code></a> and <a href=../../api/operator_literal_json_pointer/ ><code>operator""_json_pointer</code></a> are ordinary inline functions whose bodies call the parser. As <code>&lt;nlohmann/json.hpp&gt;</code> includes them by default, every translation unit instantiates the parser, even if it never parses anything itself.</p> <p>Define <a href=../../api/macros/json_no_automatic_udls/ ><code>JSON_NO_AUTOMATIC_UDLS</code></a> for the whole project and include <code>&lt;nlohmann/json_literals.hpp&gt;</code> instead of <code>&lt;nlohmann/json.hpp&gt;</code> in the files that use the literals (it includes <code>&lt;nlohmann/json.hpp&gt;</code> itself):</p> <div class=highlight><pre><span></span><code><span class=nb>target_compile_definitions</span><span class=p>(</span><span class=s>my_target</span><span class=w> </span><span class=s>PRIVATE</span><span class=w> </span><span class=s>JSON_NO_AUTOMATIC_UDLS</span><span class=p>)</span>
</code></pre></div> <div class=highlight><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json_literals.hpp&gt;</span><span class=w> </span><span class=c1>// only where "..."_json is used; includes &lt;nlohmann/json.hpp&gt;</span>
</code></pre></div> <p>The saving applies to translation units that do not parse <abbr title="JavaScript Object Notation">JSON</abbr>, for example ones that define types and their conversions or only pass <code>json</code> values around:</p> <table> <thead> <tr> <th>Compiler</th> <th>Translation unit</th> <th style="text-align: right;">Default (<code>-O0</code> / <code>-O2</code>)</th> <th style="text-align: right;"><code>JSON_NO_AUTOMATIC_UDLS</code> (<code>-O0</code> / <code>-O2</code>)</th> <th style="text-align: right;">Change</th> </tr> </thead> <tbody> <tr> <td>Apple clang</td> <td>model</td> <td style="text-align: right;">776 ms / 846 ms</td> <td style="text-align: right;">629 ms / 692 ms</td> <td style="text-align: right;">−19% / −18%</td> </tr> <tr> <td><abbr title="GNU Compiler Collection">GCC</abbr> 16</td> <td>model</td> <td style="text-align: right;">1022 ms / 1120 ms</td> <td style="text-align: right;">882 ms / 965 ms</td> <td style="text-align: right;">−14% / −14%</td> </tr> <tr> <td>Apple clang</td> <td>parsing</td> <td style="text-align: right;">992 ms / 1815 ms</td> <td style="text-align: right;">1006 ms / 1823 ms</td> <td style="text-align: right;">+1% / 0%</td> </tr> <tr> <td><abbr title="GNU Compiler Collection">GCC</abbr> 16</td> <td>parsing</td> <td style="text-align: right;">2018 ms / 3420 ms</td> <td style="text-align: right;">1990 ms / 3454 ms</td> <td style="text-align: right;">−1% / +1%</td> </tr> </tbody> </table> <p>Translation units that include only the header save up to a third. Translation units that parse anyway instantiate the parser regardless and see no difference.</p> <h2 id=instantiate-basic_json-once>Instantiate <code>basic_json</code> once<a class=headerlink href=#instantiate-basic_json-once title="Permanent link">&para;</a></h2> <p>Each translation unit instantiates the member functions of <code>nlohmann::json</code> it uses. An explicit instantiation declaration tells the compiler that the non-template members are instantiated elsewhere, so it can skip them:</p> <div class=highlight><span class=filename>json_instance.hpp</span><pre><span></span><code><span class=cp>#pragma once</span>
<span class=cp>#include</span><span class=w> </span><span class=cpf>&lt;nlohmann/json.hpp&gt;</span>
<span class=k>extern</span><span class=w> </span><span class=k>template</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;&gt;</span><span class=p>;</span>
</code></pre></div> <div class=highlight><span class=filename>json_instance.cpp</span><pre><span></span><code><span class=cp>#include</span><span class=w> </span><span class=cpf>"json_instance.hpp"</span>
<span class=k>template</span><span class=w> </span><span class=k>class</span><span class=w> </span><span class=nc>nlohmann</span><span class=o>::</span><span class=n>basic_json</span><span class=o>&lt;&gt;</span><span class=p>;</span>
</code></pre></div> <p>Include <code>json_instance.hpp</code> instead of <code>&lt;nlohmann/json.hpp&gt;</code> and compile and link <code>json_instance.cpp</code> once.</p> <table> <thead> <tr> <th>Compiler</th> <th>Translation unit</th> <th style="text-align: right;">Default (<code>-O0</code> / <code>-O2</code>)</th> <th style="text-align: right;"><code>extern template</code> (<code>-O0</code> / <code>-O2</code>)</th> <th style="text-align: right;">Change</th> </tr> </thead> <tbody> <tr> <td>Apple clang</td> <td>parsing</td> <td style="text-align: right;">992 ms / 1815 ms</td> <td style="text-align: right;">953 ms / 1625 ms</td> <td style="text-align: right;">−4% / −10%</td> </tr> <tr> <td><abbr title="GNU Compiler Collection">GCC</abbr> 16</td> <td>parsing</td> <td style="text-align: right;">2018 ms / 3420 ms</td> <td style="text-align: right;">1522 ms / 2728 ms</td> <td style="text-align: right;">−25% / −20%</td> </tr> <tr> <td>Apple clang</td> <td><code>json_instance.cpp</code></td> <td style="text-align: right;">—</td> <td style="text-align: right;">2166 ms / 4660 ms</td> <td style="text-align: right;">—</td> </tr> <tr> <td><abbr title="GNU Compiler Collection">GCC</abbr> 16</td> <td><code>json_instance.cpp</code></td> <td style="text-align: right;">—</td> <td style="text-align: right;">5085 ms / 10616 ms</td> <td style="text-align: right;">—</td> </tr> </tbody> </table> <p>Notes:</p> <ul> <li>The saving grows with the number of translation units that use <code>json</code>, while the instantiation translation unit is compiled only once (and is rarely recompiled, as it does not depend on your code).</li> <li>Member function templates (such as <code>get&lt;T&gt;()</code>, <code>parse(InputType&amp;&amp;)</code>, or <code>value(key, default)</code>) are not covered by the explicit instantiation and are still instantiated where they are used.</li> <li>The declaration covers exactly <code>nlohmann::json</code>. Add the same lines for <code>nlohmann::ordered_json</code> (<code>nlohmann::basic_json&lt;nlohmann::ordered_map&gt;</code>) or your own <code>basic_json</code> specializations if you use them.</li> </ul> <h2 id=use-c20-modules>Use C++20 modules<a class=headerlink href=#use-c20-modules title="Permanent link">&para;</a></h2> <p>With a toolchain that supports named modules, <code>import nlohmann.json;</code> compiles the library once into a module and avoids parsing the header in every translation unit. See <a href=../../features/modules/ >Modules</a> for requirements and known issues. Module support is experimental and currently depends heavily on the compiler version.</p> <h2 id=use-precompiled-headers>Use precompiled headers<a class=headerlink href=#use-precompiled-headers title="Permanent link">&para;</a></h2> <p>Build systems can precompile <code>&lt;nlohmann/json.hpp&gt;</code> together with other stable headers, for example with CMake's <a href="https://cmake.org/cmake/help/latest/command/target_precompile_headers.html"><code>target_precompile_headers</code></a>:</p> <div class=highlight><pre><span></span><code><span class=nb>target_precompile_headers</span><span class=p>(</span><span class=s>my_target</span><span class=w> </span><span class=s>PRIVATE</span><span class=w> </span><span class=s>&lt;nlohmann/json.hpp&gt;</span><span class=p>)</span>
</code></pre></div> <p>This removes the cost of parsing the header, but not of instantiating templates in each translation unit, so it combines well with the options above.</p> <h2 id=options-without-effect-on-compile-times>Options without effect on compile times<a class=headerlink href=#options-without-effect-on-compile-times title="Permanent link">&para;</a></h2> <p>Some configuration macros change what the library declares, but do not measurably change compile times:</p> <table> <thead> <tr> <th>Macro</th> <th style="text-align: right;">Apple clang, model (<code>-O0</code> / <code>-O2</code>)</th> <th style="text-align: right;"><abbr title="GNU Compiler Collection">GCC</abbr> 16, model (<code>-O0</code> / <code>-O2</code>)</th> </tr> </thead> <tbody> <tr> <td>default</td> <td style="text-align: right;">776 ms / 846 ms</td> <td style="text-align: right;">1022 ms / 1120 ms</td> </tr> <tr> <td><a href=../../api/macros/json_no_io/ ><code>JSON_NO_IO</code></a></td> <td style="text-align: right;">764 ms / 836 ms</td> <td style="text-align: right;">1022 ms / 1117 ms</td> </tr> <tr> <td><a href=../../api/macros/json_use_global_udls/ ><code>JSON_USE_GLOBAL_UDLS</code></a><code>=0</code></td> <td style="text-align: right;">763 ms / 852 ms</td> <td style="text-align: right;">1019 ms / 1106 ms</td> </tr> </tbody> </table> <p><code>JSON_USE_GLOBAL_UDLS</code> only controls <em>where</em> the literals are declared; to avoid their cost, use <code>JSON_NO_AUTOMATIC_UDLS</code> instead.</p> <h2 id=see-also>See also<a class=headerlink href=#see-also title="Permanent link">&para;</a></h2> <ul> <li><a href=../../api/macros/json_no_automatic_udls/ ><code>JSON_NO_AUTOMATIC_UDLS</code></a> - do not include the user-defined string literals automatically</li> <li><a href=../../features/modules/ >Modules</a> - C++20 module support</li> <li><a href=../ >Header only</a> - including the library</li> </ul> <!-- https://squidfunk.github.io/mkdocs-material/reference/tooltips/#adding-a-glossary --> <aside class=md-source-file> <span class=md-source-file__fact> <span class=md-icon title="Last update"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M21 13.1c-.1 0-.3.1-.4.2l-1 1 2.1 2.1 1-1c.2-.2.2-.6 0-.8l-1.3-1.3c-.1-.1-.2-.2-.4-.2m-1.9 1.8-6.1 6V23h2.1l6.1-6.1zM12.5 7v5.2l4 2.4-1 1L11 13V7zM11 21.9c-5.1-.5-9-4.8-9-9.9C2 6.5 6.5 2 12 2c5.3 0 9.6 4.1 10 9.3-.3-.1-.6-.2-1-.2s-.7.1-1 .2C19.6 7.2 16.2 4 12 4c-4.4 0-8 3.6-8 8 0 4.1 3.1 7.5 7.1 7.9l-.1.2z"/></svg> </span> <span class="git-revision-date-localized-plugin git-revision-date-localized-plugin-date" title="October 4, 2026 10:23:53 UTC">October 4, 2026</span> </span> </aside> </article> </div> <script>var tabs=__md_get("__tabs");if(Array.isArray(tabs))e:for(var set of document.querySelectorAll(".tabbed-set")){var labels=set.querySelector(".tabbed-labels");for(var tab of tabs)for(var label of labels.getElementsByTagName("label"))if(label.innerText.trim()===tab){var input=document.getElementById(label.htmlFor);input.checked=!0;continue e}}</script> <script>var target=document.getElementById(location.hash.slice(1));target&&target.name&&(target.checked=target.name.startsWith("__tabbed_"))</script> </div> <button type=button class="md-top md-icon" data-md-component=top hidden> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 24 24"><path d="M13 20h-2V8l-5.5 5.5-1.42-1.42L12 4.16l7.92 7.92-1.42 1.42L13 8z"/></svg> Back to top </button> </main> <footer class=md-footer> <div class="md-footer-meta md-typeset"> <div class="md-footer-meta__inner md-grid"> <div class=md-copyright> <div class=md-copyright__highlight> Copyright &copy; 2013-2026 Niels Lohmann </div> </div> <div class=md-social> <a href="https://github.com/nlohmann" target="_blank" rel="noopener" title="github.com" class="md-social__link"> <svg xmlns=http://www.w3.org/2000/svg viewbox="0 0 512 512"><!-- Font Awesome Free 7.1.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) Copyright 2025 Fonticons, Inc.--><path d="M173.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6m-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3m44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9M252.8 8C114.1 8 8 113.3 8 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C436.2 457.8 504 362.9 504 252 504 113.3 391.5 8 252.8 8Line truncated
+132
View File
@@ -0,0 +1,132 @@
# Compile times
The library is header-only and makes heavy use of templates, so every translation unit that includes `<nlohmann/json.hpp>` pays for parsing the header and instantiating what it uses. This page lists the options to reduce that cost, ordered by how much they typically save.
Measurements
The numbers below are medians of nine runs compiling a single translation unit with `-std=c++17 -c` against the single-header version, with Apple clang and GCC 16 on macOS (Apple silicon). They show the order of magnitude to expect; measure your own code before and after a change.
## Include `json_fwd.hpp` in headers
Header files that only need to *name* the `json` type — for function declarations, members held by pointer or reference, or friend declarations — can include `<nlohmann/json_fwd.hpp>` instead of `<nlohmann/json.hpp>`. It only forward-declares `basic_json`, `json`, `ordered_json`, `json_pointer`, and `adl_serializer`. The translation units that actually use the values then include `<nlohmann/json.hpp>`.
person.hpp
```
#pragma once
#include <nlohmann/json_fwd.hpp>
struct person;
void to_json(nlohmann::json& j, const person& p);
void from_json(const nlohmann::json& j, person& p);
```
person.cpp
```
#include "person.hpp"
#include <nlohmann/json.hpp>
void to_json(nlohmann::json& j, const person& p) { /* ... */ }
void from_json(const nlohmann::json& j, person& p) { /* ... */ }
```
| Compiler | `json.hpp` (`-O0`) | `json_fwd.hpp` (`-O0`) | Change |
| ----------- | ------------------ | ---------------------- | ------ |
| Apple clang | 704 ms | 329 ms | −53% |
| GCC 16 | 779 ms | 242 ms | −69% |
This is the most effective option, because it avoids the full header in every translation unit that includes *your* headers.
## Opt out of the automatic user-defined string literals
The user-defined string literals [`operator""_json`](https://json.nlohmann.me/api/operator_literal_json/index.md) and [`operator""_json_pointer`](https://json.nlohmann.me/api/operator_literal_json_pointer/index.md) are ordinary inline functions whose bodies call the parser. As `<nlohmann/json.hpp>` includes them by default, every translation unit instantiates the parser, even if it never parses anything itself.
Define [`JSON_NO_AUTOMATIC_UDLS`](https://json.nlohmann.me/api/macros/json_no_automatic_udls/index.md) for the whole project and include `<nlohmann/json_literals.hpp>` instead of `<nlohmann/json.hpp>` in the files that use the literals (it includes `<nlohmann/json.hpp>` itself):
```
target_compile_definitions(my_target PRIVATE JSON_NO_AUTOMATIC_UDLS)
```
```
#include <nlohmann/json_literals.hpp> // only where "..."_json is used; includes <nlohmann/json.hpp>
```
The saving applies to translation units that do not parse JSON, for example ones that define types and their conversions or only pass `json` values around:
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `JSON_NO_AUTOMATIC_UDLS` (`-O0` / `-O2`) | Change |
| ----------- | ---------------- | ----------------------- | ---------------------------------------- | ----------- |
| Apple clang | model | 776 ms / 846 ms | 629 ms / 692 ms | −19% / −18% |
| GCC 16 | model | 1022 ms / 1120 ms | 882 ms / 965 ms | −14% / −14% |
| Apple clang | parsing | 992 ms / 1815 ms | 1006 ms / 1823 ms | +1% / 0% |
| GCC 16 | parsing | 2018 ms / 3420 ms | 1990 ms / 3454 ms | −1% / +1% |
Translation units that include only the header save up to a third. Translation units that parse anyway instantiate the parser regardless and see no difference.
## Instantiate `basic_json` once
Each translation unit instantiates the member functions of `nlohmann::json` it uses. An explicit instantiation declaration tells the compiler that the non-template members are instantiated elsewhere, so it can skip them:
json_instance.hpp
```
#pragma once
#include <nlohmann/json.hpp>
extern template class nlohmann::basic_json<>;
```
json_instance.cpp
```
#include "json_instance.hpp"
template class nlohmann::basic_json<>;
```
Include `json_instance.hpp` instead of `<nlohmann/json.hpp>` and compile and link `json_instance.cpp` once.
| Compiler | Translation unit | Default (`-O0` / `-O2`) | `extern template` (`-O0` / `-O2`) | Change |
| ----------- | ------------------- | ----------------------- | --------------------------------- | ----------- |
| Apple clang | parsing | 992 ms / 1815 ms | 953 ms / 1625 ms | −4% / −10% |
| GCC 16 | parsing | 2018 ms / 3420 ms | 1522 ms / 2728 ms | −25% / −20% |
| Apple clang | `json_instance.cpp` | — | 2166 ms / 4660 ms | — |
| GCC 16 | `json_instance.cpp` | — | 5085 ms / 10616 ms | — |
Notes:
- The saving grows with the number of translation units that use `json`, while the instantiation translation unit is compiled only once (and is rarely recompiled, as it does not depend on your code).
- Member function templates (such as `get<T>()`, `parse(InputType&&)`, or `value(key, default)`) are not covered by the explicit instantiation and are still instantiated where they are used.
- The declaration covers exactly `nlohmann::json`. Add the same lines for `nlohmann::ordered_json` (`nlohmann::basic_json<nlohmann::ordered_map>`) or your own `basic_json` specializations if you use them.
## Use C++20 modules
With a toolchain that supports named modules, `import nlohmann.json;` compiles the library once into a module and avoids parsing the header in every translation unit. See [Modules](https://json.nlohmann.me/features/modules/index.md) for requirements and known issues. Module support is experimental and currently depends heavily on the compiler version.
## Use precompiled headers
Build systems can precompile `<nlohmann/json.hpp>` together with other stable headers, for example with CMake's [`target_precompile_headers`](https://cmake.org/cmake/help/latest/command/target_precompile_headers.html):
```
target_precompile_headers(my_target PRIVATE <nlohmann/json.hpp>)
```
This removes the cost of parsing the header, but not of instantiating templates in each translation unit, so it combines well with the options above.
## Options without effect on compile times
Some configuration macros change what the library declares, but do not measurably change compile times:
| Macro | Apple clang, model (`-O0` / `-O2`) | GCC 16, model (`-O0` / `-O2`) |
| ----------------------------------------------------------------------------------------------- | ---------------------------------- | ----------------------------- |
| default | 776 ms / 846 ms | 1022 ms / 1120 ms |
| [`JSON_NO_IO`](https://json.nlohmann.me/api/macros/json_no_io/index.md) | 764 ms / 836 ms | 1022 ms / 1117 ms |
| [`JSON_USE_GLOBAL_UDLS`](https://json.nlohmann.me/api/macros/json_use_global_udls/index.md)`=0` | 763 ms / 852 ms | 1019 ms / 1106 ms |
`JSON_USE_GLOBAL_UDLS` only controls *where* the literals are declared; to avoid their cost, use `JSON_NO_AUTOMATIC_UDLS` instead.
## See also
- [`JSON_NO_AUTOMATIC_UDLS`](https://json.nlohmann.me/api/macros/json_no_automatic_udls/index.md) - do not include the user-defined string literals automatically
- [Modules](https://json.nlohmann.me/features/modules/index.md) - C++20 module support
- [Header only](https://json.nlohmann.me/integration/index.md) - including the library