<story><title>How the JVM compares strings on x86 using pcmpestri</title><url>http://jcdav.is/2016/09/01/How-the-JVM-compares-your-strings/</url></story><parent_chain></parent_chain><comment><author>lvh</author><text>The JVM has a number of cool features that enable you to efficiently drop down into C (FFI) yourself: these tricks aren&amp;#x27;t just for built-ins.&lt;p&gt;A quick overview:&lt;p&gt;- First there was JNI. JNI means that you write method stubs with the &amp;quot;native&amp;quot; keyword. Then you run javah, which gives you some C glue code that you eventually need to compile. This is very fast, but it&amp;#x27;s annoying because now you need a tool chain everywhere. The Python equivalent of this is roughly writing CPython extensions.&lt;p&gt;- People thought JNI was annoying, so Sun developed JNA. JNA lets you bind a library directly: all the magic comes with the JVM, and you can just dlopen something and call some syms. This works fine, but it&amp;#x27;s very slow. The Python equivalent of this is roughly ctypes.&lt;p&gt;- Most recently, there&amp;#x27;s JNR and jnr-ffi. They do a very clever trick: you use JNI to get to libffi, and then you use libffi to call everything else performantly. You get roughly the performance of JNI, with the convenience of JNR. The Python equivalent of this is roughly cffi.&lt;p&gt;JNR is way more usable than I thought it would be. I develop caesium[0], a Clojure libsodium binding, using jnr-ffi and a pile of macros. I gave a talk about this at Clojure Conj (recording [1], slides [2]) if you&amp;#x27;re interested.&lt;p&gt;To be fair: this code uses intrinsics, which means that it&amp;#x27;s implemented differently than the three methods shown above, so it&amp;#x27;s still slightly different. It&amp;#x27;s just not different in a way that&amp;#x27;s meaningful to you unless you&amp;#x27;re working on the JVM itself :)&lt;p&gt;[0]: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;lvh&amp;#x2F;caesium&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;github.com&amp;#x2F;lvh&amp;#x2F;caesium&lt;/a&gt;
[1]: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;dev-videos.com&amp;#x2F;videos&amp;#x2F;Lf-M1ZH6KME&amp;#x2F;Using-Clojure-with-C-APIs-for-crypto-and-more--lvh&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;dev-videos.com&amp;#x2F;videos&amp;#x2F;Lf-M1ZH6KME&amp;#x2F;Using-Clojure-with...&lt;/a&gt;
[2]: &lt;a href=&quot;https:&amp;#x2F;&amp;#x2F;www.lvh.io&amp;#x2F;CCryptoClojure&amp;#x2F;#&amp;#x2F;sec-title-slide&quot; rel=&quot;nofollow&quot;&gt;https:&amp;#x2F;&amp;#x2F;www.lvh.io&amp;#x2F;CCryptoClojure&amp;#x2F;#&amp;#x2F;sec-title-slide&lt;/a&gt;</text></comment>
<story><title>How the JVM compares strings on x86 using pcmpestri</title><url>http://jcdav.is/2016/09/01/How-the-JVM-compares-your-strings/</url></story><parent_chain></parent_chain><comment><author>pcwalton</author><text>One thing I learned about pcmpxstrx is that it&amp;#x27;s surprisingly slow: latency of 10-11 cycles and reciprocal throughput of 3-5 cycles on Haswell according to Agner&amp;#x27;s tables, depending on the precise instruction variant. The instructions are also limited in the ALU ports they can use. Since AVX2 has made SIMD on x86 fairly flexible, it can sometimes not be worth using the string comparison instructions if simpler instructions suffice: even a slightly longer sequence of simpler SIMD instructions sometimes beats a single string compare.&lt;p&gt;The SSE 4.2 string comparison instructions still have their uses, but it&amp;#x27;s always worth testing alternate instruction sequences when optimizing code that might use them.</text></comment>