Skip to content

Commit

Permalink
Automated publish
Browse files Browse the repository at this point in the history
  • Loading branch information
Github Actions committed Feb 23, 2024
1 parent 3909971 commit 3387014
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 8 deletions.
2 changes: 1 addition & 1 deletion blog/2023-07-08-object-model/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -193,4 +193,4 @@
<span class="line"><span style="color:#f8f8f2"> {</span><span style="color:#88846f"> /* Normal O(n) code... */</span><span style="color:#f8f8f2"> }</span></span>
<span class="line"><span style="color:#f8f8f2"> }</span></span>
<span class="line"><span style="color:#f8f8f2"> );</span></span>
<span class="line"><span style="color:#f8f8f2">}</span></span></code></pre><h2>The numbers</h2><p>This has been a lot of theory, but my aim here is to shed light on how these things work. Your feedback on whether or not this is a good level of detail is very welcome, so please reach out to me any way you can to let me know your thoughts. Now let's celebrate some wins!<p><figure><object data="/img/blog/2023-07-08-object-model/allocations-tagged.plot.svg"type="image/svg+xml"width="50%"><img src="/img/blog/2023-07-08-object-model/allocations-tagged.plot.svg"width="50%"></object></figure><p><p>Non-empty map allocations are down from 31ns to 17ns, which is marginally higher than Clojure's 16ns. As I mentioned, the Boehm GC isn't the fastest on the market, so there's more work to be done here. Still, this is a huge win. Remember that jank has been consistently beating Clojure in benchmarks <em>without</em> these changes, so this is going to set it well ahead.<p><figure><object data="/img/blog/2023-07-08-object-model/extra-benchmarks.plot.svg"type="image/svg+xml"width="50%"><img src="/img/blog/2023-07-08-object-model/extra-benchmarks.plot.svg"width="50%"></object></figure><p><p>Map operations such as <code>get</code> and <code>count</code> were already very fast, compared to Clojure. This is one area which allowed jank to make up for its slower allocations. However, with the static objects, visitors, and concepts, these benchmarks also dropped significantly.<p>I'm very excited to benchmark more once I've finished this work, but there's still more to do. This is only a half-way report!<h2>Status</h2><p>Initial prototyping and benchmarking is finished and I'm ripping apart jank's inheritance object model to replace it with the tagged object model. This is a large effort, which is why I wanted to get this done while jank was still young; it changes how every jank object works. At the end of the quarter, I'll be presenting more final numbers, as well as outlining future plans.<h2>Wrapping up</h2><p>You may be wondering how jank will handle dynamic objects now. For those, there will just be an enum value for dynamic, which will then rely entirely on jank protocols for its behavior. This currently cuts off the static object model from the dynamic object model, in the sense that the static objects rely on concepts and not protocols. However, I think that jank can still maintain the strong Clojure compatibility goal with this approach. ClojureScript, for example, doesn't implement all of Clojure JVM's protocol API. With this design, jank can implement all that ClojureScript does, which fits my overall mantra of &quot;If it works in both Clojure and ClojureScript, it should work in jank.&quot;<p>In the original announcement of this work, I noted that I would be investigating various ECS frameworks as a way of representing objects and behaviors. While I didn't go over them much here, I did a deep dive into them (in particular <a href="https://github.com/SanderMertens/flecs">FLECS</a> and <a href="https://github.com/skypjack/entt">EnTT</a>) and ruled them out. The primary reason is that they cannot address Concern 3, meaning they won't play well with garbage collection. The secondary reason would be that they would require multiple allocations per object, since behaviors are stored separately from entities, which is going to slow things down rather than speed them up.<p>Also, to those C++ devs wondering if I've just reimplemented <code>variant</code>, in some ways you're right. I benchmarked <code>boost::variant</code> against this implementation and it's equally fast for map <code>get</code> and <code>count</code>. However, variants are significantly slower to allocate than a <code>static_object</code>. Allocation speeds was the primary focus here, so I had to roll my own.<h2>Thanks again</h2><p>As a reminder, my work on jank this quarter is sponsored by <a href="https://www.clojuriststogether.org/">Clojurists Together</a>. Thank you to all of the members there who chose jank for this quarter. Thanks, also, to all of my <a href="https://github.com/sponsors/jeaye">Github sponsors</a>. Your continued support fuels jank's continued development!<p>I've already submitted a proposal for next quarter, to build out jank's namespace loading, class file generating, compilation cache, and class path handling. This leads into support for multi-file projects, leiningen integration, and AOT compilation, so if you'd like to see this work funded, reach out to me!</div></div></section></div><footer class="footer"><div class="container"><div class="columns has-text-centered"><div class="column has-text-centered"><aside class="menu"><p class="menu-label">Resources<ul class="menu-list"><li><a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li><a href="https://github.com/jank-lang/jank">Github</a><li><a href="https://jank-lang.org/blog/feed.xml">RSS</a></ul></aside></div></div><div class="container has-text-centered"><div class="content is-small"><p>© 2022 Jeaye Wilkerson | All rights reserved.</div></div></div></footer><noscript><p><img src="//matomo.jeaye.com/matomo.php?idsite=1&amp;rec=1"style="border:0"alt=""></p></noscript><script>for(var coll=document.getElementsByClassName("collapsible"),i=0;i<coll.length;i++)coll[i].addEventListener("click",function(){this.classList.toggle("active");var l=this.nextElementSibling;"block"===l.style.display?l.style.display="none":l.style.display="block"})</script>
<span class="line"><span style="color:#f8f8f2">}</span></span></code></pre><h2>The numbers</h2><p>This has been a lot of theory, but my aim here is to shed light on how these things work. Your feedback on whether or not this is a good level of detail is very welcome, so please reach out to me any way you can to let me know your thoughts. Now let's celebrate some wins!<p><figure><object data="/img/blog/2023-07-08-object-model/allocations-tagged.plot.svg"type="image/svg+xml"width="50%"><img src="/img/blog/2023-07-08-object-model/allocations-tagged.plot.svg"width="50%"></object></figure><p><p>Non-empty map allocations are down from 31ns to 17ns, which is marginally higher than Clojure's 16ns. As I mentioned, the Boehm GC isn't the fastest on the market, so there's more work to be done here. Still, this is a huge win. Remember that jank has been consistently beating Clojure in benchmarks <em>without</em> these changes, so this is going to set it well ahead.<p><figure><object data="/img/blog/2023-07-08-object-model/extra-benchmarks.plot.svg"type="image/svg+xml"width="50%"><img src="/img/blog/2023-07-08-object-model/extra-benchmarks.plot.svg"width="50%"></object></figure><p><p>Map operations such as <code>get</code> and <code>count</code> were already very fast, compared to Clojure. This is one area which allowed jank to make up for its slower allocations. However, with the static objects, visitors, and concepts, these benchmarks also dropped significantly.<p>I'm very excited to benchmark more once I've finished this work, but there's still more to do. This is only a half-way report!<h2>Status</h2><p>Initial prototyping and benchmarking is finished and I'm ripping apart jank's inheritance object model to replace it with the tagged object model. This is a large effort, which is why I wanted to get this done while jank was still young; it changes how every jank object works. At the end of the quarter, I'll be presenting more final numbers, as well as outlining future plans.<h2>Wrapping up</h2><p>You may be wondering how jank will handle dynamic objects now. For those, there will just be an enum value for dynamic, which will then rely entirely on jank protocols for its behavior. This currently cuts off the static object model from the dynamic object model, in the sense that the static objects rely on concepts and not protocols. However, I think that jank can still maintain the strong Clojure compatibility goal with this approach. ClojureScript, for example, doesn't implement all of Clojure JVM's protocol API. With this design, jank can implement all that ClojureScript does, which fits my overall mantra of &quot;If it works in both Clojure and ClojureScript, it should work in jank.&quot;<p>In the original announcement of this work, I noted that I would be investigating various ECS frameworks as a way of representing objects and behaviors. While I didn't go over them much here, I did a deep dive into them (in particular <a href="https://github.com/SanderMertens/flecs">FLECS</a> and <a href="https://github.com/skypjack/entt">EnTT</a>) and ruled them out. The primary reason is that they cannot address Concern 3, meaning they won't play well with garbage collection. The secondary reason would be that they would require multiple allocations per object, since behaviors are stored separately from entities, which is going to slow things down rather than speed them up.<p>Also, to those C++ devs wondering if I've just reimplemented <code>variant</code>, in some ways you're right. I benchmarked <code>boost::variant</code> against this implementation and it's equally fast for map <code>get</code> and <code>count</code>. However, variants are significantly slower to allocate than a <code>static_object</code>. Allocation speeds was the primary focus here, so I had to roll my own.<h2>Thanks again</h2><p>As a reminder, my work on jank this quarter is sponsored by <a href="https://www.clojuriststogether.org/">Clojurists Together</a>. Thank you to all of the members there who chose jank for this quarter. Thanks, also, to all of my <a href="https://github.com/sponsors/jeaye">Github sponsors</a>. Your continued support fuels jank's continued development!<p>I've already submitted a proposal for next quarter, to build out jank's namespace loading, class file generating, compilation cache, and class path handling. This leads into support for multi-file projects, leiningen integration, and AOT compilation, so if you'd like to see this work funded, reach out to me!<h2>Would you like to join in?</h2><ol><li>Join the community on <a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li>Join the design discussions or pick up a ticket on <a href="https://github.com/jank-lang/jank">GitHub</a><li>Considering becoming a <a href="https://github.com/sponsors/jeaye">Sponsor</a> ❤️<li><strong>Hire me full-time to work on jank!</strong></ol></div></div></section></div><footer class="footer"><div class="container"><div class="columns has-text-centered"><div class="column has-text-centered"><aside class="menu"><p class="menu-label">Resources<ul class="menu-list"><li><a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li><a href="https://github.com/jank-lang/jank">Github</a><li><a href="https://jank-lang.org/blog/feed.xml">RSS</a></ul></aside></div></div><div class="container has-text-centered"><div class="content is-small"><p>© 2022 Jeaye Wilkerson | All rights reserved.</div></div></div></footer><noscript><p><img src="//matomo.jeaye.com/matomo.php?idsite=1&amp;rec=1"style="border:0"alt=""></p></noscript><script>for(var coll=document.getElementsByClassName("collapsible"),i=0;i<coll.length;i++)coll[i].addEventListener("click",function(){this.classList.toggle("active");var l=this.nextElementSibling;"block"===l.style.display?l.style.display="none":l.style.display="block"})</script>
2 changes: 1 addition & 1 deletion blog/2023-08-26-object-model/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion blog/2023-10-14-module-loading/index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion blog/2023-12-17-module-loading/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -90,4 +90,4 @@
<span class="line"><span style="color:#f8f8f2"> },</span></span>
<span class="line"><span style="color:#f8f8f2"> source</span></span>
<span class="line"><span style="color:#f8f8f2"> );</span></span>
<span class="line"><span style="color:#f8f8f2">}</span></span></code></pre><p>The special case, which needs to check the ambiguous flag, incurs a performance cost, due to the if. Every other case is unaffected. This was a challenge to wrap my head around at first, but after I wrote out all the things I need to know, as well as a test suite for each of the cases, I could work toward a solution which addressed everything.<h2>What's next?</h2><p>Firstly, dynamic vars. Once those are implemented, I'll need to go through all of the different parts of the compiler and runtime to start filling in vars. This will allow everything from improved error messages by tracking file/line/function to cyclical dependency checks on module loading.<p>Also, in order for jank to operate alongside other Clojure dialects, we'll need to support reader conditionals on the <code>:jank</code> key. Currently, jank doesn't support any reader macros, so getting that system going will open up the door to things like <code>#()</code> and <code>#{}</code> being supported.<p>Finally, I'll be improving the interop interpolation syntax to be consistent with ClojureScript, adding meta hint support, and more. Stay tuned!<h2>Would you like to join in?</h2><ol><li>Join the community on <a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li>Join the design discussions or pick up a ticket on <a href="https://github.com/jank-lang/jank">GitHub</a><li>Considering becoming a <a href="https://github.com/sponsors/jeaye">Sponsor</a></ol></div></div></section></div><footer class="footer"><div class="container"><div class="columns has-text-centered"><div class="column has-text-centered"><aside class="menu"><p class="menu-label">Resources<ul class="menu-list"><li><a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li><a href="https://github.com/jank-lang/jank">Github</a><li><a href="https://jank-lang.org/blog/feed.xml">RSS</a></ul></aside></div></div><div class="container has-text-centered"><div class="content is-small"><p>© 2022 Jeaye Wilkerson | All rights reserved.</div></div></div></footer><noscript><p><img src="//matomo.jeaye.com/matomo.php?idsite=1&amp;rec=1"style="border:0"alt=""></p></noscript><script>for(var coll=document.getElementsByClassName("collapsible"),i=0;i<coll.length;i++)coll[i].addEventListener("click",function(){this.classList.toggle("active");var l=this.nextElementSibling;"block"===l.style.display?l.style.display="none":l.style.display="block"})</script>
<span class="line"><span style="color:#f8f8f2">}</span></span></code></pre><p>The special case, which needs to check the ambiguous flag, incurs a performance cost, due to the if. Every other case is unaffected. This was a challenge to wrap my head around at first, but after I wrote out all the things I need to know, as well as a test suite for each of the cases, I could work toward a solution which addressed everything.<h2>What's next?</h2><p>Firstly, dynamic vars. Once those are implemented, I'll need to go through all of the different parts of the compiler and runtime to start filling in vars. This will allow everything from improved error messages by tracking file/line/function to cyclical dependency checks on module loading.<p>Also, in order for jank to operate alongside other Clojure dialects, we'll need to support reader conditionals on the <code>:jank</code> key. Currently, jank doesn't support any reader macros, so getting that system going will open up the door to things like <code>#()</code> and <code>#{}</code> being supported.<p>Finally, I'll be improving the interop interpolation syntax to be consistent with ClojureScript, adding meta hint support, and more. Stay tuned!<h2>Would you like to join in?</h2><ol><li>Join the community on <a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li>Join the design discussions or pick up a ticket on <a href="https://github.com/jank-lang/jank">GitHub</a><li>Considering becoming a <a href="https://github.com/sponsors/jeaye">Sponsor</a> ❤️<li><strong>Hire me full-time to work on jank!</strong></ol></div></div></section></div><footer class="footer"><div class="container"><div class="columns has-text-centered"><div class="column has-text-centered"><aside class="menu"><p class="menu-label">Resources<ul class="menu-list"><li><a href="https://clojurians.slack.com/archives/C03SRH97FDK">Slack</a><li><a href="https://github.com/jank-lang/jank">Github</a><li><a href="https://jank-lang.org/blog/feed.xml">RSS</a></ul></aside></div></div><div class="container has-text-centered"><div class="content is-small"><p>© 2022 Jeaye Wilkerson | All rights reserved.</div></div></div></footer><noscript><p><img src="//matomo.jeaye.com/matomo.php?idsite=1&amp;rec=1"style="border:0"alt=""></p></noscript><script>for(var coll=document.getElementsByClassName("collapsible"),i=0;i<coll.length;i++)coll[i].addEventListener("click",function(){this.classList.toggle("active");var l=this.nextElementSibling;"block"===l.style.display?l.style.display="none":l.style.display="block"})</script>
Loading

0 comments on commit 3387014

Please sign in to comment.