{"id":330,"date":"2024-09-03T20:48:57","date_gmt":"2024-09-03T20:48:57","guid":{"rendered":"https:\/\/permutationcity.co.uk\/bp\/?p=330"},"modified":"2024-09-10T18:59:40","modified_gmt":"2024-09-10T18:59:40","slug":"saving-pennies","status":"publish","type":"post","link":"https:\/\/permutationcity.co.uk\/bp\/2024\/09\/03\/saving-pennies\/","title":{"rendered":"Saving pennies"},"content":{"rendered":"\n<p>Imagine your shopping at a different supermarket from normal.\nYou notice that baked beans are 3p per tin cheaper than you&#8217;re use to.\nThe news had a story about supermarket price wars on basic goods recently.\nIt&#8217;s a bit out of your way but if you switch supermarkets you could save money on beans each month!<\/p>\n\n\n\n<p>Does that sound familiar?\nNo, probably not.\nSaving 3p on a tin of beans is unlikely to be worth it unless you eat a <strong>lot<\/strong> of beans.\nIf the supermarket is out of your way then you might end up spending more money on getting there.\nIt might make sense if you noticed the other supermarket sells steak or bottles of wine at half price.\nOtherwise it&#8217;s better to look at the overall cost for a trolley and decide based on that.<\/p>\n\n\n\n<p>Optimisation is a bit like this.\nThere are a few simple ways you can save a fraction here and there.\nThere are even automated ways to detect those situations.\nWhile making your code a few percent faster is nice wouldn&#8217;t it be better to make it\n<a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/01\/08\/400000000-times-faster\/\">many times faster<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"inefficient-vector-operations\">Inefficient vector operations<\/h2>\n\n\n\n<p><a href=\"https:\/\/clang.llvm.org\/extra\/clang-tidy\/index.html\"><code>clang-tidy<\/code><\/a>\nis a static analysis tool that can perform all sorts of checks on your code.\nOne of them looks for\n<a href=\"https:\/\/clang.llvm.org\/extra\/clang-tidy\/checks\/performance\/inefficient-vector-operation.html\">inefficient vector operations<\/a>.\nLets say you want a list of numbers:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    std::vector&lt;uint32_t&gt; values;\n    for (uint32_t i = 0; i &lt; count; i++) {\n      values.push_back(i);\n    }<\/pre><\/div>\n\n\n\n<p>This will trigger a warning because, as <code>values<\/code> gradually expands,\nit could trigger multiple memory allocations and copies.\nIf instead you pre-allocate the list then only a single allocation is required:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    std::vector&lt;uint32_t&gt; values;\n    values.reserve(count);\n    for (uint32_t i = 0; i &lt; count; i++) {\n      values.push_back(i);\n    }<\/pre><\/div>\n\n\n\n<p>Does this really make a difference? I can guess but let&#8217;s have a look. It does, pre-allocating space can be <a href=\"https:\/\/quick-bench.com\/q\/B-UhLwZv6i9dvGt5R89wyVIQNfE\">2.5 times faster<\/a>. Or maybe <a href=\"https:\/\/quick-bench.com\/q\/ILQvUAbifiKT148BkLCsm8ng9FE\">4.3 times faster<\/a> or <a href=\"https:\/\/quick-bench.com\/q\/H1Mg5zZM350RQmSx-BvxUkx1Cts\">1.5 times faster<\/a>. So yes, it&#8217;s faster but details matters. The smaller loops show a greater speed increase. It matters more when you add 10 numbers and less add 1000 numbers. However remember that adding 10 numbers is going to <em>fast<\/em> anyway, there&#8217;s only 10 of them. Dealing with 1000 things is where you&#8217;re more likely to notice the difference but there the speed is more similar. All of these have been dealing with some of the simplest possible loops. What if they were slightly more complicated? Then pre-allocating space is only <a href=\"https:\/\/quick-bench.com\/q\/6A0DNXLlV0aJh4Jb_hVf4VAywl8\">1.1 times faster<\/a>.<\/p>\n\n\n\n<p>It&#8217;s not that <em>much<\/em> faster, it looks more complicated and it&#8217;s has more room for bugs:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>If you change your upper bound you have to remember to change <code>reserve<\/code>.<\/li>\n\n\n\n<li>If you change how many values to add per loop you have to remember to change <code>reserve<\/code>.<\/li>\n<\/ul>\n\n\n\n<p>And if you <em>do<\/em> make a mistake it won&#8217;t break it will just silently slow down.\nIn some ways that&#8217;s worse because it&#8217;s unlikely to be noticed and fixed.<\/p>\n\n\n\n<p>I suppose the worst situation for you code is when\nyou are adding, say, 10 numbers to a new array but you&#8217;re doing that hundreds of times.\nHowever, you can do even better than using <code>reserve<\/code> by\n<a href=\"https:\/\/quick-bench.com\/q\/J7GvHKqRPZjwIPXa2I7Z_ACJ7QM\">thinking about the algorithm<\/a>.<\/p>\n\n\n\n<p>To my mind <code>reserve<\/code> is best used when you&#8217;re writing library functions that can get re-used everywhere:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">template &lt;typename T, typename Generator&gt;\nvoid append_n(std::vector&lt;T&gt;&amp; values, size_t count, Generator generator) {\n    values.reserve(values.size() + count);\n    for (size_t i = 0; i &lt; count; i++) {\n        values.push_back(generator(i));\n    }\n}<\/pre><\/div>\n\n\n\n<p>That way everyone else can write something simple and automatically get the benefit:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    std::vector&lt;uint32_t&gt; values;\n    append_n(values, count, [](const int i){ return i; });<\/pre><\/div>\n\n\n\n<p>This is <a href=\"https:\/\/quick-bench.com\/q\/oELoapGc2sAEujnsD3WwJr5R_Vo\">just as fast<\/a> as pre-allocating the list manually. It can also be easily repurposed to store only even numbers, or string representations of the numbers, or whatever you want to calculate. As it&#8217;s something discrete it&#8217;s easy to write unit tests for so should be more reliable. Your team <em>will<\/em> have to learn another set of library functions and what to expect from them. That&#8217;s a cost that comes with any new library whether you write it yourself or not.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"pre-increment-vs-post-increment\">Pre-increment vs post-increment<\/h2>\n\n\n\n<p>Sometimes you see advice saying to prefer pre-increment operators to get the best performance.<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    \/\/ First increment and then use the new value.\n    uint32_t preTotal = 0;\n    for (uint32_t i = 0; i &lt; s_Count;) {\n      pretotal += ++i;\n    }\n    \/\/ Store the old value, increment, and then use the old value.\n    uint32_t postTotal = 0;\n    for (uint32_t i = 0; i &lt; s_Count;) {\n      postTotal += i++;\n    }<\/pre><\/div>\n\n\n\n<p>So the <a href=\"https:\/\/quick-bench.com\/q\/qHuW1tUL-EjHmkAc1N2lwJuQ7bU\">first loop is faster than the second<\/a> but\ndid you notice anything special about the test?\nI had to switch the optimisation off.\nWith optimisation switched on the <a href=\"https:\/\/quick-bench.com\/q\/kZMmZc1JmQAIG-5UrmmkO8zhDEE\">both loops are the same<\/a>.\nIndeed with a more typical loop:<\/p>\n\n\n\n<div class=\"wp-block-codemirror-blocks-code-block code-block\"><pre class=\"CodeMirror\" data-setting=\"{&quot;showPanel&quot;:true,&quot;languageLabel&quot;:&quot;language&quot;,&quot;fullScreenButton&quot;:true,&quot;copyButton&quot;:true,&quot;mode&quot;:&quot;clike&quot;,&quot;mime&quot;:&quot;text\/x-c++src&quot;,&quot;theme&quot;:&quot;material&quot;,&quot;lineNumbers&quot;:false,&quot;styleActiveLine&quot;:false,&quot;lineWrapping&quot;:true,&quot;readOnly&quot;:true,&quot;fileName&quot;:&quot;C++&quot;,&quot;language&quot;:&quot;C++&quot;,&quot;maxHeight&quot;:&quot;400px&quot;,&quot;modeName&quot;:&quot;cpp&quot;}\">    uint32_t total = 0;\n    for (uint32_t i = 0; i &lt; s_Count; i++) {\n      total += i;\n    }<\/pre><\/div>\n\n\n\n<p>It doesn&#8217;t even matter if you don&#8217;t use optimisation.\nAgain, <a href=\"https:\/\/quick-bench.com\/q\/hO9-L8X--ZfmMdKkJZkU2Aklvjo\">both loops are the same<\/a>.\nYou&#8217;ll also find if you do anything other than the most basic calculations which operator you use\n<a href=\"https:\/\/quick-bench.com\/q\/AZ0hm0tFnoGLonh_VD4Q_ozyY28\">largely doesn&#8217;t matter<\/a>.<\/p>\n\n\n\n<p>So technically pre-increment operators can be faster than post-increment operators but\nin practice it hardly ever seems to be the case.\nIt may be that this <em>use<\/em> to matter with older compilers but not today.<\/p>\n\n\n\n<p>Really I have more of a problem with doing something to a value <em>and<\/em> using a value at the same time. If you can separate <em>incrementing the value<\/em> from <em>using the value<\/em> then it&#8217;s generally easier to understand what the code is doing. There are less likely to be edge cases that you miss. For me I&#8217;d prefer a single increment operator <code>i++<\/code> that had the same behaviour as <code>i += 1<\/code>. That way we don&#8217;t have to worry about specific pre and post increment behaviours. Unfortunately I don&#8217;t get to re-design C++.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"function-calls\">Function calls<\/h2>\n\n\n\n<p>Another idea is that the cost of function calls can add up. People might encourage you to duplicate code or specifically inline functions to avoid this. We can take a simple example of squaring a number. If you do it directly your code will be scattered with <code>value * value<\/code>. If you do it via function call you&#8217;ll have <code>Square(value)<\/code>. What does the profiler say? Direct usage is about <a href=\"https:\/\/quick-bench.com\/q\/zMhNz1BuRGeHZKUZJ2pfn1SPmPs\">10% faster than calling a function<\/a>. Interesting inlining the function doesn&#8217;t seem to help. Maybe that&#8217;s because I had to switch off optimisation again. With optimisation <a href=\"https:\/\/quick-bench.com\/q\/w9guAEjXpuRK6UvHt4hCr7r7z8A\">they are all neck and neck<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"little-vs-big\">Little vs big<\/h2>\n\n\n\n<p>Some of these techniques do make for faster code and some don&#8217;t.\nFor some of them it matters what optimisation you use, perhaps which compiler as well.\nHowever I&#8217;d argue that all of the are <em>relatively<\/em> small gains.\nThey&#8217;re small details that are easy to teach, easy to put in a tips &amp; tricks list, and\neasy to write automatic checkers for.<\/p>\n\n\n\n<p>What&#8217;s harder to teach is where to get <em>big<\/em> performance improvements.\nGenerally speaking this comes down:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><a href=\"https:\/\/en.wikipedia.org\/wiki\/List_of_algorithms\">Clever algorithms<\/a><\/li>\n\n\n\n<li>Organising you data<\/li>\n\n\n\n<li>Switching your tools<\/li>\n\n\n\n<li>Doing less work somehow<\/li>\n<\/ul>\n\n\n\n<p>I&#8217;ve <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/03\/21\/algorithms-are-great-minimax\/\">said it before<\/a> and\nI&#8217;ll say it again, the right algorithm can make a huge difference.\nThese <em>can<\/em> be complicated but they don&#8217;t have to be.\nBinary search is <a href=\"https:\/\/quick-bench.com\/q\/HhbYEzC3kFJ5m_VrUZyeci31lUM\"><em>much faster<\/em><\/a> than linear search.\nHere that&#8217;s 8.5 times faster, the biggest performance difference so far, and it&#8217;s not a huge example.\nWith a bigger example it gets even more significant,\n<a href=\"https:\/\/quick-bench.com\/q\/yOO3rCC7N1XGBGDB6vZ5D4OV61c\">54 times faster<\/a>!\nHowever it&#8217;s not as simple as using it everywhere.\nFor small lists <a href=\"https:\/\/quick-bench.com\/q\/Vg8Rur8tRkUkfeJQPkNg4qkOFqs\">linear can be faster<\/a>.<\/p>\n\n\n\n<p>I&#8217;ve talked about <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/04\/09\/data-oriented-design\/\">organising your data<\/a> before. At the time I wasn&#8217;t impressed by the book but saw that the technique could work. I looked at an <a href=\"https:\/\/permutationcity.co.uk\/bp\/2024\/04\/09\/data-oriented-design\/#example-particle-system\">example particle system<\/a> where I kept related data together. Again it has a speed up an order of magnitude greater than the <em>little<\/em> ones we discussed earlier. Data that isn&#8217;t useful to the calculations at hand can clog up the <a href=\"https:\/\/en.wikipedia.org\/wiki\/CPU_cache\">CPU cache<\/a> and cause more cache misses. It can also help you concentrate on doing only the work that you need to do, separate active and inactive data.<\/p>\n\n\n\n<p>If you are using libraries to do some of your work you might want to investigate alternatives.\nLets consider a fairly common activity, parsing <a href=\"https:\/\/en.wikipedia.org\/wiki\/JSON\">JSON<\/a>.\nFortunately for me someone else has already\n<a href=\"https:\/\/github.com\/miloyip\/nativejson-benchmark\">looked at the numbers<\/a>.\nThe look at 43 libraries from <a href=\"https:\/\/github.com\/bblanchon\/ArduinoJson\">ArduinoJson<\/a>\nall the way to <a href=\"https:\/\/github.com\/lloyd\/yajl\">YAJL<\/a>.<\/p>\n\n\n\n<div class=\"wp-block-merpress-mermaidjs diagram-source-mermaid\"><pre class=\"mermaid\">xychart-beta horizontal\n\nx-axis [\"gason\", \"RapidJSON\", \"RapidJSON_Insitu\", \"sajson\", \"ujson4c\", \"RapidJSON_AutoUTF\", \"RapidJSON_FullPrec\", \"Scheredom json.h\", \"mikeando\/FastJson\", \"cJSON\", \"ujson\", \"taocpp\/json\", \"udp\/json-parser\", \"V8\", \"ccan\/json\", \"Nlohmann\", \"SimpleJSON\", \"Configuru\", \"jsoncons\", \"Parson\", \"dropbox\/json11\", \"JVar\", \"YAJL\", \"Vinenthz\/libjson\", \"Jansson\", \"Qt\", \"C++ REST SDK\", \"json-c\", \"PicoJSON\", \"Jzon\", \"JsonCpp\", \"POCO\", \"hjiang\/JSON++\", \"tunnuz\/JSON++\", \"JsonBox\", \"jsmn\", \"nbsdx_SimpleJSON\", \"ArduinoJson\", \"CAJUN\"]\ny-axis \"Parsing time (ms)\" 0 --> 1200\nbar [8, 8, 8, 9, 9, 16, 16, 17, 19, 25, 37, 41, 47, 53, 60, 72, 79, 81, 89, 90, 94, 94, 103, 107, 112, 125, 134, 135, 140, 149, 166, 219, 224, 317, 341, 395, 486, 568, 1133]<\/pre><\/div>\n\n\n\n<p>There&#8217;s a factor of about 140 times between the fastest and slowest.\nPersonally I&#8217;m use to using <a href=\"https:\/\/github.com\/nlohmann\/json\">Nlohmann\/json<\/a>\nwhich turns out to be middle of the road.\nIf my project was slow switching to <a href=\"https:\/\/github.com\/Tencent\/rapidjson\">RapidJSON<\/a>\nmight be the way to go.\n(<a href=\"https:\/\/github.com\/USESystemEngineeringBV\/qajson4c\">gason<\/a> is the same speed but a different language.)<\/p>\n\n\n\n<p>Are you doing calculations multiple times when you could get away with doing them once? Caching previous work and then re-using it later trades memory for time. I once inherited a project where potentially thousands of tasks where being performed but each triggered the loading and saving of one of dozens of files. That meant a single file might be loaded and saved 100 times on average. Re-organising the code allowed me to load one file, perform 100 tasks and then save the file. It was a massive speedup.<\/p>\n\n\n\n<p>One of the most powerful options is just doing less work.\nLook at what the task actually requires.\nIf it was &#8220;List the top 10 items in order cost&#8221;.\nYou might total up the cost of every item, sort all the costs and take the first 10.\nThat&#8217;s certainly the obvious way to do it.\nHowever, with the right algorithm, you could start sorting all the costs and then stop once you had the first 10.\nThe order of the rest of them doesn&#8217;t matter.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"in-the-end\">In the end<\/h2>\n\n\n\n<p>There are lots of ways you can improve the performance of code.\nYou might think it&#8217;s good to do them all.\nSurely fast code is good code?\nI&#8217;d say: clear, readable, flexible and functional code are all more important than just being fast.\nIf you do <em>need<\/em> code that is faster the first thing to do is almost always to \n<a href=\"https:\/\/en.wikipedia.org\/wiki\/Profiling_(computer_programming)\">profile<\/a> it.\nOnce you know what parts of your code are slow you know where to focus your attention.\nYou get a bigger impact speeding up slow code than speeding up something that is already fast.\nStart by looking for ways to save a <em>lot<\/em> of time rather than a <em>little<\/em>.\nWe usually have limited time for development.\nIt&#8217;s not a questions of &#8220;How fast can this code possibly be?&#8221; but &#8220;How fast does this code need to be?&#8221;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Imagine your shopping at a different supermarket from normal. You notice that baked beans are 3p per tin cheaper than you&#8217;re use to. The news had a story about supermarket price wars on basic goods recently. It&#8217;s a bit out of your way but if you switch supermarkets you could save money on beans each [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_import_markdown_pro_load_document_selector":0,"_import_markdown_pro_submit_text_textarea":"","footnotes":""},"categories":[1],"tags":[22,7,18],"class_list":["post-330","post","type-post","status-publish","format-standard","hentry","category-general","tag-algorithms","tag-performance","tag-tools"],"_links":{"self":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/330","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/comments?post=330"}],"version-history":[{"count":6,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/330\/revisions"}],"predecessor-version":[{"id":353,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/posts\/330\/revisions\/353"}],"wp:attachment":[{"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/media?parent=330"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/categories?post=330"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/permutationcity.co.uk\/bp\/wp-json\/wp\/v2\/tags?post=330"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}