<?xml version="1.0" encoding="utf-8" ?><rss version="2.0"><channel><title>Cupdev</title><link href="https://cupdev.net/feed.xml" rel="self" type="application/rss+xml"></link><link>https://cupdev.net</link><description>Duplicorn</description><!--pubDate= articles[0].rfc822date--><generator>Cupdev Website - http://cupdev.net</generator><language>en</language><item><title>Quantum Hardening Cryptographic Protocols</title><link>https://cupdev.net/blog/014_quantumhardening.html</link><pubDate>Thu, 18 Jun 2020 20:27:13 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/014_quantumhardening.html</guid><author></author><description>&lt;p&gt;I recently did some work as a side project for company called Patero that involved creating quantum hardened prototype of one of their products. This post discusses how to secure state-of-the-art cryptographic protocols against attacks from (future) quantum computers. It starts off with an introduction to how crypto protocols in general are constructed, to serve as an introduction for those of us who haven&amp;#39;t done much crypto work in the past.&lt;/p&gt;
&lt;iframe width=&quot;1024&quot; height=&quot;576&quot; src=&quot;https://media.ccc.de/v/DiVOC-19-quantum-en/oembed&quot; frameborder=&quot;0&quot; allowfullscreen&gt;&lt;/iframe&gt;

&lt;p&gt;&lt;a href=&quot;https://media.ccc.de/v/DiVOC-19-quantum&quot;&gt;Video auf Deutsch&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;In addition to my role at Adobe, I also do occasional freelance work as an software engineer focusing on rust/c++/embedded and cryptographic work. One of the clients I usually do work for is Patero, who are working on integrating quantum hardened secure communication modules
in mobile devices, IoT and critical infrastructure. One of their projects is an end-to-end encrypted, hardware-based cryptography module for securing mobile calls and communications in general even in the face of a compromised operating system. To further this project I was asked to create a quantum hardened version of this chip for evaluation purposes; first identifying those parts of their cryptographic protocol&lt;sup&gt;&lt;a href=&quot;#foot1&quot;&gt;1&lt;/a&gt;&lt;/sup&gt; that would break when quantum computer based attacks become feasible and finding solutions to harden the protocol against such attacks. This blog post discusses the general approach usually taken when hardening modern crypto protocols.&lt;/p&gt;
&lt;p&gt;To be clear here, this post is about Quantum Hardening also known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Post-quantum_cryptography&quot;&gt;Post Quantum Cryptography&lt;/a&gt;; that is the study of how to secure the sort of crypto protocols used in normal machines against cryptanalysis (attacks) using quantum computers. This post is not about &lt;a href=&quot;https://en.wikipedia.org/wiki/Quantum_computing&quot;&gt;Quantum Computing&lt;/a&gt; (the study of how to use quantum computers to solve problems) and it is not about &lt;a href=&quot;https://en.wikipedia.org/wiki/Quantum_cryptography&quot;&gt;Quantum Cryptography&lt;/a&gt; (the study of using quantum effects to do cryptography).&lt;/p&gt;
&lt;p&gt;The first part of this post is dedicated to revisiting some cryptography fundamentals the basic make up of modern day crypto protocols so even readers less familiar with the subject can take away something from this post. Jump down to &lt;a href=&quot;#quantum-attacks-grover-s-algorithm&quot;&gt;Quantum Attacks: Grover&amp;#39;s algorithm&lt;/a&gt; if you are already familiar with the inner workings of modern cryptographic transport protocols.&lt;/p&gt;
&lt;h2 id=&quot;summary-how-to-quantum-harden-in-a-hurry&quot;&gt;Summary: How to quantum harden in a hurry&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_34.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_34.png&quot; alt=&quot;Slide: Summary of the commonly used primitives in different stages of a cryptographic transport protocol.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;The availability of practical quantum computers would render all commonly used asymmetric cryptography used today insecure. Since pretty much all modern day cryptographic protocols (like HTTPS, TLS&lt;sup&gt;&lt;a href=&quot;#foot5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt;, or SSH&lt;sup&gt;&lt;a href=&quot;#foot6&quot;&gt;6&lt;/a&gt;&lt;/sup&gt;) rely on asymmetric crypto as a vital component, these protocols will also become insecure. Symmetric cryptography is also affected but doubling key sizes provides an easy fix. Updating asymmetric crypto to be secure again will require the introduction of entirely new cryptographic primitives.&lt;/p&gt;
&lt;p&gt;This is not a large problem now, because quantum computers are currently impractical, but their technology may advance in the coming years or decades enough to make quantum computer based attacks feasible; we should prepare for this point in time soon and some data needs to remain securely encrypted over the next decades, which is why quantum hardened cryptography is starting to become an important subject.&lt;/p&gt;
&lt;p&gt;The process to develop post quantum cryptography is &lt;a href=&quot;https://csrc.nist.gov/Projects/Post-Quantum-Cryptography/Post-Quantum-Cryptography-Standardization&quot;&gt;currently ongoing&lt;/a&gt;.
For key exchanges, Classic McElice is a robust choice, but its memory requirements are prohibitive for many platforms. Failing that FrodoKEM is not a terrible choice.
Post quantum signature schemes are not as relevant because they are only relevant to thwart online attacks (and for those you need a quantum computer now). Still Sphincs+ is probably not a particularly bad choice, but again the memory requirements are pretty tough to meet.&lt;/p&gt;
&lt;p&gt;Any post quantum crypto primitive is currently suspect and should not be used on it&amp;#39;s own; there is significant risk the key exchange or signature scheme could be &lt;strong&gt;insecure against classical computers&lt;/strong&gt;, meaning that you would be &lt;strong&gt;worse off than with state of the art protocols&lt;/strong&gt; using such a primitive. Quantum hardened algorithms should only be used together with classical, well analyzed primitives. Employ &lt;a href=&quot;#robust-combiners&quot;&gt;robust combiners&lt;/a&gt; for this purpose. &lt;a href=&quot;https://openquantumsafe.org/&quot;&gt;Open Quantum Safe&lt;/a&gt; is probably not a bad source of implementations for post quantum primitives.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Post Quantum Crypto should be limited to research and evaluation use cases at the moment except in very special circumstances. Even though redundant constructions using robust combiners are probably safe, the act of updating protocols, changing implementations may introduce implementation errors, &lt;a href=&quot;https://en.wikipedia.org/wiki/Side-channel_attack&quot;&gt;side channels&lt;/a&gt;, or operational problems which can easily render your crypto system as a whole insecure. Even if extremely stringent measures are taken to publicly vet the resulting protocol and implementation, this risk persists.&lt;/strong&gt;&lt;/p&gt;
&lt;h2 id=&quot;what-is-crypto&quot;&gt;What is crypto&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_2.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_2.png&quot; alt=&quot;Slide: Alice sending the message &quot;I like your cat ears&quot; to Berta.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;On a basic level, the goal of cryptography is the protection of private messages sent over public channels from interception by a third party. In the slide shown above, Alice would like to send a message (&amp;quot;I like your cat ears!&amp;quot;) to Berta; since this message is confidential, she would like to cryptographically protect the message.&lt;/p&gt;
&lt;p&gt;Other use cases have even more stringent requirements: imagine sending a message requesting a wire transfer via online banking; you would not want an adversary to be able to send a transfer in your name or modify the message in somehow. This is why all crypto protocols should fulfill all three properties: Confidentiality (only recipient can read it), Authentication (only you can send), as well as Data Integrity (message cannot be changed). &lt;/p&gt;
&lt;h2 id=&quot;archaic-ciphers-rotation-cipher&quot;&gt;Archaic Ciphers: Rotation Cipher&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_4.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_4.png&quot; alt=&quot;Slide: Rotation Ciphers.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Modern cryptographic ciphers can be quite hard to understand, so in order to illustrate how basic encryption works, we will take a look at some historical ciphers. The first cipher I would like to introduce is the Caesar Cipher; called that because Julius Caesar was one of the users of this cipher. Before we can encrypt some text using this cipher, we first have to assign a number to each letter of our alphabet and choose a key. Then we simply add the key to each character or subtract it to decrypt our cipher text.&lt;/p&gt;
&lt;p&gt;Using 4 as our key we get the following conversion table:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;space/0 → d/4
a/1 → e/5
b/2 → f/6
...
x/24 → a/1
y/25 → b/2
z/26 → c/2&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Our text &amp;quot;i like your cat ears&amp;quot; turns into &amp;quot;mdpmoidbsyvdgexdievw&amp;quot;, which cannot be red without decryption.&lt;/p&gt;
&lt;p&gt;So how hard is breaking this cipher? Not very hard as it turns out: There is one kind of attack that can always be performed; just try every one of our 27 possible keys until you find one that works. This is called a brute force attack and works well for any cipher whose key space (that is the number of possible keys) is very small; other, more advanced ciphers with a very large key space require more sophisticated sorts of attack.&lt;/p&gt;
&lt;h2 id=&quot;archaic-ciphers-substitution-cipher&quot;&gt;Archaic Ciphers: Substitution Cipher&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_6.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_6.png&quot; alt=&quot;Slide: Substitution Ciphers.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Substitution ciphers fit that bill; similar to how a rotation cipher works, one character maps to another random character from our alphabet. Basically instead of rotating our alphabet by a fixed offset, we shuffle it. This makes rotation ciphers a specific case of substitution ciphers.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;alphabet: &amp;quot; abcdefghijklmnopqrstuvwxyz&amp;quot;
key:      &amp;quot;jxngzdtlciu wemkavbfsoqprhy&amp;quot;

plaintext:  &amp;quot;i like your cat ears&amp;quot;
ciphertext: &amp;quot;ijwi djhkobjgxsjdxbf&amp;quot;&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Shuffling our alphabet yields a much larger key space; $27!$ (that is 27 factorial, $27&lt;em&gt;26&lt;/em&gt;...&lt;em&gt;2&lt;/em&gt;1$) to be precise or roughly $10^28$ (a 10 with 28 zeroes) keys, which is far too many keys for us to try each one. Even one or many computers can not try this many keys, so attacking this cipher will require a more advanced attack: Notice how our cipher text contains the letter &lt;code&gt;J&lt;/code&gt; a lot? We can use that and infer that &lt;code&gt;J&lt;/code&gt; must map to a particularly common character -- space in our case. By using statistical analysis – that measuring the frequency of each character in our cipher text – we can simply look up which character is this frequent in the English language and break the cipher this way. This works because vowels for instance appear much more frequently than consonants.&lt;/p&gt;
&lt;h2 id=&quot;archaic-ciphers-transposition-cipher&quot;&gt;Archaic Ciphers: Transposition Cipher&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_8.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_8.png&quot; alt=&quot;Slide: Transposition Ciphers.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Finally, let&amp;#39;s look at a slightly different sort of cipher; while substitution ciphers shuffle our alphabet, a transposition cipher shuffles the actual text turning the cipher text into an anagram of the plain text.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key:        31542
plaintext:  HELLO
ciphertext: EOHLL&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unlike with our previous cipher the problem with this cipher is immediately visible: &amp;quot;eohll&amp;quot; being an anagram of &amp;quot;hello&amp;quot; is pretty obvious. This problem gets worse when the key is used multiple times.&lt;/p&gt;
&lt;h2 id=&quot;modern-cipher-aes&quot;&gt;Modern Cipher: AES&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_10.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_10.png&quot; alt=&quot;Slide: The modern AES Cipher.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Having looked at some archaic examples of ciphers, let&amp;#39;s now jump into the 21st century and take a look at an example of a modern cipher. The Advanced Encryption Standard is widely used today (although there are &lt;a href=&quot;https://en.wikipedia.org/wiki/Salsa20&quot;&gt;alternatives&lt;/a&gt;). there is a good chance this website was transferred to you via an AES encrypted channel. It is a block cipher; meaning the data is chopped into fixed size segments which are separately encrypted. All operations used by the cipher are reversible, so to decrypt the data, all operations are applied in reverse.&lt;/p&gt;
&lt;p&gt;Internally, AES uses a &lt;a href=&quot;https://en.wikipedia.org/wiki/Substitution%E2%80%93permutation_network&quot;&gt;Substitution-Permutation-Network&lt;/a&gt;. The big round plus with a circle you can see is an &lt;a href=&quot;https://en.wikipedia.org/wiki/XOR_gate&quot;&gt;XOR&lt;/a&gt; operation; this is similar to the rotation cipher (rotation or &lt;a href=&quot;https://en.wikipedia.org/wiki/Modular_arithmetic&quot;&gt;modular addition&lt;/a&gt; in binary is just xor), except that every bit of data is rotated with a single bit from the key. The boxes labeled S represent substitution steps; here four bit long words of data are replaced according to a built in lookup table. Finally the step labeled P is a transposition step; here the results of the substitution are shuffled according to a predefined pattern.&lt;/p&gt;
&lt;p&gt;Only the xor step actually combines the data with the key; the substitution and permuatation steps are not really encryption steps per say since their &amp;quot;keys&amp;quot; are known to any attackers. Instead they basically scramble the data, ensuring that each bit in the cipher text is influenced by every bit of plain text and key. Applying these three steps multiple times effectively obscures the relationship between ciphertex, key and plaintext, to the point that statistical methods cannot be used to uncover their relationship. Every bit of the output depends on every bit of the input and every bit of the key; changing just one bit in the input or key should change roughly 50% of the output bits.&lt;/p&gt;
&lt;p&gt;Note that we left out a lot of the steps required to really make a secure block cipher; e.g. one problem with the above description is that the same input block and key will produce the same output. This is unacceptable since this would allow attackers to detect when &lt;a href=&quot;https://en.wikipedia.org/wiki/Block_cipher_mode_of_operation#Electronic_codebook_(ECB)&quot;&gt;two blocks are the same&lt;/a&gt;, there are solutions to this problem but we won&amp;#39;t go into detail here.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_11.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_11.png&quot; alt=&quot;Slide: A basic encryption protocol.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Now since we have a cipher that is actually secure, we can start to encrypt something, we just need a key! So, Alice does create a key and transmits it to Berta over a secure channel. Our key exchange here is really the most important part; if the key is intercepted all our efforts will be wasted. The adversary will be able to decrypt all past, present, and future messages transmitted using this key. Once the key has been exchanged however, we can start sending data, securely, over untrusted channels.&lt;/p&gt;
&lt;h2 id=&quot;message-authentication-codes&quot;&gt;Message Authentication Codes&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_12.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_12.png&quot; alt=&quot;Slide: Message authentication codes.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;There is one – actually there are many problems with the protocol above, however one particularly bad one is that the protocol is not authenticated; meaning, that while an attacker could never correctly encrypt data (they would need the key), they could flip bits in the ciphertext or even send entirely random data and Berta would not automatically notice.&lt;/p&gt;
&lt;p&gt;To remedy this problem, a message authentication code is used; the authentication tag generated by this function is a bit of redundant data, added to the message to prevent tampering. This tag can only be generated by someone who knows the symmetric key, so an attacker could only guess at the correct code.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_13.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_13.png&quot; alt=&quot;Slide: Authenticated crypto protocol.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Our protocol is still almost the same as it was before: having exchanged a shared key, Alice can now start encrypting data. She uses the shared key to encrypt our message. Before sending it, she also uses the message authentication code to generate a short authentication tag over the cipher text using the key. Both the cipher text as well as the message authentication code are sent to Berta who checks the auth tag by generating an auth tag of her own and comparing the one sent along with the message. Having successfully established that the message is authentic, she continues to decrypt the data as before.&lt;/p&gt;
&lt;h2 id=&quot;key-derivation-functions&quot;&gt;Key derivation Functions&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_14.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_14.png&quot; alt=&quot;Slide: Key Derivation Functions.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;We now have achieved authenticated encryption; our crypto system is secure as long as the shared key is exchanged securely.&lt;/p&gt;
&lt;p&gt;That is all well and good, however secure key transmission is actually not that easy to achieve. Sounds easy enough, but in practice it usually the key consists of around one hundred completely random characters; ciphers need high quality keys to function properly. A short key, or a key that has obvious patterns in it will not do. Hardly any messenger would be able to remember such a random figure; you could write it down, but then you may loose the piece of paper so this is not a good solution either.&lt;/p&gt;
&lt;p&gt;Luckily, key derivation functions can at least help us lessen that problem; basically a key derivation function can take a string of random data and bring it into the format of a high quality key, provided of course that the input actually contains enough random information. The output will have the needed length, it will look random&lt;sup&gt;&lt;a href=&quot;#foot2&quot;&gt;2&lt;/a&gt;&lt;/sup&gt; and when used with a password, it should be slow to compute, just to thwart attacks testing lot&amp;#39;s of commonly used passwords.&lt;/p&gt;
&lt;p&gt;Key derivation functions really provide flexibility; you could choose a long sentence as your key (easier for your messenger to remember) or you could sent multiple keys and combine them using the KDF; as long as one key was not intercepted, the generated key will still be secure.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_15.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_15.png&quot; alt=&quot;Slide: Using KDFs to derive a shared key.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;To integrate this key derivation function in our protocol, Alice chooses a password instead of the key itself and transmits it to Berta. Both parties run the key derivation function to generate the actual key and can now transmit data as they did in the previous two protocols.&lt;/p&gt;
&lt;h2 id=&quot;asymmetric-cryptography&quot;&gt;Asymmetric Cryptography&lt;/h2&gt;
&lt;p&gt;Using a key derivation function drastically simplifies key transmission, without actually solving our core problem: We still need to transmit our keys via a secure channel. Creating a secure channel is really hard; the entire point of this exercise is to create a secure channel, so wouldn&amp;#39;t it be nice to be able to sidestep this problem? Luckily, there is a solution and that solution is called asymmetric cryptography.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_16.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_16.png&quot; alt=&quot;Slide: Asymmetric Cryptography.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;While in symmetric crypto there is just one key that is shared between both our parties, in asymmetric crypto there is two keys; one that can be absolutely public&lt;sup&gt;&lt;a href=&quot;#foot3&quot;&gt;3&lt;/a&gt;&lt;/sup&gt; and one that is to be kept absolutely private; not even shared with your communication partner. The public key can be used by anyone to encrypt data they would like to transmit to you, while only you could decrypt the data again. There also is a corresponding signature scheme that can be used to proof that you are really the sender of some data; only you can sign a message using the private signature key, but anyone can validate the signature against your public key (notice to how this is somewhat similar in purpose to an authentication tag).&lt;/p&gt;
&lt;p&gt;In practice, when sending a message, you would encrypt using the recipients public key and sign using your own secret key and since public key crypto is actually a bit inefficient, you would generate a random shared key, encrypt and authenticate the data using that and finally encrypt and sign the symmetric key using asymmetric cryptography.&lt;/p&gt;
&lt;p&gt;Combining asymmetric and symmetric crypto in such a way to gain both – the performance of symmetric cryptography and the flexibility of public key cryptography – is called &lt;a href=&quot;https://en.wikipedia.org/wiki/Hybrid_cryptosystem&quot;&gt;Hybrid Cryptography&lt;/a&gt;. When asymmetric encryption is used to encrypt a shared key for further encryption, this is called a &lt;a href=&quot;https://en.wikipedia.org/wiki/Key_encapsulation&quot;&gt;Key Encapsulation Method&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;diffie-hellmann-key-exchange&quot;&gt;Diffie Hellmann Key Exchange&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_17.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_17.png&quot; alt=&quot;Slide: The Diffie Hellmann Key Exchange.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Most cryptographic connections today are online – meaning it is possible to quickly send messages back and forth. Key encapsulation can be used to exchange the keys for such a connection, however there is a better way: The Diffie Hellmann Key Exchange; this is a function that produces a shared key directly using my own private key and your public key. To execute the key exchange, both parties generate a random key pair and transmit their public key before executing the Diffie Hellman function. That&amp;#39;s it. Just two packets to transmit and the secret never actually has to be transmitted over the wire.&lt;/p&gt;
&lt;h2 id=&quot;putting-it-together-modern-day-crypto-protocols&quot;&gt;Putting it together: Modern day Crypto protocols&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_18.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_18.png&quot; alt=&quot;Slide: The make up of a modern day crypto protocol.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Now, using both symmetric and asymmetric cryptography we can build a cryptographic protocol like this:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Alice and Berta generate random Diffie Hellmann key pairs, and exchange their public keys and generate a secret using those keys.&lt;/li&gt;
&lt;li&gt;They establish each others authenticity; often this involves using a digital signature scheme, although different ways to achieve this exist.&lt;/li&gt;
&lt;li&gt;They use a key derivation function to generate a good key using the secret they just exchanged.&lt;/li&gt;
&lt;li&gt;They use the key to encrypt data.&lt;/li&gt;
&lt;li&gt;And a message authentication code to make sure the data is not tampered with.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;That&amp;#39;s it. This is pretty much how state-of-the-art cryptographic protocols work; there is a good chance your browser is used something like this to download this blog post.&lt;/p&gt;
&lt;h2 id=&quot;quantum-attacks-grover-s-algorithm&quot;&gt;Quantum Attacks: Grover&amp;#39;s algorithm&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_19.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_19.png&quot; alt=&quot;Slide: Grover' Algorithm.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;There are two ways that quantum computers can attack modern cryptography; the first and less important of the two is grovers algorithm. As we discussed before, there is one attack that works on every cryptographic method: A &amp;quot;brute force&amp;quot; attack which is just a fancy word for trying every possible key until you find one that works. In computer science this is known as a &amp;quot;linear search&amp;quot; – the most basic search algorithm. Given a million possible keys it would take five hundred thousand tries on average to find the correct one; the formula is just $^N/_2$ where $N$ is the number of keys.&lt;/p&gt;
&lt;p&gt;Grover&amp;#39;s algorithm is the generic quantum search; this takes (don&amp;#39;t ask me how) just a thousand tries for a million possible keys: While
the generic classical search takes $^N/_2$ tries, quantum search just takes $sqrt(N)$ attempts on average, so it is much faster, or one thousand tries given a million possible keys.
Luckily, we can just double our key size from six decimal places to twelve (or from 128 bits to 256 bits for actual cryptographic algorithms) to achieve the same security level as before.&lt;/p&gt;
&lt;p&gt;So while Grover&amp;#39;s algorithm can be used against any cryptographic algorithm, there is a relatively easy fix.&lt;/p&gt;
&lt;h2 id=&quot;quantum-attacks-shor-s-algorithm&quot;&gt;Quantum Attacks: Shor&amp;#39;s algorithm&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_20.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_20.png&quot; alt=&quot;Slide: Shor's Algorithm.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Shor&amp;#39;s algorithm presents a bigger problem; pretty much all asymmetric cryptography&lt;sup&gt;&lt;a href=&quot;#foot4&quot;&gt;4&lt;/a&gt;&lt;/sup&gt; used today is either based on the &lt;a href=&quot;https://en.wikipedia.org/wiki/Discrete_logarithm&quot;&gt;Discrete Logarithm Problem&lt;/a&gt; or the difficulty of &lt;a href=&quot;https://en.wikipedia.org/wiki/Integer_factorization&quot;&gt;factorizing integers&lt;/a&gt;. Both problems can be solved very efficiently using Shor&amp;#39;s algorithm.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_21.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_21.png&quot; alt=&quot;Slide: Modern crypto protocols are broken against quantum computers.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;This means: Our handshake is broken; it is entirely insecure against attacks from quantum computers. This is why it is commonly said that quantum computers break all modern crypto; the symmetric part is fine, but if the handshake is insecure the symmetric key will be known so the protocol is insecure as a whole&lt;/p&gt;
&lt;h2 id=&quot;quantum-attacks-are-they-feasible-&quot;&gt;Quantum Attacks: Are they feasible?&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_22.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_22.png&quot; alt=&quot;Slide: Feasibility of quantum computer based attacks.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Now, this sounds really bad until you remember that practical quantum computers simply do not exist at the moment. They are really expensive, need to be cooled using cryogenics and just have on the order of 50 to 60 quantum bits; you would need thousands of quantum bits to even attempt breaking modern crypto. Attacking modern crypto with &lt;a href=&quot;https://en.wikipedia.org/wiki/ENIAC&quot;&gt;ENIAC&lt;/a&gt; (a very early computer) seems more feasible than using quantum computer at this time.&lt;/p&gt;
&lt;p&gt;However, there is a good chance practical quantum computers will arrive in the next decades, so it is good to be prepared. Besides, in addition to all the cat videos, there is some data stored and transmitted now that we would like to &lt;em&gt;remain&lt;/em&gt; secure in thirty to forty years; think financial or medical records. An attacker could simply commit all data they can get their hands on to cold storage and wait until quantum computers are advanced enough to decrypt it; a concept that is called &amp;quot;store now break later&amp;quot;. To thwart this, we should really start to use post quantum crypto as soon as possible.&lt;/p&gt;
&lt;h2 id=&quot;quantum-hardening-currently-in-early-alpha&quot;&gt;Quantum Hardening: Currently in early alpha&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_23.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_23.png&quot; alt=&quot;Slide: Feasibility of quantum computer based attacks.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;To this end, the National Institute of Standards and Technology – the same organization that standardized SHA, AES, and RSA – has organized a competition to find suitable post quantum crypto algorithms. The competition started 2017 and is expected to take half a decade more. In the beginning around 90 candidates where submitted, but a lot of them where discovered to be insecure in the first couple of hours after submission. Some similar ones have also been merged, but 26 are left and are now candidates in round two of the competition; you can follow the progress &lt;a href=&quot;https://csrc.nist.gov/Projects/Post-Quantum-Cryptography/Post-Quantum-Cryptography-Standardization&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_24.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_24.png&quot; alt=&quot;Slide: Feasibility of quantum computer based attacks.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;The new primitives include signature schemes as well as key encapsulation methods and a single example &lt;a href=&quot;https://en.wikipedia.org/wiki/Supersingular_isogeny_key_exchange&quot;&gt;SIKE&lt;/a&gt; of a replacement for Diffie Hellmann style key exchanges. They are based on problems like Learning With Errors, Elliptic Curve Isogeny, or the difficulty of decoding Error Correction Codes (as if I knew what the first two meant).&lt;/p&gt;
&lt;p&gt;Experimental &lt;a href=&quot;https://en.wikipedia.org/wiki/CECPQ1&quot;&gt;implementations&lt;/a&gt; of NewHope, NTRU, and SIKE where created for TLS&lt;sup&gt;&lt;a href=&quot;#foot5&quot;&gt;5&lt;/a&gt;&lt;/sup&gt; and used in the
Chrome browser and some servers with good results. BSI (the German equivalent of the American NIST) &lt;a href=&quot;https://www.bsi.bund.de/DE/Themen/Kryptografie_Kryptotechnologie/Kryptografie/PostQuantenKryptografie/postquantenkryptografie_node.html&quot;&gt;recommends&lt;/a&gt;
using FrodoKEM or ClassicMcElice if you so choose to use quantum hardened key exchanges. Post Quantum Signature Schemes haven&amp;#39;t received as much attention because they are not quite as relevant for protection from &amp;quot;save now decrypt later&amp;quot; style attacks. They protect from man in the middle attacks which have to be performed live – just at the time the connection is being created.&lt;/p&gt;
&lt;h2 id=&quot;robust-combiners&quot;&gt;Robust Combiners&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_27.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_27.png&quot; alt=&quot;Slide: Using classical and quantum hardened primitives together.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Post quantum crypto primitives are new and shiny; with crypto as with databases this is a bad thing. It means we can not really trust these algorithms&amp;#39; security as there is still a good chance some of these will turn out to be insecure in future cryptanalytic works. If we were to rely on them alone, our cryptographic protocol may not only be susceptible to quantum attacks but to classical attacks as well. This would be a total failure.&lt;/p&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_28.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_28.png&quot; alt=&quot;Slide: Concat combiner.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Optimally we would find some way to combine state-of-the-art asymmetric cryptographic primitives with post quantum ones, similar to how we combined symmetric and asymmetric cryptography to get the best from both worlds. There is a way and the study of how to do this securely is called &amp;quot;Robust Combiners&amp;quot;; enter the term in the search engine of your choice and you will find that there are a lot of constructions that are unsafe – proven to be bad. One of the few things that has been show to work as a robust combiner is the concatenation combiner: Simply perform both key exchanges; and concatenate the secrets they produce. You will end up with a secret twice the size, which is not really a problem because we just use it as the input for our key derivation function anyways. Combining signature schemes is trivial because we can just use both; test each signature and if one of the tests fails, consider the signature to be invalid.&lt;/p&gt;
&lt;h2 id=&quot;putting-it-together-the-make-up-of-a-quantum-hardened-crypto-protocol&quot;&gt;Putting it together: The make up of a quantum hardened crypto protocol&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_30.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_30.png&quot; alt=&quot;Slide: Post quantum combined cryptographic protocol.&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Now, finally, we can actually come up with a quantum hardened cryptographic protocol: Perform two key exchanges – one post quantum key exchange
and one legacy key exchange; concat their secrets. Perform two authentication steps; again, one quantum hardened and one legacy authentication.
Use your key derivation function to format the combined secrets and start encrypting data. That&amp;#39;s it.&lt;/p&gt;
&lt;h2 id=&quot;choosing-primitives-and-implementations&quot;&gt;Choosing primitives and implementations&lt;/h2&gt;
&lt;object type=&quot;image/svg+xml&quot; data=&quot;/blog/014_quantumhardening/slide_33.svg&quot;&gt;
 &lt;img src=&quot;/blog/014_quantumhardening/slide_33.png&quot; alt=&quot;Slide: Which algorithms, which implementations should be used?&quot;/&gt;
&lt;/object&gt;

&lt;p&gt;Should you ever be given the challenge to quantum harden a protocol, you will find yourself trying to decide which cipher to use. Unfortunately, there is no straight answer to this question yet; the jury is still out on which post quantum primitives will turn out to be secure and which ones have vital flaws. If you had to choose, Classic McEleice is based on a &lt;a href=&quot;https://en.wikipedia.org/wiki/McEliece_cryptosystem&quot;&gt;crypto system invented in 1979&lt;/a&gt; that has been analyzed pretty extensively. It is probably secure, but its key sizes are huge, too huge to fit into the memory of the chip I was programming. If memory is not a giant constraint for your application, use Classic McEleice. FrodoKEM is not as well analyzed, but probably not a terrible choice either and it&amp;#39;s keys are still large, but not prohibitively so at least for the chip I was using. Sphincs+ is probably not a terribly choice for a post quantum signature algorithm, but it&amp;#39;s signatures are around 40Kb large, so probably too large for a lot of platforms especially when trying to establish a &lt;a href=&quot;https://en.wikipedia.org/wiki/Chain_of_trust&quot;&gt;chain of trust&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;As for implementations, &lt;a href=&quot;https://doc.libsodium.org/&quot;&gt;libsodium&lt;/a&gt; is what you should use in most applications for pre quantum algorithms and symmetric crypto. It provides a very small, secure set of cryptographic functions and follows usable security API design practices which make it comparatively hard to create unsafe constructions. There are alternatives implementing a wider array of cryptographic primitives, but often these include unsafe primitives or ones which are only secure when used in very specific ways. A limited set of choices can be a good thing.&lt;/p&gt;
&lt;p&gt;Finally, there are a couple of libraries that implement post quantum crypto primitives; these implementations are of course not as tried and true as libsodium, but they do follow similar API design guides. There is &lt;a href=&quot;https://openquantumsafe.org/&quot;&gt;Open Quantum Safe&lt;/a&gt; which is a good default choice as a source of post quantum crypto algorithms. &lt;a href=&quot;https://github.com/pqclean/pqclean&quot;&gt;PQClean&lt;/a&gt; provides a lot of the implementations used in OQS; I ended up using this one just because I had an easier time compiling it for my platform. &lt;a href=&quot;https://github.com/mupq/pqm4&quot;&gt;mupq&lt;/a&gt; implements variants of post quantum primitives optimized for Arm M4; I could have used this, I ended up not using this simply because speed wasn&amp;#39;t an issue at all for my platform, memory was the primary constraint.&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot1&quot;&gt;[1]&lt;/a&gt;: &lt;a href=&quot;https://en.wikipedia.org/wiki/Cryptographic_protocol&quot;&gt;https://en.wikipedia.org/wiki/Cryptographic_protocol&lt;/a&gt;; this is the sort of technology used to encrypt live connections; TLS – the protocoll your browser is using to fetch this blog post – is an example of such a protocol.&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot2&quot;&gt;[2]&lt;/a&gt;: On average – there must be a 50% probability for each bit to be one or zero.&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot3&quot;&gt;[3]&lt;/a&gt;: Download my public key from my web server &lt;a href=&quot;https://cupdev.net/keys/7EA37614E956818EBFEA76526739B1556DBB745A.asc&quot;&gt;https://cupdev.net/keys/7EA37614E956818EBFEA76526739B1556DBB745A.asc&lt;/a&gt; or from the key servers: &lt;code&gt;gpg --search-key 7EA37614E956818EBFEA76526739B1556DBB745A&lt;/code&gt;&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot4&quot;&gt;[4]&lt;/a&gt;: This includes RSA, DSA, Diffie-Hellman and all Elliptic Curve Cryptography&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot5&quot;&gt;[5]&lt;/a&gt;: Transport Layer Security, your browser is using this to encrypt the connection with the blog&amp;#39;s HTTP server.&lt;/p&gt;
&lt;p&gt;&lt;a name=&quot;foot6&quot;&gt;[6]&lt;/a&gt;: Secure Shell; the most widely used protocol for administrating servers on the internet.&lt;/p&gt;
</description></item><item><title>How to Analyze Assembly Code to Guide Optimization Strategies</title><link>https://cupdev.net/blog/013_bin2c.html</link><pubDate>Fri, 29 May 2020 16:09:40 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/013_bin2c.html</guid><author></author><description>&lt;p&gt;Bin2c is a tool for embedding files in C89 compliant source code. The advantages and disadvantages of bin2c over existing methods of embedding files are discussed at length in the below project’s ReadMe. In short: bin2c’s goal is to quickly generate C code that is fast to compile and very compact. As such, using it is more portable but slower than directly embedding the file using ld for example. Compared to xxd -i, its output is much more compact, quicker to generate, and quicker to compile.&lt;/p&gt;
&lt;p&gt;How bin2c achieves this level of efficiency is discussed in this post!&lt;/p&gt;
&lt;h2 id=&quot;choosing-the-output&quot;&gt;Choosing the output&lt;/h2&gt;
&lt;p&gt;Before we are able to implement the converter, we need to decide which format we are going to produce. xxd -i encodes binary data as an array literal containing hexadecimal integers:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ echo -n &amp;#39;Hello World my big floof&amp;#39; | xxd -i 0x48, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x57, 0x6f, 0x72, 0x6c, 0x64, 0x20, 0x6d, 0x79, 0x20, 0x62, 0x69, 0x67, 0x20, 0x66, 0x6c, 0x6f, 0x6f, 0x66&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This format is quite readable, but it also has a very high overhead needing 6.167 characters to encode one byte of input data. By getting rid of the extra spaces and using decimal numbers instead of hex (getting rid of 0x) we can reduce space requirement down to 3.58 chars/byte. The resulting format is less readable than before:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;72,101,108,108,111,32,87,111,114,108,100,32, 109,121,32,98,105,103,32,102,108,111,111,102&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;We could also consider storing the data as a hex encoded array of eight byte words (uint64_t):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;0x48656c6c6f20576f,0x726c64206d792062,0x696720666c6f6f66&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This format is even more compact (at 2.4 chars/byte), however it is also really fragile: The memory area would have to be cast to a byte array and the encoding of each hex number depends on the endianess of the target platform.&lt;/p&gt;
&lt;p&gt;Bin2c follows an entirely different approach: Instead of encoding the data as a byte array, we encode it as a string! This way, text files can be included almost verbatim; just a few characters like &amp;quot; or \n have to be escaped. Unicode characters and binary can be encoded using escape sequences.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ echo -n &amp;#39;Hello World my big floof&amp;#39; | build/bin2c
hHello World my big floof
$ head -c 20 &amp;lt;/dev/urandom | build/bin2c
\241dT\000\314\022\241\351\355\377#\352\244\216\334\336\004\002\350\31&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This encoding is extremely compact for text (requiring 1.2 chars to encode one byte) and still decently small binary (3.1 chars/byte).
Turns out compilers are also 20x-30x faster at parsing this format.&lt;/p&gt;
&lt;h2 id=&quot;our-first-implementation&quot;&gt;Our first implementation&lt;/h2&gt;
&lt;p&gt;As usual, when approaching optimization problems, we should focus on writing an obvious, easy-to-read implementation of our solution. This way we will have a baseline to compare our code against. Here it is:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;ctype.h&amp;gt;

void bin2c() {
  for (int inc = getchar(); inc != EOF; inc = getchar()) {
    // Detect characters that need a special escape sequence
    switch ((char)inc) {
      case &amp;#39;\a&amp;#39;: fputs(&amp;quot;\\a&amp;quot;, stdout);     continue;
      case &amp;#39;\b&amp;#39;: fputs(&amp;quot;\\b&amp;quot;, stdout);     continue;
      case &amp;#39;\t&amp;#39;: fputs(&amp;quot;\\t&amp;quot;, stdout);     continue;
      case &amp;#39;\n&amp;#39;: fputs(&amp;quot;\\n\\\n&amp;quot;, stdout); continue;
      case &amp;#39;\v&amp;#39;: fputs(&amp;quot;\\v&amp;quot;, stdout);     continue;
      case &amp;#39;\f&amp;#39;: fputs(&amp;quot;\\f&amp;quot;, stdout);     continue;
      case &amp;#39;\r&amp;#39;: fputs(&amp;quot;\\r&amp;quot;, stdout);     continue;
      case &amp;#39;\\&amp;#39;: fputs(&amp;quot;\\\\&amp;quot;, stdout);    continue;
      case &amp;#39;&amp;quot;&amp;#39;:  fputs(&amp;quot;\\\&amp;quot;&amp;quot;, stdout);    continue;
      default: {} // pass
    }

// Handle printable characters (excluding $, @ and ?)
    if (isprint(inc) &amp;amp;&amp;amp; inc != &amp;#39;$&amp;#39; &amp;amp;&amp;amp; inc != &amp;#39;@&amp;#39; &amp;amp;&amp;amp; inc != &amp;#39;?&amp;#39;) {
      putchar(inc);

// Fall back to octal encoding
    } else {
      printf(&amp;quot;\\%.3o&amp;quot;, inc);
    }
  }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This very first version already outperforms XXD, albeit by a relatively small factor of 1.6; I am not entirely sure why this is the case. &lt;a href=&quot;https://github.com/vim/vim/blob/master/src/xxd/xxd.c#L749&quot;&gt;The hot loop&lt;/a&gt; for encoding C source files in XXD seems to call fprintf in a loop while using some complicated logic to choose the format string and supply the delimiter string. This is probably one of the major reasons for xxds slowness; &lt;em&gt;clever code&lt;/em&gt; does not tend to perform well. Coders have a hard time reading — and thus optimizing — clever code and sometimes, so do compilers.&lt;/p&gt;
&lt;p&gt;It probably also helps that bin2c can skip a call to fprintf in many cases and just use puts or putc directly.&lt;/p&gt;
&lt;h2 id=&quot;inlining&quot;&gt;Inlining&lt;/h2&gt;
&lt;p&gt;Let us now take a look at the &lt;a href=&quot;https://godbolt.org/z/K-q9_n&quot;&gt;assembly produced&lt;/a&gt; when compiling the code above with optimization. Not many surprises there: getchar() turns into a call _IO_getc, our puts() calls in the switch statement become fwrite(), putchar turns into _IO_putc, isprint() turns into__ctype_b_loc , and the printf() call stays the same in the assembly.&lt;/p&gt;
&lt;p&gt;That is a lot of call instructions — two or three per character encoded and the functions are pretty complex. The stream writing functions need to do error handling, isprint takes the locale into account, printf needs to parse the format string. Optimizing out the bin2c function is going to involve creating alternate implementations of the called functions that are both simpler and can be inlined.&lt;/p&gt;
&lt;p&gt;We will have to use manual buffering coupled with &lt;a href=&quot;https://github.com/adobe/bin2c/blob/master/src/bin2c.c#L31&quot;&gt;fread&lt;/a&gt; and &lt;a href=&quot;https://github.com/adobe/bin2c/blob/master/src/bin2c.c#L46&quot;&gt;fwrite&lt;/a&gt; and use &lt;a href=&quot;https://github.com/adobe/bin2c/blob/master/src/bin2c.c#L90&quot;&gt;setvbuf&lt;/a&gt; to disable the built in stream buffering. This way our hot loop just has to write from one buffer and into another, deferring all the complexities of writing to C streams to whenever the buffers are flushed.&lt;/p&gt;
&lt;p&gt;isprint() can be replaced with chr &amp;gt;= &amp;#39; &amp;#39; &amp;amp;&amp;amp; chr &amp;lt;= &amp;#39;~&amp;#39; , if we handle any special cases in the switch statement and octal encoding is really easy to implement because we can get the ascii digit for a numerical value by adding &amp;#39;0&amp;#39; or 48.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;ctype.h&amp;gt;
#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

// Not using the normal strcpy here because the `call` instruction emitted would be expensive…
inline size_t b2c_strcpy(char *from, char *to) {
    size_t r = strlen(from);
    strcpy(to, from);
    return r;
}

inline size_t bin2c_single(uint8_t chr, char *out) {
  switch ((char)chr) {
    case &amp;#39;\a&amp;#39;: return b2c_strcpy(&amp;quot;\\a&amp;quot;, out);
    case &amp;#39;\b&amp;#39;: return b2c_strcpy(&amp;quot;\\b&amp;quot;, out);
    case &amp;#39;\t&amp;#39;: return b2c_strcpy(&amp;quot;\\t&amp;quot;, out);
    case &amp;#39;\n&amp;#39;: return b2c_strcpy(&amp;quot;\\n\\\n&amp;quot;, out);
    case &amp;#39;\v&amp;#39;: return b2c_strcpy(&amp;quot;\\v&amp;quot;, out);
    case &amp;#39;\f&amp;#39;: return b2c_strcpy(&amp;quot;\\f&amp;quot;, out);
    case &amp;#39;\r&amp;#39;: return b2c_strcpy(&amp;quot;\\r&amp;quot;, out);
    case &amp;#39;\\&amp;#39;: return b2c_strcpy(&amp;quot;\\\\&amp;quot;, out);
    case &amp;#39;&amp;quot;&amp;#39;:  return b2c_strcpy(&amp;quot;\\\&amp;quot;&amp;quot;, out);
    case &amp;#39;$&amp;#39;:
    case &amp;#39;@&amp;#39;:
    case &amp;#39;?&amp;#39;:
      goto octal;
  }

// isprint, but inline
  if (chr &amp;gt;= &amp;#39; &amp;#39; &amp;amp;&amp;amp; chr &amp;lt;= &amp;#39;~&amp;#39;) {
    out[0] = chr;
    return 1;
  }

octal:
  // Octal digits are three bit long, so we can just a bit mask 0b111
  // and bit shifts to extract each digit
  out[0] = &amp;#39;\\&amp;#39;; // octal encode
  out[1] = (chr &amp;gt;&amp;gt; 6 &amp;amp; 7) + &amp;#39;0&amp;#39;;
  out[2] = (chr &amp;gt;&amp;gt; 3 &amp;amp; 7) + &amp;#39;0&amp;#39;;
  out[3] = (chr &amp;gt;&amp;gt; 0 &amp;amp; 7) + &amp;#39;0&amp;#39;;
  return 4;
}

void bin2c(uint8_t **in, uint8_t *in_end, char **out, char *out_end) {
  // We just work around the 4 byte buffer limitation in the enclosing
  // read/process/write loop…not an issue for our specific application
  assert(out_end-*out &amp;gt;= 4);
  // (hot loop) While data in inbuff &amp;amp; outbuf has 4 free slots
  // (bin2c needs four free slots)
  for (; *in &amp;lt; in_end &amp;amp;&amp;amp; out_end-*out &amp;gt;= 4; (*in)++)
    *out += bin2c_single(**in, *out);
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;These changes just gave us an 8x improvement in performance. Take a look at &lt;a href=&quot;https://godbolt.org/z/Am6dhD&quot;&gt;the assembly&lt;/a&gt; again; looks less complex, not a single call instruction.&lt;/p&gt;
&lt;h2 id=&quot;lookup-table&quot;&gt;Lookup Table&lt;/h2&gt;
&lt;p&gt;Having eliminated call instructions is great, as doing so &lt;a href=&quot;https://en.wikipedia.org/wiki/Cache_coherence&quot;&gt;improves cache coherence&lt;/a&gt; and means less work to store parameters (fulfilling the &lt;a href=&quot;https://en.wikipedia.org/wiki/X86_calling_conventions&quot;&gt;calling convention&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;In fact, all sorts of &lt;a href=&quot;https://en.wikipedia.org/wiki/JMP_(x86_instruction)&quot;&gt;jumps&lt;/a&gt; and &lt;a href=&quot;https://en.wikipedia.org/wiki/Branch_(computer_science)&quot;&gt;branch&lt;/a&gt; instructions are somewhat expensive. Again, this is because the cache coherence will be slightly worse, but also because of the impact on &lt;a href=&quot;https://en.wikipedia.org/wiki/Branch_predictor&quot;&gt;CPU pipelining&lt;/a&gt;. Optimally we should not use any conditional execution (if statements, switch statements or ternary operators) in our hot loop for optimum throughput.&lt;/p&gt;
&lt;p&gt;Luckily, there is a way to achieve that in our case: Our encoder is just a mapping from one specific input byte to between one and four output bytes. This is not a lot of data so we can simply use a lookup table! Four bytes per value, zero padded — we need 1KB of lookup table; that is small enough to easily fit into most CPU caches!&lt;/p&gt;
&lt;p&gt;That should be pretty easy: Use a lookup table with 256 32bit words (uint32_t), lookup the value for the input char, and copy the output value to the output buffer. Unfortunately, because our lookup table uses variable sizes, we still need an efficient way to determine the length of our output sequence. We could, for instance, use strnlen to determine the length (which results in a call instruction being emitted). Failing that we could use a similar pattern as before and implement our own, inlinable strnlen, but that results in a few conditional jumps.&lt;/p&gt;
&lt;p&gt;After playing around with various implementations, even writing my own &lt;a href=&quot;https://github.com/adobe/bin2c/blob/ad8689ec37d316e07687bde66f27abeec36d17d9/src/bin2c.h#L56&quot;&gt;branch free&lt;/a&gt; version of strnlen (based on the &lt;a href=&quot;https://www.felixcloutier.com/x86/bsr&quot;&gt;Bit Scan Reverse&lt;/a&gt; instruction), I decided to simply store the string length inside some bits of the lookup table, which happened to be unused.&lt;/p&gt;
&lt;p&gt;Then I just made sure that clearing those bits and copying the data to the output was done in four byte blocks (uint32), instead of byte for byte. Even if the output sequence is short, we still copy all four bytes from the lookup table. It might seem like copying fewer bytes would be less work, but that would require us to use conditional execution which is simply not worth it if the payoff is copying just one byte instead of three or four.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#include &amp;lt;stdint.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
#include &amp;lt;assert.h&amp;gt;
#include &amp;lt;string.h&amp;gt;

static inline size_t bin2c_single(uint8_t chr, char *out) {
  extern const char bin2c_lookup_table_[];

  // NOTE: The length is in the two most significant bits of
  // the last character of the output. The length in there is
  // 0..3, our actual value is 1..4 so we need to add 1.
  // In order to store this mask in an endianess independent way
  // we store it a byte array; in order to apply it efficiently
  // we cast to an uint32_t so we can perform a one 4 byte instruction
  // instead of multiple single byte instructions when copying into
  // the output buffer.

  // Lookup table char -&amp;gt; escaped for C.
  // Each code is between one and 4 bytes and padded by zeroes.
  const uint8_t *slot8 = ((uint8_t*)bin2c_lookup_table_) + chr*4;

  // The bit mask for erasing the length information; stored as a byte
  // array instead of a uint32_t literal to avoid endianess issues
  uint8_t mask8[] = { 0xff, 0xff, 0xff, 0x3f };

  // Copy the data from the lookup table and erase length info
  // This really is just `out = slot &amp;amp; mask;`.
  // Both casting to a packed struct and using memcpy are ways to express
  // unaligned 32 bit pointer access; this is faster than doing the copying
  // byte by byte on x86_64
#ifdef __GNUC__ // GCC/Clang optimized version
  struct __attribute__((__packed__)) uint32_noalign {
    uint32_t v;
  };
  ((struct uint32_noalign*)out)-&amp;gt;v = ((struct uint32_noalign*)slot8)-&amp;gt;v &amp;amp; ((struct uint32_noalign*)mask8)-&amp;gt;v;
#else 
  uint32_t mask32, slot32;
  memcpy(&amp;amp;mask32, mask8, 4);
  memcpy(&amp;amp;slot32, slot8, 4);
  slot32 &amp;amp;= mask32;
  memcpy(out, &amp;amp;slot32, 4);
#endif

// Extract length info from lookup
  return ((slot8[3] &amp;amp; 0xc0) &amp;gt;&amp;gt; 6) + 1;
}

void bin2c(const uint8_t **in, const uint8_t *in_end, char **out, const char *out_end) {
  // (hot loop) While data in inbuff &amp;amp; outbuf has 4 free slots
  // (bin2c needs four free slots)
  for (; *in &amp;lt; in_end &amp;amp;&amp;amp; out_end-*out &amp;gt;= 4; (*in)++)
    *out += bin2c_single(**in, *out);

}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using the lookup table strategy yielded another 2.3x speedup. In &lt;a href=&quot;https://godbolt.org/z/779KAz&quot;&gt;the assembly&lt;/a&gt; we can see why: Just two jump statements left in the hot loop, the code is also much more compact than before and all code in the hot loop is executed every time, so there is no opportunity for the branch predictor to generate incorrect predictions.&lt;/p&gt;
&lt;p&gt;The original implementation is still included, by the way, since we &lt;a href=&quot;https://github.com/adobe/bin2c/blob/3d5fda1e310c26acdb70e27b4791e1d329c6358f/Makefile#L57&quot;&gt;need a way&lt;/a&gt; to &lt;a href=&quot;https://github.com/adobe/bin2c/blob/3d5fda1e310c26acdb70e27b4791e1d329c6358f/src/genlookup.c&quot;&gt;generate the lookup&lt;/a&gt; table in the first place.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot;&gt;Conclusions&lt;/h2&gt;
&lt;p&gt;The optimization strategies discussed in this post demonstrate how reading assembly can give vital clues when trying to improve your code’s efficiency and that even basic operations like calls and jump instructions can slow down your code when used inside the hot portion of your code. We also discussed a common optimization strategy: Using a lookup table.&lt;/p&gt;
&lt;p&gt;The greatest gains though can often be reaped from taking a step back and reexamining your approach; changing the format from hex numbers to escaped string not only improved output size, sped up compilation, and laid the foundation for later performance improvements.&lt;/p&gt;
&lt;h2 id=&quot;benchmarks&quot;&gt;Benchmarks&lt;/h2&gt;
&lt;p&gt;These benchmarks show the optimization progress; taken on a i7–9700K CPU @ 3.60GHz. This contains some more development steps, like fixing unaligned access to uint32_t (which is undefined behavior; fixing this resulted in a performance hit).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;xxd                             13.9282  Mb/s
bin2c-0001_initial              24.5181  Mb/s
bin2c-0003_inline_octal         129.244  Mb/s
bin2c-0002_manual_buffer        129.292  Mb/s
bin2c-0005_lookup               165.952  Mb/s
bin2c-0004_inline_isprint       180.759  Mb/s
bin2c-0006_branchless_length    218.387  Mb/s
bin2c-0007_lookup_length        435.427  Mb/s
bin2c-0008_32bit_lookup_access  593.669  Mb/s
bin2c-0009_fix_unaligned        437.677  Mb/s
bin2c-000a_packed_unaligned     553.805  Mb/s
bin2c-000b_discard_b2c_memcpy   555.226  Mb/s&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Filtering Duplicates on the Command Line: 30x Faster than sort|uniq</title><link>https://cupdev.net/blog/012_huniq.html</link><pubDate>Tue, 25 Feb 2020 00:00:00 +0100</pubDate><guid isPermaLink="true">https://cupdev.net/blog/012_huniq.html</guid><author></author><description>&lt;p&gt;sort | uniq sorts data given to it via stdin and then removes any duplicates. Personally, I use this quite often to create a ranking of something. For example, looking below, you could create a ranking of the words I use most often in this blog:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ curl &amp;quot;[https://cupdev.net/blog/](https://cupdev.net/blog/)&amp;quot; | html2text2 | sed &amp;#39;s@[^a-zA-Z_0-9]@\n@g&amp;#39; | grep -v &amp;#39;^\s*$&amp;#39; | sort | uniq -c | sort -n
     34 s
     39 com
     39 tag
     40 it
     40 that
     48 you
     49 is
     52 in
     53 search
     82 of
     88 I
     94 and
    112 a
    114 to
    180 the&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Unsurprisingly, I use ‘the,’ ‘to,’ and ‘a,’ quite a lot.&lt;/p&gt;
&lt;p&gt;The first two commands download the blog, the third removes all special characters and splits lines into words, grep gets rid of any empty lines left over, sort|uniq -c counts duplicates, and the final sort -n ranks them.&lt;/p&gt;
&lt;p&gt;You might notice, that for the purpose above, sorting is not really required. We just need to count duplicates. A more speedy way to get this job done might be to use a hash table.&lt;/p&gt;
&lt;p&gt;That’s why I created &lt;a href=&quot;https://github.com/koraa/huniq&quot;&gt;huniq&lt;/a&gt; in order to count/remove duplicates by using a hash table. huniq implements two modes; it removes duplicates and counts them. In this blog post, we’ll look at how to implement and optimize the first mode.&lt;/p&gt;
&lt;h3 id=&quot;writing-idiomatic-rust-code&quot;&gt;Writing idiomatic Rust code&lt;/h3&gt;
&lt;p&gt;My initial implementation was very simple; I used &lt;a href=&quot;https://clap.rs&quot;&gt;clap&lt;/a&gt; to parse command line arguments, &lt;a href=&quot;https://crates.io/crates/anyhow&quot;&gt;anyhow&lt;/a&gt; to handle errors (actually I used failure, but that was later replaced), and wrote the simplest implementation I could think of for uniq (&lt;a href=&quot;https://github.com/koraa/huniq/blob/803d9589708292b3de4bb807e80c30e156bb0069/src/main.rs#L30&quot;&gt;source&lt;/a&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn uniq_cmd(delim: u8) -&amp;gt; Result&amp;lt;()&amp;gt; {
    let mut out = BufWriter::new(stdout());
    let mut set = HashSet::&amp;lt;Vec&amp;lt;u8&amp;gt;&amp;gt;::new();

    for line in BufReader::new(stdin()).split(delim) {
        let line = line?;
        if set.insert(line.clone()) {
            out.write(&amp;amp;line)?;
            out.write(slice::from_ref(&amp;amp;delim))?;
        }
    }

    Ok(())
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Each line is read using BufReader/BufWriter. You then insert it into the hash set. If it succeeds (because the value wasn’t in the hash set before), the line is also printed to stdout.&lt;/p&gt;
&lt;p&gt;This design already includes one optimization, albeit the reason for including it is that it makes the code actually easier. By using &lt;a href=&quot;https://doc.rust-lang.org/std/io/struct.BufReader.html&quot;&gt;BufReader&lt;/a&gt;/&lt;a href=&quot;https://doc.rust-lang.org/std/io/struct.BufWriter.html&quot;&gt;BufWriter&lt;/a&gt;, instead of the plain stdin() and stdout(), the number of &lt;a href=&quot;https://en.wikipedia.org/wiki/System_call&quot;&gt;system calls&lt;/a&gt; can be reduced. For more on why this improves performance, keep reading.&lt;/p&gt;
&lt;h3 id=&quot;allocation-system-calls-and-context-switches&quot;&gt;Allocation, system calls, and context switches&lt;/h3&gt;
&lt;p&gt;Two inefficiencies are immediately visible: BufReader::split &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_management#ALLOCATION&quot;&gt;allocates&lt;/a&gt; a new Vec&amp;lt;8&amp;gt; for each element read and clone creates another copy, which also needs to be allocated.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Memory allocations&lt;/strong&gt; can be quite slow; they need a bit of time to find an available memory location and, if there is none, the allocator will fall back to using a system call to request more memory from the system.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A system call&lt;/strong&gt; requires at least two &lt;a href=&quot;https://en.wikipedia.org/wiki/Context_switch&quot;&gt;context switches&lt;/a&gt;: one into the kernel and one back.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Context switch&lt;/strong&gt; on the other hand means switching to another process, thread, or into the &lt;a href=&quot;https://en.wikipedia.org/wiki/Kernel_(operating_system)&quot;&gt;kernel&lt;/a&gt; (the core of the operating system). All the data currently in the cpu registers need to be written back into &lt;a href=&quot;https://en.wikipedia.org/wiki/Random-access_memory&quot;&gt;RAM&lt;/a&gt; and the &lt;a href=&quot;https://en.wikipedia.org/wiki/CPU_cache&quot;&gt;CPU caches&lt;/a&gt; need to be cleared. The &lt;a href=&quot;https://en.wikipedia.org/wiki/Page_table&quot;&gt;page table&lt;/a&gt; (hardware accelerated supported memory management, see &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_management_unit&quot;&gt;Memory Management Unit&lt;/a&gt;) needs to be cleared. New data is loaded into the CPU from the new thread of execution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;To sum it up&lt;/strong&gt;: Accessing RAM is really slow, and in order to do a system call/context switch/some memory allocations, a lot of new data needs to be loaded from the RAM. The CPU caches are used avoid needing to access RAM directly, so clearing them is also bad for performance.&lt;/p&gt;
&lt;p&gt;To get rid of at least one of those allocations, a trick can be used: you can store the hash of the line only instead of the full value. This way, we can avoid calling clone() and thus avoid the extra allocation andsaving some memory. We now just need 8 bytes for each string, while Vec would require at least 16 (one for the size and one for the location of the allocated string in memory, in addition to the actual data; rusts implementation &lt;a href=&quot;https://play.rust-lang.org/?version=stable&amp;amp;mode=debug&amp;amp;edition=2018&amp;amp;gist=b68086c31f50c2f82b72de61a92d2a04&quot;&gt;actually needs 24&lt;/a&gt; as it also stores the capacity).&lt;/p&gt;
&lt;p&gt;Here is the &lt;a href=&quot;https://github.com/koraa/huniq/blob/5ad413137bde10a5e97517e490981c448e4e5489/src/main.rs#L31&quot;&gt;code&lt;/a&gt;: We now just call set.insert(hash(&amp;amp;line)) to insert the hash; this also let’s us get rid of the clone() call since hash() just needs a reference instead of moving the whole string.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;for line in BufReader::new(stdin()).split(delim) {
    let line = line?;
    if set.insert(hash(&amp;amp;line)) {
        out.write(&amp;amp;line)?;
        out.write(slice::from_ref(&amp;amp;delim))?;
    }
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Due to the &lt;a href=&quot;https://www.johndcook.com/blog/2017/01/10/probability-of-secure-hash-collisions/&quot;&gt;birthday paradoxon&lt;/a&gt;&lt;/strong&gt;, doing this is really only safe for about 2&lt;strong&gt;32 elements when using a 64-bit hash. We&amp;#39;re not too worried about this, because 2&lt;/strong&gt;32 is a large number, but if you expect more than a billion unique elements, you should probably use a 128-bit has function, which is good for 2**64 elements.&lt;/p&gt;
&lt;h4 id=&quot;benchmarking&quot;&gt;Benchmarking&lt;/h4&gt;
&lt;p&gt;At this point in the process, I decided huniq was ready for a first release. I tested the code (turns out it worked) with a simple shell script and created some benchmarks.&lt;/p&gt;
&lt;p&gt;Benchmarking is tough. For huniq, I decided I didn’t really need something sophisticated and simply used /usr/bin/time -v on the command line to measure execution time and memory usage.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ /usr/bin/time -v echo

Command being timed: &amp;quot;echo&amp;quot;
        User time (seconds): 0.00
        System time (seconds): 0.00
        Percent of CPU this job got: 100%
        Elapsed (wall clock) time (h:mm:ss or m:ss): 0:00.00
        Average shared text size (kbytes): 0
        Average unshared data size (kbytes): 0
        Average stack size (kbytes): 0
        Average total size (kbytes): 0
        Maximum resident set size (kbytes): 1512
        Average resident set size (kbytes): 0
        Major (requiring I/O) page faults: 7
        Minor (reclaiming a frame) page faults: 73
        Voluntary context switches: 2
        Involuntary context switches: 0
        Swaps: 0
        File system inputs: 56
        File system outputs: 0
        Socket messages sent: 0
        Socket messages received: 0
        Signals delivered: 0
        Page size (bytes): 4096
        Exit status: 0&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;This already gives a lot of insight; most interesting is the “Elapsed (wall clock) time” (how long the execution took), and the “Maximum resident set size” (how much memory it used). There are other interesting values here, too— for instance “System time” in relation to “Elapsed time” can help us understand how much time of our program spends in system calls.&lt;/p&gt;
&lt;p&gt;I created a little script (&lt;a href=&quot;https://github.com/koraa/huniq/blob/master/benchmark.sh&quot;&gt;see here&lt;/a&gt;) for benchmarking so I wouldn’t always have to run the benchmarks manually. Later I would keep the binaries from different optimization steps around and add them to the benchmark script, so I could see whether my optimization attempts are working. At this point, the benchmarks looked like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;implemetation  seconds  memory/kb
rust             10.26      29548
cpp              18.87      26128
shell           151.40      10060&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Pretty good, right? This simple rust implementation is already beating sort|uniq and my previous c++ implementation!&lt;/p&gt;
&lt;p&gt;Using idiomatic rust code already beats the old C++ implementation. The reason for this likely is the choice of hash table (although I did not verify this). It just goes to show you how well the rust standard library is crafted!&lt;/p&gt;
&lt;h3 id=&quot;stdin-lock-stdout-lock-as-suggested-in-these-responses-thanks-awesome-rust-reditters-i-decided-to-use-lock-on-stdout-and-stdin-this-method-lets-you-avoid-the-overhead-of-thread-synchronization-when-using-these-functions-which-is-acceptable-in-our-case-since-we-re-accessing-the-method-from-just-one-thread-check-out-the-code-fn-uniq_cmd-delim-u8-result-let-out-stdout-let-mut-out-bufwriter-new-out-lock-let-mut-set-hashset-u64-new-for-line-in-bufreader-new-stdin-lock-split-delim-let-line-line-if-set-insert-hash-line-out-write-line-out-write-slice-from_ref-delim-&quot;&gt;Stdin::lock()/Stdout::lock() As suggested in these &lt;a href=&quot;https://www.reddit.com/r/rust/comments/eq4ky4/requesting_assistance_optimizing_a_rust_cli_util/&quot;&gt;responses&lt;/a&gt; (thanks awesome Rust Reditters), I decided to use &lt;a href=&quot;https://doc.rust-lang.org/std/io/struct.Stdin.html#method.lock&quot;&gt;lock()&lt;/a&gt; on stdout and stdin. This method lets you avoid the overhead of thread synchronization when using these functions, which is acceptable in our case, since we’re accessing the method from just one thread. Check out the &lt;a href=&quot;https://github.com/koraa/huniq/blob/792612a9bba3939aaa895bf6c6b04db2dd322e34/src/main.rs#L36&quot;&gt;code&lt;/a&gt;.  fn uniq_cmd(delim: u8) -&amp;gt; Result&amp;lt;()&amp;gt; { let out = stdout(); let mut out = BufWriter::new(out.lock()); let mut set = HashSet::&lt;u64&gt;::new(); for line in BufReader::new(stdin().lock()).split(delim) { let line = line?; if set.insert(hash(&amp;amp;line)) { out.write(&amp;amp;line)?; out.write(slice::from_ref(&amp;amp;delim))?; } }&lt;/h3&gt;
&lt;pre&gt;&lt;code&gt;    Ok(())
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Using lock() did not have a measurable effect on performance, but I still decided to keep it because it made sense conceptually and was a very simple change.&lt;/p&gt;
&lt;h3 id=&quot;getting-rid-of-redundant-work-extra-allocation-extra-hash&quot;&gt;Getting rid of redundant work: Extra allocation, extra hash&lt;/h3&gt;
&lt;p&gt;Just storing the hash, instead of the full value, was a good idea, but that also meant we were now calculating two hashes. First, we manually hashed the line, but then the hash table would execute run hash function again! We solved that problem by creating a custom hasher that just returns the data it received. The drawback here is that we needed to create custom implementations of &lt;a href=&quot;https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html&quot;&gt;Hasher&lt;/a&gt; (&lt;a href=&quot;https://github.com/koraa/huniq/blob/116038627a0a02dd6178c10cf9cb345c48b39f21/src/main.rs#L30&quot;&gt;my source&lt;/a&gt;) and of &lt;a href=&quot;https://doc.rust-lang.org/nightly/core/hash/trait.BuildHasher.html&quot;&gt;BuildHasher&lt;/a&gt; (&lt;a href=&quot;https://github.com/koraa/huniq/blob/116038627a0a02dd6178c10cf9cb345c48b39f21/src/main.rs#L49&quot;&gt;my source&lt;/a&gt;); this was worth it because it resulted in a speedup of 10-20 percent.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;struct IdentityHasher {
    off: u8,
    buf: [u8; 8],
}

impl Hasher for IdentityHasher {
    fn write(&amp;amp;mut self, bytes: &amp;amp;[u8]) {
        self.off += (&amp;amp;mut self.buf[self.off as usize..])
            .write(bytes).unwrap_or(0) as u8;
    }

    fn finish(&amp;amp;self) -&amp;gt; u64 {
        u64::from_ne_bytes(self.buf)
    }
}

#[derive(Default)]
struct BuildIdentityHasher {}

impl BuildHasher for BuildIdentityHasher {
    type Hasher = IdentityHasher;

    fn build_hasher(&amp;amp;self) -&amp;gt; Self::Hasher {
        IdentityHasher { off: 0, buf: [0; 8] }
    }
}

fn hash&amp;lt;T: std::hash::Hash&amp;gt;(v: &amp;amp;T) -&amp;gt; u64 {
    let mut s = DefaultHasher::new();
    v.hash(&amp;amp;mut s);
    s.finish()
}&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;In addition, our split() invocation was still allocating on the heap. To solve this, you can use &lt;a href=&quot;https://doc.rust-lang.org/std/io/trait.BufRead.html#method.read_until&quot;&gt;BufRead::read_until&lt;/a&gt; to remedy that which can reuse a Vec. Again, our code was becoming more and more complicated; using read_until() requires you to declare the Vec and handle an edge case when there is no delimiter before eof; but then again, we&amp;#39;re another 10- 20 percent faster.&lt;/p&gt;
&lt;p&gt;Now our &lt;a href=&quot;https://github.com/koraa/huniq/blob/116038627a0a02dd6178c10cf9cb345c48b39f21/src/main.rs#L63&quot;&gt;code&lt;/a&gt; looks like this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;fn uniq_cmd(delim: u8) -&amp;gt; Result&amp;lt;()&amp;gt; {
    let out = stdout();
    let inp = stdin();
    let mut out = BufWriter::new(out.lock());
    let mut inp = BufReader::new(inp.lock());
    let mut set = HashSet::&amp;lt;u64, BuildIdentityHasher&amp;gt;::default();
    let mut line = Vec::&amp;lt;u8&amp;gt;::new();
    while inp.read_until(delim, &amp;amp;mut line)? &amp;gt; 0 {

        if *line.last().unwrap() == delim {
            line.pop();
        }

        if set.insert(hash(&amp;amp;line)) {
            out.write(&amp;amp;line)?;
            out.write(slice::from_ref(&amp;amp;delim))?;
        }

        line.clear();
    }

    Ok(())
}&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;going-zero-copy&quot;&gt;Going zero-copy&lt;/h3&gt;
&lt;p&gt;Keen eyes will spot that our code is still doing unnecessary work — copying the current line from BufRead into the line buffer. I haven’t found anything in the standard library that lets me avoid the copy, so I had to resort to writing my own split function.&lt;/p&gt;
&lt;p&gt;The split_read_zerocopy (&lt;a href=&quot;https://github.com/koraa/huniq/blob/78a068002b894c6b216797f4722b9a8652217e3c/src/main.rs#L61&quot;&gt;source&lt;/a&gt;, bit too long to post inline but with lots of comments) function takes a delimiter (u8), a Read stream (anything that implements Read), and calls a callback function whenever a new token is found. Now instead of copying the data found into a user provided buffer, the function emits slices of the internal buffer, which can be resized when we need to fit in very long lines.&lt;/p&gt;
&lt;p&gt;This &lt;a href=&quot;https://en.wikipedia.org/wiki/Zero-copy&quot;&gt;zero-copy&lt;/a&gt; optimization was really high effort; for many projects, you should consider whether it is even worth it. Huniq is a small project with a very specific use case, and I do think a boost of 15-25 percent was worth it.&lt;/p&gt;
&lt;h3 id=&quot;choosing-a-hash-function-ahash-fxhash-or-xxh3&quot;&gt;Choosing a hash function: ahash, fxhash, or xxh3&lt;/h3&gt;
&lt;p&gt;The default &lt;a href=&quot;https://en.wikipedia.org/wiki/Hash_function&quot;&gt;hash function&lt;/a&gt; in rust hash tables is currently &lt;a href=&quot;https://131002.net/siphash/&quot;&gt;siphash&lt;/a&gt;, which is a good choice against &lt;a href=&quot;https://en.wikipedia.org/wiki/Collision_attack&quot;&gt;hash collision attacks&lt;/a&gt;. Such an attack could allow an attacker to slow down huniq massively and even hide elements from the input, since it doesn’t involve storing the original value.&lt;/p&gt;
&lt;p&gt;Huniq isn’t really advertised as particularly safe for untrusted inputs, but keeping basic mitigations in place against collision attacks is probably a good idea. At the very least, I wanted to use a secret key/seed to hash the data, which meant we had to find a hash function that has some basic support for a secret keys and is also faster than siphash.&lt;/p&gt;
&lt;p&gt;I tried various ways of hashing including &lt;a href=&quot;https://github.com/koraa/huniq/commit/f48780f0160144f97963dddaeee143c5893bdb14&quot;&gt;ahash&lt;/a&gt;, which was 20 percent faster than the default hasher, &lt;a href=&quot;https://github.com/koraa/huniq/commit/a73cde6bcafd37c71096f4569080b2cc42c5b755&quot;&gt;fxhash&lt;/a&gt;, which sped up the process by another 20 percent. Fxhash isn’t really optimized though; it is not optimized for long values and — more importantly — is not very collision resistant.&lt;/p&gt;
&lt;p&gt;After &lt;a href=&quot;https://github.com/koraa/huniq/commit/8eaafd76173707d032ef20745ff65000b0d85e41&quot;&gt;cleaning up the code&lt;/a&gt; using ahash and trying &lt;a href=&quot;https://github.com/koraa/huniq/commit/c2658a998e7527444e59e032d0a11d2dd15561b7&quot;&gt;two&lt;/a&gt; &lt;a href=&quot;https://github.com/koraa/huniq/commit/fd6323c1de593434d83f930dfae47e03e3af260d&quot;&gt;ways&lt;/a&gt; of manually applying a random seed to fxhash, I still wasn’t really satisfied. And honestly, I didn’t really trust my own way of seeding fxhash (getting cryptographic problems right is hard).&lt;/p&gt;
&lt;p&gt;Enter: &lt;a href=&quot;https://fastcompression.blogspot.com/2019/03/presenting-xxh3.html&quot;&gt;XXH3&lt;/a&gt;. This is a relatively new, very quick hash function. It is based on xxhash (which is very fast, especially for long inputs) but includes additional optimizations for short inputs. It provides the XXH3_64bits_withSecret function, which pretty much exactly covered our use case and should be &lt;a href=&quot;https://github.com/Cyan4973/xxHash/issues/294&quot;&gt;relatively safe&lt;/a&gt; against collision attacks. The fact that this is a single function call instead of byte oriented hashing (that is a combination of &lt;a href=&quot;https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html#tymethod.write&quot;&gt;Hasher::write()&lt;/a&gt; and &lt;a href=&quot;https://doc.rust-lang.org/nightly/core/hash/trait.Hasher.html#tymethod.finish&quot;&gt;Hasher::finish()&lt;/a&gt;) also probably helps.&lt;/p&gt;
&lt;p&gt;In the end using XXH3 yielded another 15 percent speedup over using fxhash, while being optimized for long values too and providing some level of protection against collision attacks. This was the optimization with the most effort yet; there is no crate exposing the XXH3 hash function, so huniq includes additional &lt;a href=&quot;https://github.com/koraa/huniq/commit/345ec269153180cbc27908df5e9f0eab295df3ee&quot;&gt;code&lt;/a&gt; to compile the xxhash repository and create bindings for XXH3 on the fly.&lt;/p&gt;
&lt;h3 id=&quot;link-time-optimization-alternative-hash-tables&quot;&gt;Link Time Optimization, alternative Hash Tables&lt;/h3&gt;
&lt;p&gt;In addition to the optimizations outlined above, I also tried to use different hash tables, activating &lt;a href=&quot;https://llvm.org/docs/LinkTimeOptimization.html&quot;&gt;Link Time Optimization&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Both attempts ended up decreasing the efficiency of huniq. For the hash table, it seems the standard library is already using one of the most efficient hash tables &lt;a href=&quot;https://github.com/Amanieu/hashbrown&quot;&gt;out there&lt;/a&gt;. This seems to be an advantage of rust’s faster paced approach over the design-by-committee approach used in C++. &lt;a href=&quot;https://en.cppreference.com/w/cpp/container/unordered_map&quot;&gt;std::unordered_map&lt;/a&gt; is famously slow, because the standard imposes very specific guarantees in regards to pointer stability and memory layout, which makes it very hard to write a fast hash table.&lt;/p&gt;
&lt;p&gt;As to why Link Time Optimization slowed down the code, I don’t know; I even tried setting codegen-units=1 as suggested &lt;a href=&quot;https://github.com/rust-lang/rust/issues/48371&quot;&gt;here&lt;/a&gt;, but to no avail.&lt;/p&gt;
&lt;h3 id=&quot;conclusion&quot;&gt;Conclusion&lt;/h3&gt;
&lt;p&gt;By porting huniq to rust and applying a number of standard optimization techniques I was able to improve the performance of filtering duplicates on the command line by a factor of 30x, compared to using the standard sort|uniq technique. With this, I was able to achieve an improvement of 4x-5x compared to huniq1, which was written in C++.&lt;/p&gt;
&lt;p&gt;In this benchmark below you can see the improvements achieved in each step (&lt;a href=&quot;https://gist.github.com/koraa/d0622d1abbc8b428fb15ed2036425dc1&quot;&gt;full benchmark&lt;/a&gt;).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;repetitions  implemetation  seconds  memory/kb
50             shell         374.30      11180
50             huniq1         54.48      26136
50             datamash       95.37      10896
50             awk            62.73     322052
50            0original       29.91      29484
50            1anyhow         29.65      29564
50            2iolock         30.76      29664
50            3noalloc        26.10      29544
50            4singlehash     23.80      29632
50            5ahash          21.35      29612
50            6fxhash         17.96      29556
50            7copyelision    15.03      29548
50            8cleanup        20.13      29668
50            9seeded-fxhas   17.17      29664
50           10cache-seed     14.42      29608
50           11xxh3           12.46      29548&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;No single step had the largest effect; most iterations improved the efficiency by 10-20 percent, but a lot of steps involved improving the hash function, so using XXH3 is probably the most important optimization that was applied to huniq. The least impactful optimization was using Stdin/Stdout::lock(), yielding no measurable performance benefit.&lt;/p&gt;
&lt;p&gt;The most unusual kind of optimization used in huniq is probably the zero copy Stdin splitter, which yielded a moderate performance improvement.&lt;/p&gt;
&lt;p&gt;One thing still irritates me though; using LTO should not necessarily yield great performance improvements, but it should not slow down the code as it did with huniq. I am still unsure how that happened; possibly a &lt;a href=&quot;https://github.com/rust-lang/rust/issues/48371&quot;&gt;regression&lt;/a&gt; in rustc? Maybe a reader can shed light on this mystery…&lt;/p&gt;
</description></item><item><title>Why implementing equals() in javascript is hard and how use Symbols to do it correctly!</title><link>https://cupdev.net/blog/011_ferrum_traits_equals.html</link><pubDate>Sun, 19 Jan 2020 20:02:19 +0100</pubDate><guid isPermaLink="true">https://cupdev.net/blog/011_ferrum_traits_equals.html</guid><author></author><description>&lt;p&gt;A while back, we released &lt;a href=&quot;https://github.com/adobe/ferrum&quot;&gt;ferrum.js&lt;/a&gt;,
a relatively small javascript library that “brings features from rust to
JavaScript” in a way that is supposed to feel native to js developers.
When we first started to write the library we began by trying to answer
two key questions; the first of which is a bit provocative I admit: Why
is there no good library for working with es6 iterators that integrates
well with javascript syntax?&lt;/p&gt;
&lt;p&gt;We decided to tackle the problem head on: by writing just such a
library!&lt;/p&gt;
&lt;p&gt;The second question we had to address, turned out to be more complex;
“How can we implement a function like &lt;code&gt;equals()&lt;/code&gt; or &lt;code&gt;hash()&lt;/code&gt; correctly
in javascript?&amp;quot; Here’s how we tackled that one, too.&lt;/p&gt;
&lt;h3 id=&quot;how-to-badly-implement-equals&quot;&gt;How to (badly) implement equals&lt;/h3&gt;
&lt;p&gt;It seems like there are a lot of implementations of these kinds of
functions; lodash has one for instance. For &lt;code&gt;hash()&lt;/code&gt; there is
&lt;a href=&quot;https://github.com/puleos/object-hash&quot;&gt;object-hash&lt;/a&gt;, which I
contributed to myself a while ago! In principle, implementing a
function like equals is relatively easy:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; assert = &lt;span class=&quot;built_in&quot;&gt;require&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;'assert'&lt;/span&gt;);

&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; equals = &lt;span class=&quot;function&quot;&gt;(&lt;span class=&quot;params&quot;&gt;a, b&lt;/span&gt;) =&amp;gt;&lt;/span&gt; {
  &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.constructor !== b.constructor) {
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;  &lt;span class=&quot;comment&quot;&gt;// Implement for a variety of simple types&lt;/span&gt;

  } &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.constructor === &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;) {
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a.toString() === b.toString();  &lt;span class=&quot;comment&quot;&gt;// Implement for data structures using recursion&lt;/span&gt;

  } &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.constructor === &lt;span class=&quot;built_in&quot;&gt;Array&lt;/span&gt;) {
    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.length !== b.length)
      &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;let&lt;/span&gt; idx = &lt;span class=&quot;number&quot;&gt;0&lt;/span&gt;; idx &amp;lt; a.length; idx++)
      &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!equals(a[idx], b[idx]))
        &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;

    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;
  } &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (a.constructor === &lt;span class=&quot;built_in&quot;&gt;Object&lt;/span&gt;) {
    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (&lt;span class=&quot;built_in&quot;&gt;Object&lt;/span&gt;.keys(a).length !== &lt;span class=&quot;built_in&quot;&gt;Object&lt;/span&gt;.keys(b).length)
      &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;    &lt;span class=&quot;keyword&quot;&gt;for&lt;/span&gt; (&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; [key, val] &lt;span class=&quot;keyword&quot;&gt;of&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Object&lt;/span&gt;.entries(a))

    &lt;span class=&quot;keyword&quot;&gt;if&lt;/span&gt; (!equals(val, b[key]))
      &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;false&lt;/span&gt;;

    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; &lt;span class=&quot;literal&quot;&gt;true&lt;/span&gt;;
  } &lt;span class=&quot;keyword&quot;&gt;else&lt;/span&gt; {
    &lt;span class=&quot;comment&quot;&gt;// Provide a fallback for any other types&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a === b;
  }
};

&lt;span class=&quot;comment&quot;&gt;// Test our equals implementation!&lt;/span&gt;
&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; d = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;();
&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; e = &lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;Date&lt;/span&gt;(d.toString())

assert(equals(
  {
    &lt;span class=&quot;attr&quot;&gt;foo&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;42&lt;/span&gt;,
    &lt;span class=&quot;attr&quot;&gt;baz&lt;/span&gt;: d,
    &lt;span class=&quot;attr&quot;&gt;bar&lt;/span&gt;: [&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;foo&quot;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;],
  },
  {
    &lt;span class=&quot;attr&quot;&gt;foo&lt;/span&gt;: &lt;span class=&quot;number&quot;&gt;42&lt;/span&gt;,
    &lt;span class=&quot;attr&quot;&gt;bar&lt;/span&gt;: [&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;&quot;foo&quot;&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;3&lt;/span&gt;],
    &lt;span class=&quot;attr&quot;&gt;baz&lt;/span&gt;: e,
  }));&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;All these implementations have a drawback though: They can’t support any
types they don’t know about; like this one for instance:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Rational&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;constructor&lt;/span&gt;(p, q) {
    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.p = p;
    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.q = q;
  }...
};

assert(equals(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Rational(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;), Rational(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)));&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Even if the &lt;code&gt;equals()&lt;/code&gt; implementation you are using has some support for
custom types (automatically comparing each field), this example would
still fail, even though &lt;code&gt;2/2&lt;/code&gt; clearly equals &lt;code&gt;1/1&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;using-ferrum-js-to-get-it-right&quot;&gt;Using ferrum.js to get it right&lt;/h3&gt;
&lt;p&gt;So, in order to implement &lt;code&gt;equals()&lt;/code&gt; correctly, we need to support all
the types your users might want to create; the function needs to be
extensible!&lt;/p&gt;
&lt;p&gt;Here is where &lt;code&gt;ferrum.js&lt;/code&gt; comes in; it provides a helper class called
&lt;a href=&quot;https://www.ferrumjs.org/module-trait-Trait.html&quot;&gt;Trait&lt;/a&gt; (one of the
features borrowed from rust — see &lt;a href=&quot;https://doc.rust-lang.org/1.8.0/book/traits.html&quot;&gt;Rust
Traits&lt;/a&gt;) to define
extension points for functions like &lt;code&gt;equals()&lt;/code&gt;. Ferrum already has an
&lt;a href=&quot;https://www.ferrumjs.org/module-stdtraits-Equals.html&quot;&gt;Equals&lt;/a&gt; trait
and an &lt;a href=&quot;https://www.ferrumjs.org/module-stdtraits.html#~eq&quot;&gt;eq()&lt;/a&gt;
function, so we can just reuse it:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-javascript&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; { Equals, eq } = &lt;span class=&quot;built_in&quot;&gt;require&lt;/span&gt;(&lt;span class=&quot;string&quot;&gt;'ferrum'&lt;/span&gt;);

&lt;span class=&quot;class&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;class&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;Rational&lt;/span&gt; &lt;/span&gt;{
  &lt;span class=&quot;keyword&quot;&gt;constructor&lt;/span&gt;(p, q) {
    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.p = p;
    &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.q = q;
  }

  &lt;span class=&quot;comment&quot;&gt;// ...&lt;/span&gt;

  normalize() {
    &lt;span class=&quot;comment&quot;&gt;// ... Normalize the rational so that 2/2 becomes 1/1&lt;/span&gt;
  }

  [Equals.sym](other) {
    &lt;span class=&quot;comment&quot;&gt;// Tell ferrum in here how to compare your custom type&lt;/span&gt;
    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; a = &lt;span class=&quot;keyword&quot;&gt;this&lt;/span&gt;.normalize();
    &lt;span class=&quot;keyword&quot;&gt;const&lt;/span&gt; b = other.normalize();
    &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; a.p == b.p &amp;amp;&amp;amp; a.q == b.q;
  }
}assert(equals(&lt;span class=&quot;keyword&quot;&gt;new&lt;/span&gt; Rational(&lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;2&lt;/span&gt;), Rational(&lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;, &lt;span class=&quot;number&quot;&gt;1&lt;/span&gt;)));&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ferrum already provides implementations of &lt;code&gt;eq()&lt;/code&gt; for all standard types
(Array, Map, Number, Date, etc.), so you just have to implement an
equality function for your new type.&lt;/p&gt;
&lt;p&gt;Internally, the library uses &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol&quot;&gt;ES6 Symbols&lt;/a&gt;
to find the implementation; this is the recommended way to implement
generic interfaces in JavaScript. All ferrum does is wrap this in order
to provide a more convenient interface to handle a lot of edge cases.&lt;/p&gt;
&lt;p&gt;The &lt;a href=&quot;https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols&quot;&gt;Iterator Protocol&lt;/a&gt;
uses Symbols in this way to implement ES6 iterators. You can even wrap
existing protocols; for instance, the &lt;a href=&quot;https://www.ferrumjs.org/module-sequence-Sequence.html&quot;&gt;Sequence Trait&lt;/a&gt; is just a
wrapper around the iterator protocol, created to make use of the
advanced edge case handling of ferrum. One example: The Sequence Trait
can support plain Objects, while the Iterator Protocol cannot.&lt;/p&gt;
&lt;p&gt;Ferrum is also designed to be null/undefined safe; many functions
explicitly handle null/undefined as a special edge case. Traits can even
be implemented for null and/or undefined; our &lt;code&gt;equals()&lt;/code&gt; implementation
above on the other hand would simply crash. Ferrum even provides the
&lt;a href=&quot;https://www.ferrumjs.org/module-typesafe.html&quot;&gt;typesafe&lt;/a&gt; module to
safely deal with null/undefined values.&lt;/p&gt;
&lt;p&gt;This was one of our main motivations when creating ferrum; while Rust
has been designed to be safe and avoid a lot of those edge cases,
JavaScript has historically had a lot of them. Ferrum is designed to
take as much of the edge case load of the developer…anything that fits
that description should probably be part of the Ferrum ecosystem — make
JavaScript a bit safer.&lt;/p&gt;
&lt;h3 id=&quot;what-s-next-&quot;&gt;What’s next?&lt;/h3&gt;
&lt;p&gt;Ferrum is currently under active development. One upcoming big feature
(again, borrowed from rust) is documentation testing. Ever found that
the examples in your documentation were full of bugs? &lt;a href=&quot;https://github.com/adobe/ferrum.doctest/&quot;&gt;This allows you
test your documentation!&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Other features expected to be released this year as a part of ferrum:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;Hash&lt;/code&gt; trait, and Hash tables supporting arbitrary keys.&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;Ord&lt;/code&gt; trait and ordered maps supporting arbitrary keys.&lt;/li&gt;
&lt;li&gt;Support for rxjs Observables and Asynchronous
Iterators; all using the familiar Ferrum Sequence api!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;This was originally posted on the &lt;a href=&quot;https://medium.com/adobetech/ferrum-traits-a32309a613e7&quot;&gt;adobe tech blog&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;
</description></item><item><title>All the fibonacci sequence algorithms you will ever need</title><link>https://cupdev.net/blog/010_fibonacci.html</link><pubDate>Mon, 19 Jun 2017 11:45:02 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/010_fibonacci.html</guid><author></author><description>&lt;p&gt;This blog post shall given an overview over different methods to compute the fibonacci sequence
or parts of it. Since this is a common interview question, you may print out this blog article
and show it to your potential employers, not only to demonstrate how specialized your abilities
are in the broad area of fibonacci computation but also to demonstrate your humor and free spirit.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR: Type &amp;quot;fast fibonacci algorithm&amp;quot; into your mobile browser before the eyes of your soon-to-be boss and download the resulting algorithm.&lt;/strong&gt;&lt;/p&gt;
&lt;h3 id=&quot;the-silly-algorithm&quot;&gt;The silly algorithm&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(wtf this is calling itself twice recursively must be something truly horrific)&lt;/em&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def fib(n):
    if n &amp;lt; 2:
        return n
    else:
        return fib(n-1) + fib(n-2)&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;the-naive-algorithm&quot;&gt;The naive algorithm&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(n)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Simply generate the entire fibonacci sequence, discarding unneeded values.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;# Utilities

def seek(n, seq):
    it = iter(seq)
    for _ in range(n):
        next(seq)
    return it

def at(n, seq):
    seek(n, seq)
    return next(seq)

# Implementation

def fib_sequence():
    a = 0
    b = 1
    while True:
        yield a
        yield b
        a += b
        b += a

def fib(n):
    return at(n, fib_sequence())&lt;/code&gt;&lt;/pre&gt;&lt;h3 id=&quot;the-sensible&quot;&gt;The sensible&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(log n)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Search the internet for &amp;quot;fast fibonacci algorithm&amp;quot;, find this page &lt;a href=&quot;https://www.nayuki.io/page/fast-fibonacci-algorithms&quot;&gt;https://www.nayuki.io/page/fast-fibonacci-algorithms&lt;/a&gt;,
and download the source code for fast doubling from that page. This is the only fibonacci implementation you will ever need.
Use this and see how amazed (or potentially angry or scared) recruiters will be at how fast you can compute any fibonacci number.&lt;/p&gt;
&lt;h3 id=&quot;bonus-recursive-naive&quot;&gt;Bonus: Recursive naive&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;O(1)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This is like the naive algorithm generating the entire sequence except that it&amp;#39;s recursive, much more pretty and it will fail after a couple
hundred iterations because the python joksters have out of pure trolling prowess not yet implemented proper &lt;a href=&quot;https://en.wikipedia.org/wiki/Tail_call&quot;&gt;tail call optimization&lt;/a&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;def fib_sequence(a=0, b=1):
    yield a
    yield from fib_sequence(b, a+b)

...&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Why neither the command line nor the GUI is usable</title><link>https://cupdev.net/blog/009_flow_based_gui.html</link><pubDate>Sun, 20 Mar 2016 18:33:50 +0100</pubDate><guid isPermaLink="true">https://cupdev.net/blog/009_flow_based_gui.html</guid><author></author><description>&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I wrote this as a comment &lt;a href=&quot;http://gandre.ws/blog/blog/2015/04/07/why-the-command-line-is-not-usable/&quot;&gt;http://gandre.ws/blog/blog/2015/04/07/why-the-command-line-is-not-usable/&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR:&lt;/strong&gt;
As you said, the shell is lacking is a way to hint users towards common use cases,
while in the GUI, it is almost impossible to combine applications.&lt;/p&gt;
&lt;p&gt;I think we need to use a new, combined approach that lets users start with user interfaces as concise as today’s excellent GUIs, but providing tools to empower users to learn the power of programming in a rewarding learning curve. Without the leap of faith that is jumping from GUI to CLI or any programming language today.&lt;/p&gt;
&lt;p&gt;—&lt;/p&gt;
&lt;p&gt;Thanks for your post; the shell is indeed entirely unsuitable for use by non-experts:
if a user opens a shell to solve a particular task (let’s say they want to display the current time), they will probably understand that they have to text something. Maybe they think of typing ‘time’ or ‘help’, but both of these commands will be entirely useless for what they want to achieve. Maybe they will take some time to research, and after a considerable time they might successfully be able to type &lt;code&gt;date&lt;/code&gt;.
Next, if they want to list the items on their desktop, they won’t have any idea where to begin with: after even more research they will learn about cd and ls, but at this point we’re just in day two of learning a programming language.&lt;/p&gt;
&lt;p&gt;In the GUI, by contrast, you are likely to find out in seconds how to do these things; you will see the current time anyways on any decent system and even from only knowing how a mouse works you can probably learn how to navigate the file system from randomly clicking on the screen within 30 minutes or so.&lt;/p&gt;
&lt;p&gt;Now let’s take a much more complex task; let’s delete all the images from a folder. This can be accomplished easily if you are an experienced shell users, yet if you are an experienced GUI user, it will be extremely difficult. I just tried to research how to “mac delete all mp3 from folder”, and the first result I got was a forum showing me an appropriate command line.&lt;/p&gt;
&lt;p&gt;We create GUIs often by analyzing what usecases an application will have and based on that we will create hints for maybe 90% (arbitrary guess) of them. We can optimize that by using sane defaults (values for preferences, or just showing all the tracks in the playlist without any need for user intervention). We can group actions/views so users can make an educated guess about where to find a certain action.
Ultimately though, there is a limit to the space of actions that can be performed using a GUI; we can only display so many options and hints until we simply can’t fit more information onto a screen: a list of 10000 preferences is about as useful as displaying none – just like we do in a shell.&lt;/p&gt;
&lt;p&gt;GUIs also put a considerable load on the programming team: I am a programmer and I’d usually estimate two times the effort for creating a terrible GUI I design myself and more than ten times the effort for creating an excellent GUI with professional designers and usability studies.
This is because good user interface design is very hard, but also because with a GUI you have to explicitly handle every single use case: if a want a feature that lets the user select a file to write to, or read from a website, I will have to built that in manually. Moreover, for the URL feature I should probably even display the website I am reading from within my application.
In the shell, I usually just assume that the user will use curl and redirection to accomplish both those features, so I can support those features without actually programming anything.&lt;/p&gt;
&lt;p&gt;GUIs show what can be achieved, by limiting what can be achieved. Having the computer hint users at what the system needs them to do quickly reaches it’s limits: ultimately the user needs to tell the computer what they want it to do.&lt;/p&gt;
&lt;p&gt;I think it is possible to combine those approaches, because in a way GUIs already do this: App stores let you expand your system and customize it to your needs. At the beginning you see a very limited set of possibilities with those applications you are most likely to use.
When you then expand your set of applications and add an application, you will have actively selected it and learn what it does.&lt;/p&gt;
&lt;p&gt;I also think, we can take that even further and create a learning curve for normal users that empowers them to expand the way they use their system and even get to a point where they can perform moderately complex programming tasks (such as removing all mp3s from a folder).&lt;/p&gt;
&lt;p&gt;It is hard to predict what such a system could look like and you’d need a big research team to get any meaningful idea, but my best guess would be having a normal GUI on top, backed by a graphical gui editor and a flow based, graphical programming language as a replacement for the shell and it’s pipes.
Simple things like moving a button, or connecting the value of one field to some data receiver could be done using drag and drop (drag a text field to the notification icon to display notifications when it changes; drag it to the browsers URL bar to automatically follow the url). You could show users what happens in the flow interface when you drag a value somewhere, to teach them about the flow interface.
If the GUI can easily be edited, this could also be useful to admins, optimizing an interface for their specific organization.
The Flow interface could be stored as a full programming language (Rust or GO or something), so you can use that for algorithms and tasks that exceed the flow interface and you could learn about the language by using the flow interface and looking at the resulting code.
You could even package sets of hints how to program as GUIs: how about a window that just displays the date in various configurations, so when you want your date in some weird format, use the GUI to configure how the date format should look like and then drag the result to the menu bar (on os x).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; I didn&amp;#39;t mention in the comment, because I don&amp;#39;t like plugging things, but this was the idea behind &lt;a href=&quot;https://shocto.de/&quot;&gt;https://shocto.de/&lt;/a&gt; , which at the moment purely exists in the form of an idea written on a website.&lt;/p&gt;
</description></item><item><title>Blackmailed with Patreon account data</title><link>https://cupdev.net/blog/008_being_blackmailed.html</link><pubDate>Sat, 21 Nov 2015 14:20:09 +0100</pubDate><guid isPermaLink="true">https://cupdev.net/blog/008_being_blackmailed.html</guid><author></author><description>&lt;p&gt;&lt;strong&gt;Note: if you receive a similar mail, don&amp;#39;t pay. Your data is already public and their claims to have sensitive data is very likely a bluff.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So, some time ago I created an account with &lt;a href=&quot;https://www.patreon.com/home?ty=a&quot;&gt;Patreon&lt;/a&gt;, mostly to support the &lt;a href=&quot;http://www.hoaxilla.com/&quot;&gt;Hoaxilla Podcast&lt;/a&gt; (check it out. They&amp;#39;re really great).
Unfortunately they &lt;a href=&quot;http://arstechnica.com/security/2015/10/patreon-some-user-names-e-mail-and-mailing-addresses-stolen/&quot;&gt;have&lt;/a&gt; been &lt;a href=&quot;http://arstechnica.com/security/2015/10/gigabytes-of-user-data-from-hack-of-patreon-donations-site-dumped-online/&quot;&gt;cracked&lt;/a&gt; end of September and lots of &lt;a href=&quot;https://patreon.thecthulhu.com/&quot;&gt;data&lt;/a&gt; &lt;a href=&quot;magnet:?xt=urn:btih:B93B1C2921EFF0846DA268968755D01B6E9698DA&amp;amp;dn=Patreon%20Leak&amp;amp;tr=udp%3a%2f%2ftracker.publicbt.com%3a80%2fannounce&amp;amp;tr=udp%3a%2f%2ftracker.openbittorrent.com%3a80%2fannounce&amp;amp;tr=udp%3a%2f%2ftracker.ccc.de%3a80%2fannounce&amp;amp;ws=https%3a%2f%2fpatreon.thecthulhu.com%2fpatredump.tar.gz%2f&quot;&gt;(torrent/magnet)&lt;/a&gt; has been leaked.&lt;/p&gt;
&lt;p&gt;So, today I received the following mail:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Subject:     Noah recommends - I will leak your identity&lt;br&gt;From:     &lt;a href=&quot;mailto:sharingservices@aol.com&quot;&gt;sharingservices@aol.com&lt;/a&gt;&lt;br&gt;Reply-To:     &lt;a href=&quot;mailto:abc8537458@163.com&quot;&gt;abc8537458@163.com&lt;/a&gt;&lt;br&gt;To:     &lt;a href=&quot;mailto:patreonjo@jayceland.com&quot;&gt;patreonjo@jayceland.com&lt;/a&gt;, &lt;a href=&quot;mailto:patreonjohari@gmail.com&quot;&gt;patreonjohari@gmail.com&lt;/a&gt;, &lt;a href=&quot;mailto:patreonkaro@cupdev.net&quot;&gt;patreonkaro@cupdev.net&lt;/a&gt;   &lt;/p&gt;
&lt;p&gt;Unfortunately your data was leaked in the recent hacking of the Patreon web site and I now have your information. I have your tax id, tax forms, SSN, DOB, Name, Address, Credit card details and more sensitive data. Now, I can go ahead and leak your details online which would damage your credit score like hell and would create a lot of problems for you.&lt;/p&gt;
&lt;p&gt;If you would like to prevent me from doing this then you need to send 1 bitcoin to the following BTC address.&lt;/p&gt;
&lt;p&gt;Bitcoin Address:
1QAQTyhCzAfvp8uLpneBNamWTNRR1hx9Cp&lt;/p&gt;
&lt;p&gt;You can buy bitcoins using online exchanges easily. The bitcoin address is unique to you. Sending bitcoin takes take, so you better get started right now, you have 48 hours in total. &lt;a href=&quot;mailto:abc8537458@163.com&quot;&gt;abc8537458@163.com&lt;/a&gt; has shared an article with you&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;a href=&quot;https://duckduckgo.com/?q=1QAQTyhCzAfvp8uLpneBNamWTNRR1hx9Cp&amp;amp;ia=bitcoinaddress&quot;&gt;(Other people also received this)&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;First blackmail of my life. Yay. Fortunately it&amp;#39;s a also bluff. The data was leaked publicly; It seems to contain postal addresses, email addresses and well encrypted passwords.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;This means, that their claims to having tax ids, tax forms, SSN, DOB and credit card details are wrong. Their claims to be able to damage your credit score are also wrong. Since the data is already public, they can not do any more harm by leaking it again.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Besides, I am pretty sure I didn&amp;#39;t even give them anything but a password, my legal name and a paypal account. So there is no way they could ever have data like a Tax ID. And what the hell is a SSN and a DOB.
The worst thing they could possibly do with the data I gave patreon in the first place is to send me money, and I wouldn&amp;#39;t object to that.&lt;/p&gt;
&lt;p&gt;In the end this just adds to the miserable experience micropayment services provide. Bot my patreon and my flatter payments started failing after a few weeks; I tried to restore flattr payments and failed. I didn&amp;#39;t even try with patreon.&lt;/p&gt;
&lt;p&gt;Patreon was probably hacked because the run the same half assed approach most projects have towards security. I mean, I am running around finding random occurrences of &lt;a href=&quot;https://github.com/mongodb/mongo-cxx-driver/pull/367&quot;&gt;possible buffer overvloas&lt;/a&gt; and &lt;a href=&quot;https://github.com/jed1/smrtlink/blob/master/src/Packet.cpp#L160&quot;&gt;private keys&lt;/a&gt; in random code I find.  The most common cause of breaches is that someone &lt;a href=&quot;https://en.wikipedia.org/wiki/Social_engineering_(security)&quot;&gt;calls and says&lt;/a&gt; &amp;quot;Hi, this is tech support. Could I please have your password&amp;quot;.&lt;/p&gt;
&lt;p&gt;How the hell are micropayments supposed to work with such sloppy tech. You are dealing with money, hire someone to do code reviews. Asshole.&lt;/p&gt;
&lt;p&gt;(The full source of the mail for anyone interested):&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;Return-Path: &amp;lt;sharingservices@aol.com&amp;gt;
X-Original-To: patreonkaro@cupdev.net
Delivered-To: mapc@cupdev.net
Received: from taclomr-a001e.mx.aol.com (taclomr-a001e.mx.aol.com [204.29.187.81])
    (using TLSv1 with cipher ADH-AES256-SHA (256/256 bits))
    (No client certificate requested)
    by cupdev.net (Postfix) with ESMTPS id BCB4E203C1E
    for &amp;lt;patreonkaro@cupdev.net&amp;gt;; Sat, 21 Nov 2015 12:30:12 +0100 (CET)
Received: from vm-149-174-150-116.asset.aol.com (vm-149-174-150-116.asset.aol.com [149.174.150.116])
    by taclomr-a001e.mx.aol.com (Outbound Mail Relay) with ESMTP id 1104F3800214;
    Sat, 21 Nov 2015 06:30:10 -0500 (EST)
From: sharingservices@aol.com
Reply-To: abc8537458@163.com
To: patreonjo@jayceland.com, patreonjohari@gmail.com, patreonkaro@cupdev.net
Message-ID: &amp;lt;534381049.34352343.1448105409977.JavaMail.dpadmin@vm-149-174-150-116.asset.aol.com&amp;gt;
Subject: Noah recommends  - I will leak your identity
MIME-Version: 1.0
Content-Type: text/html; charset=us-ascii
Content-Transfer-Encoding: 7bit
From-IP-Address: 172.29.108.145

Unfortunately your data was leaked in the recent hacking of the Patreon web site and I now have your information. I have your tax id, tax forms, SSN, DOB, Name, Address, Credit card details and more sensitive data. Now, I can go ahead and leak your details online which would damage your credit score like hell and would create a lot of problems for you.
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
If you would like to prevent me from doing this then you need to send 1 bitcoin to the following BTC address.
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
Bitcoin Address:
&amp;lt;br&amp;gt;
1QAQTyhCzAfvp8uLpneBNamWTNRR1hx9Cp
&amp;lt;br&amp;gt;&amp;lt;br&amp;gt;
You can buy bitcoins using online exchanges easily. The bitcoin address is unique to you. Sending bitcoin takes take, so you better get started right now, you have 48 hours in total.
&amp;lt;title&amp;gt;abc8537458@163.com has shared an article with you&amp;lt;/title&amp;gt;&lt;/code&gt;&lt;/pre&gt;</description></item><item><title>Refactoring Sauerbraten – When two STLs break</title><link>https://cupdev.net/blog/007_when_stl_crashes.html</link><pubDate>Mon, 09 Nov 2015 11:33:36 +0100</pubDate><guid isPermaLink="true">https://cupdev.net/blog/007_when_stl_crashes.html</guid><author></author><description>&lt;p&gt;Yesterday night I found &lt;a href=&quot;https://github.com/inexor-game/code/commit/ba8dd46289e39a51a67b40fe32d3e19607b63f2e&quot;&gt;this commit&lt;/a&gt; in one of the branches
of Inexor:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-diff&quot;&gt;commit ba8dd46289e39a51a67b40fe32d3e19607b63f2e
Author: a_teammate &amp;lt;madoe3@web.de&amp;gt;
Date:   Wed Nov 4 12:29:11 2015 +0100

    replace std::min max with selfwritten implementations to fix lightmapping

    vec::min/max were broken with the std versions

diff --git a/inexor/shared/tools.h b/inexor/shared/tools.h
index 6a32520..51f9d20 100644
&lt;span class=&quot;comment&quot;&gt;--- a/inexor/shared/tools.h&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;+++ b/inexor/shared/tools.h&lt;/span&gt;
@@ -40,8 +40,13 @@ typedef unsigned long long int ullong;
 #endif

 using std::swap;
&lt;span class=&quot;deletion&quot;&gt;-using std::min;&lt;/span&gt;
&lt;span class=&quot;deletion&quot;&gt;-using std::max;&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+/// return the minimal value of the two given.&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+/// we do not use the std:: version here because it crashes inside the vec-implementation.&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+template&amp;lt;class A, class B&amp;gt; inline A(min)(A val1, B val2) { return val1 &amp;gt; val2 ? val2 : val1; }&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+/// return the bigger value of the two given.&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+/// we do not use the std:: version here because it crashes inside the vec-implementation.&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+template&amp;lt;class A, class B&amp;gt; inline A(max)(A val1, B val2) { return val2 &amp;gt; val1 ? val2 : val1; }&lt;/span&gt;
&lt;span class=&quot;addition&quot;&gt;+&lt;/span&gt;
 using boost::algorithm::clamp;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Sauerbraten has a lot of self written implementations for
a lot of standard algorithms and containers. That includes
things like vector, hashmaps (unordered_map), sorting
algorithms and also min, max and clamp implementations and
even it&amp;#39;s own math and crypto libraries.
It has been argued that the predecessor of Sauerbraten – Cube
– is so old, that all the libraries did not exist back then,
but I looked it up and both OpenSSL and the first
standardization of C++98 date back do 1998 while Cube
started development in 2001.&lt;/p&gt;
&lt;p&gt;In the course of Inexor development I was trying to replace
at least a tiny little part of the sauerbraten special STL
with the standard stuff, because the sauerbraten
implementations do have some nasty stuff.&lt;/p&gt;
&lt;p&gt;Here is an &lt;a href=&quot;https://github.com/inexor-game/code/blob/master/inexor/shared/tools.h#L739&quot;&gt;except from the sauerbraten vector implementation&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-c++&quot;&gt;  &lt;span class=&quot;comment&quot;&gt;/// get the last index and decrement the vector's size&lt;/span&gt;
  &lt;span class=&quot;function&quot;&gt;T &amp;amp;&lt;span class=&quot;title&quot;&gt;pop&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;()&lt;/span&gt; &lt;/span&gt;{ &lt;span class=&quot;keyword&quot;&gt;return&lt;/span&gt; buf[--ulen]; }&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is a pop method. It should remove the last element and
pass it to the caller. Maybe by using &lt;a href=&quot;https://en.wikipedia.org/wiki/Return_value_optimization&quot;&gt;return value optimization&lt;/a&gt;
r possibly by taking a writable lvalue reference from the outside and moving/swapping into that.
The STL vector&amp;#39;s pop() just deletes the last element because
both of the above implementations of pop are not &lt;a href=&quot;https://stackoverflow.com/questions/12206242/store-results-of-stdstack-pop-method-into-a-variable&quot;&gt;quite&lt;/a&gt;
&lt;a href=&quot;https://stackoverflow.com/questions/25035691/why-stdqueuepop-doesnt-returns-value&quot;&gt;optimal&lt;/a&gt;.
The sauer implementation does neither and just returns
a reference to the last element in the vector&amp;#39;s buffer and
marks that element as non-existent.&lt;br&gt;This is extremely dangerous; first of all any successive
push/appends will overwrite the old element; secondly the
destruction of the element is now in the hands of the caller
who would need to manually call the destructor so the code
behaves correctly (of course this would have to be done
before another element is appended). Unfortunately large
parts of the Sauerbraten code rely on such misbehaviour and
thus I was unable to remove them easily.&lt;/p&gt;
&lt;p&gt;I was however able to replace the implementations of
&lt;a href=&quot;https://github.com/inexor-game/code/commit/8efb9efd1c1bb0ccd9e47e07c0c698b609135be0&quot;&gt;min, max, clamp and swap&lt;/a&gt;
and quite recently I was also able to replace sauerbratens
&lt;a href=&quot;https://github.com/inexor-game/code/commit/6a1e4d686a3a4d7c21828a97712486101038f4f7&quot;&gt;custom&lt;/a&gt;
&lt;a href=&quot;https://github.com/inexor-game/code/commit/8b7dac4d71ef9b8fc7cbebe9da7ca40ba03546f8&quot;&gt;random number generator&lt;/a&gt;.
Though even that created some &lt;a href=&quot;https://github.com/inexor-game/code/commit/a32ccaf578839a02193ea1af9e1ae5c904aa4a34&quot;&gt;problems&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now one of the other Inexor developers reintroduced the old
implementations of min/max because STL implementation of std::min was crashing.
This kind of problem already smelled like a deeper
underlying problem so I decided to investigate:&lt;/p&gt;
&lt;p&gt;First of all, I tried to reproduce the problem and I failed
on recent clang and gcc versions, so it must be some
compiler related problem.&lt;/p&gt;
&lt;p&gt;Then I looked at the signature of both versions of min/max;
maybe some code relied on the quirks of sauerbratens
min/max, just like with vector::pop().
And indeed found a difference – the STL version of min max
takes a single template argument and operates entirely on
lvalue references while the sauerbraten version takes two
template parameters (one for each parameter), uses the
first parameter&amp;#39;s type as return value and operates entirely
by value rather than by reference.&lt;br&gt;I looked at the code that crashed but I found nothing to
indicate such a problem.&lt;/p&gt;
&lt;p&gt;Finally I got access to some from the
crash itself:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;STacktrace:

&amp;gt;    inexor.exe!_VCrtDbgReportW(int nRptType, void * returnAddress, const wchar_t * szFile, int nLine, const wchar_t * szModule, const wchar_t * szFormat, char * arglist) Line 481    C++
     inexor.exe!_CrtDbgReportW(int report_type, const wchar_t * file_name, int line_number, const wchar_t * module_name, const wchar_t * format, ...) Line 273    C++
     [External Code]    
     inexor.exe!vec::min(const vec &amp;amp; o) Line 156    C++
     inexor.exe!genclipplanes(const cube &amp;amp; c, const ivec &amp;amp; co, int size, clipplanes &amp;amp; p, bool collide) Line 1220    C++
     inexor.exe!getclipplanes(const cube &amp;amp; c, const ivec &amp;amp; o, int size, bool collide, int offset) Line 22    C++

from _CrtDbgReportW on were somewhere inside error reporting code probably. however checking the values of the variables inside that code reveals an error inside algorithm:4178 which is:

definition where we get stuck inside std::min:

        // TEMPLATE FUNCTION min
template&amp;lt;class _Ty&amp;gt; inline

    _Post_equal_to_(_Right &amp;lt; _Left ? _Right : _Left)

    _CONST_FUN const _Ty&amp;amp; (min)(const _Ty&amp;amp; _Left, const _Ty&amp;amp; _Right)
    {    // return smaller of _Left and _Right
    return (_DEBUG_LT(_Right, _Left) ? _Right : _Left); /// &amp;lt;- THIS IS the line which crashes
    }&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Here you can see that it really crashes inside the min
implementation. A look at the stack trace reveals that
&lt;code&gt;_CrtDbgReportW&lt;/code&gt; and &lt;code&gt;_VCrtDbgReportW&lt;/code&gt; are being called; at
first I though those where outputting debug info about the
crash, but apparently there wasn&amp;#39;t any, so we tried
compiling in Release mode and the crash was gone.&lt;/p&gt;
&lt;p&gt;Seems we found a bug in the Visual C++ STL Debug version;
serves to remind that you should always trace bugs to the
root cause before patching them.&lt;/p&gt;
&lt;p&gt;We had recently updated to Visual Studio 2015 and I guess
that introduced the problem.&lt;/p&gt;
&lt;p&gt;If you want to reproduce this, I suggest you try with Visual
Studio 2015 (minor update 1) and the current &lt;a href=&quot;https://github.com/inexor-game/code/tree/dad67eec5cf68a7ea57821ef47af183126ecfc01&quot;&gt;master at the time of this writing&lt;/a&gt;.&lt;/p&gt;
</description></item><item><title>Hetzner Supportanfrage zu Zensur</title><link>https://cupdev.net/blog/006hetzner_supportanfrage_zu_zensur.html</link><pubDate>Sat, 09  Aug 2014 11:03:28 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/006hetzner_supportanfrage_zu_zensur.html</guid><author></author><description>&lt;p&gt;Ich habe gerade einen
&lt;a href=&quot;http://www.heise.de/newsticker/meldung/Reporter-ohne-Grenzen-Russland-versucht-im-Ausland-zu-zensieren-2289163.html?wt_mc=rss.ho.beitrag.rdf&quot;&gt;Heise Artikel&lt;/a&gt;
und einen
&lt;a href=&quot;http://www.spiegel.de/netzwelt/netzpolitik/webhoster-hetzner-fordert-zensur-von-ukrainischer-website-glavcom-a-985147.html#js-article-comments-box-pager&quot;&gt;Artikel auf SPON&lt;/a&gt;
gelesen in denen beschrieben wird, dass Hetzner offenbar den
Zensurwüschen der Russischen regierung nachkommt. Das passt
mir nicht, weil mein eigener Server ja auch bei Hetzner
läuft, also habe ich beschlossen mal ne Supportanfrage zu
senden (und so vielleicht etwas Druck aufzubauen):&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Sehr geehrte Damen und Herren,
ich habe soeben folgenden Spiegel Artikel gelesen:&lt;/p&gt;
&lt;p&gt;Webhoster Hetzner: Deutsche Firma hilft russischer Medienaufsicht bei Zensur&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;http://www.spiegel.de/netzwelt/netzpolitik/webhoster-hetzner-fordert-zensur-von-ukrainischer-website-glavcom-a-985147.html#js-article-comments-box-pager&quot;&gt;http://www.spiegel.de/netzwelt/netzpolitik/webhoster-hetzner-fordert-zensur-von-ukrainischer-website-glavcom-a-985147.html#js-article-comments-box-pager&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Darin wird beschrieben, dass sie eine Mitteilung der russischen Medienaufsicht erhalten haben, die die Aufforderung enthielt teile der Ukrainischen Seite Glavcom zu Zensieren.
Offenbar haben sie darauf reagiert indem sie die Website aufgefordert haben, die Inhalte vom Netz zu nehmen.&lt;/p&gt;
&lt;p&gt;Das irritiert mich sehr, denn sie sind einen Deutsche Firma und ich hätte von ihnen erwartet, dass sie die Interessen ihrer Kunden wahren.&lt;/p&gt;
&lt;p&gt;Bitte erläutern sie, wie rechtfertigen sie diese Vorgehensweise? Inwiefern widersprechen die Inhalte auf der Seite Glavcom Punkt 6.2 ihrer AGB?
Im lichte auf meine eigenen Webseiten, möchte ich außerdem wissen unter welchen Voraussetzungen sie weitere Zensurmaßnahmen durchführen werden? Ist generell damit zu rechnen, dass den Zensurwünschen anderer Regierungen nachkommen?&lt;/p&gt;
&lt;p&gt;Mit freundlichen Grüßen,
Karolin Varner&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;em&gt;Die Anfrage lizensiere ich natürlich unter CC-0 und ich
lade alle anderen Herzlich ein dieses Schreiben als Vorlage
für ihre eigenen Anfragen zu benutzen!&lt;/em&gt;&lt;/p&gt;
&lt;h3 id=&quot;update&quot;&gt;Update&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;(Heute ist der 17.3.2015)&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hetzner hat mir in der Tat geantwortet und das auch recht
schnell – also zumindest viel, viel schneller als ich das
hier veröffentliche.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Guten Tag,&lt;/p&gt;
&lt;p&gt;Wir möchten uns zu dem von Spiegel Online veröffentlichten Artikel wie folgt äußern.&lt;/p&gt;
&lt;p&gt;Wir als Webhosting-Unternehmen konzentrieren uns auf unsere Kernkompetenz, unseren
Kunden auf aller Welt Leistungen rund um
das Hosten von Webseiten bereit zu stellen, und halten uns politisch neutral. Wir
pflegen keine politischen Beziehungen im In- und Ausland.&lt;/p&gt;
&lt;p&gt;Grundsätzlich werden bei uns alle Beschwerden gleich behandelt.
Sobald eine Beschwerde über eine auf unseren Servern gehostete
Webseite eingeht, wird die Beschwerde formell geprüft und der betroffene Kunde per
E-Mail an die bei uns hinterlegte E-Mail-Adresse informiert und gebeten, binnen 24
Stunden eine Stellungnahme dazu abzugeben.&lt;/p&gt;
&lt;p&gt;Bei der formellen Prüfung prüfen wir, ob die beanstandete
Webseite tatsächlich bei Hetzner Online gehostet wird. Darüber hinaus erfolgt eine
erste Blickprüfung der Webseite, eine inhaltliche Prüfung findet in dieser Stufe
noch nicht statt.&lt;/p&gt;
&lt;p&gt;Erfolgt nach Fristablauf keine Reaktion/Stellungnahme des Kunden, so wird eine
Erinnerung an den Kunden gesendet, mit Angabe einer evtl. Sperrung bei weiterer
Nichtreaktion.&lt;/p&gt;
&lt;p&gt;Bei weiterer Nichtreaktion wird diese Erinnerung nach weiteren
24 Stunden in der Regel nochmals versendet. Reagiert der Kunde weiterhin nicht,
wird der Inhalt der beanstandeten Webseite geprüft und ggf. die Sperrung
durchgeführt, um Schaden für den Kunden und Hetzner Online abzuwenden.&lt;/p&gt;
&lt;p&gt;In dem von Spiegel Online veröffentlichten Fall wurde von unserem Kunden auf
unsere Anfragen nicht fristgerecht eingegangen. Eine Serversperrung ist trotz der
mangelnden Kommunikation des Kunden nicht erfolgt.&lt;/p&gt;
&lt;p&gt;Bezüglich des Inhalts der angemahnten Website (sogut das über die Sprachbarriere
hinweg möglich ist) sehen wir unsererseits keinen
Grund, das Abuse-Ticket weiter zu verfolgen. Der Kunde wurde darüber informiert,
dass wir das Abuse-Ticket schliessen, und unsererseits keine weiteren Schritte
notwendig sind. Was uns in künftigen ähnlichen Fällen sehr helfen würde, wäre eine
Stellungnahme des Kunden. Wenn man die Argumente beider Seiten kennt, fällt eine
vernünftige Entscheidung im Abuse-Vorgang wohlmöglich leichter, als wenn nur die
Beschwerde eines Beschwerdeführers vorliegt, welche vom Kunden ignoriert wird.&lt;/p&gt;
&lt;p&gt;Wir bedauern den Vorfall sehr und hoffen, dass die kritischen Stimmen unsere
Vorgehensweise nachvollziehen können.&lt;/p&gt;
&lt;p&gt;Mit freundlichen Grüßen / Best Regards
[NAME ENTFERNT]&lt;/p&gt;
&lt;/blockquote&gt;
</description></item><item><title>Non breaking multi line strings in Ruby</title><link>https://cupdev.net/blog/005non_breaking_multiline_strings_in_ruby.html</link><pubDate>Fri, 08  Aug 2014 12:44:49 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/005non_breaking_multiline_strings_in_ruby.html</guid><author></author><description>&lt;p&gt;Personally I like my code to be no longer than 60 characters
(that&amp;#39;s because so I can comfortably split my Vim screen and
view two files side by side).&lt;br&gt;When I am coding rails it often happens that I need to
create some error message or user feedback and these strings
get far longer than 60 characters normally. Until now I&amp;#39;ve
split my lines using &lt;code&gt;+&lt;/code&gt; in these cases.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;print &lt;span class=&quot;string&quot;&gt;&quot;This is a nice, long string giving you some &quot;&lt;/span&gt; +
    &lt;span class=&quot;string&quot;&gt;&quot;feedback. Unfortunately it does not fit on the &quot;&lt;/span&gt; +
    &lt;span class=&quot;string&quot;&gt;&quot;screen so I have to split it.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I dislike that syntax because it is a lot of hassle to get
the spaces and the quotes right. There seem to be a few
better syntaxes (according to &lt;a href=&quot;https://stackoverflow.com/questions/10522414/breaking-up-long-strings-on-multiple-lines-in-ruby-without-stripping-newlines&quot;&gt;this StackOverflow
Question&lt;/a&gt;),
but they do not substantially improve the situation I think:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;print &lt;span class=&quot;string&quot;&gt;&quot;This is a nice, long string giving you some &quot;&lt;/span&gt;\
      &lt;span class=&quot;string&quot;&gt;&quot;feedback. Unfortunately it does not fit on the &quot;&lt;/span&gt;\
      &lt;span class=&quot;string&quot;&gt;&quot;screen so I have to split it.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The solution I came up with was a little helper function:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;comment&quot;&gt;# Helper for multi line strings:&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# Normalizes the string, so that every sequence of spaces is&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# replaced by a single space.&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# This also strips the string.&lt;/span&gt;
&lt;span class=&quot;function&quot;&gt;&lt;span class=&quot;keyword&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;title&quot;&gt;NOCR&lt;/span&gt;&lt;span class=&quot;params&quot;&gt;(s)&lt;/span&gt;&lt;/span&gt;
  s.gsub!(&lt;span class=&quot;regexp&quot;&gt;/\s\s*/&lt;/span&gt;, &lt;span class=&quot;string&quot;&gt;' '&lt;/span&gt;)
  s.strip!
  s
&lt;span class=&quot;keyword&quot;&gt;end&lt;/span&gt;

print NOCR &lt;span class=&quot;string&quot;&gt;&quot;This is a nice, long string giving you some
    feedback. Unfortunately it does not fit on the screen
    screen so I have to split it.&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is still not a perfect solution, but it at least saves
me the hassle of manually formatting the spaces and adding
lots of quotes.&lt;/p&gt;
&lt;p&gt;Of course, when using this, support for inserting newlines
or tabs is completely gone. It would be possible to use some
kind of escape syntax (&lt;code&gt;%%&lt;/code&gt;, &lt;code&gt;%n&lt;/code&gt;, &lt;code&gt;%t&lt;/code&gt;, &lt;code&gt;%s&lt;/code&gt;) to introduce
it again, but I think in these cases it is better to fall
back to manual formatting.&lt;/p&gt;
</description></item><item><title>Git stats – LOC per author in the current head</title><link>https://cupdev.net/blog/004git_statistic_loc_per_author.html</link><pubDate>Fri, 01  Aug 2014 04:08:47 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/004git_statistic_loc_per_author.html</guid><author></author><description>&lt;p&gt;So suddenly I am fluent in awk. Well, this is unexpected!&lt;/p&gt;
&lt;p&gt;I&amp;#39;ve been working on one of my projects for quite a while
and today I got interested in how much code I actually
produced, so I wrote a little script to generate that
statistic:&lt;/p&gt;
&lt;p&gt;&lt;gist url=&quot;&quot;&gt;&lt;/gist&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;meta&quot;&gt;#! /bin/bash&lt;/span&gt;
&lt;span class=&quot;comment&quot;&gt;# List the amount of code per author in the current HEAD&lt;/span&gt;

git ls-files &lt;span class=&quot;string&quot;&gt;&quot;&lt;span class=&quot;variable&quot;&gt;$@&lt;/span&gt;&quot;&lt;/span&gt; | xargs -l1 git blame -s -- | awk &lt;span class=&quot;string&quot;&gt;'
  function get_author(commit) {
    author = commit_map[commit]
    if (author == &quot;&quot;) {
      cmd = &quot;git show -s --pretty=format:%ae &quot; commit 
      cmd | getline author
      commit_map[commit] = author
      close(cmd)
    }
    return author
  }

  {
    author = get_author($1)
    counter[author] = counter[author] + 1
    if (counter[author] % 500 == 0)
      print($1 &quot; -&amp;gt; &quot; author &quot; -&amp;gt; &quot; counter[author]) | &quot;cat &amp;gt;&amp;amp;2&quot;
  }

  END {
    for (author in counter) {
      print counter[author] &quot; &quot; author
    }
  }
'&lt;/span&gt; | sort -n | column -t&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://gist.github.com/koraa/6f66cdc7f99848035892/raw/d337ce21230f9be2ab96209fe2177d32b28a745c/author-stat.sh&quot;&gt;Github Gist&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;This lists the files in the current head, git-blames each of
those and runs the result through AWK.
Awk does the author lookup (caches the result in an
associative array) and then amount of lines for each author
in another associative array.
Finally the result is being printed, sorted and formatted.&lt;/p&gt;
</description></item><item><title>Shuffling movies with mplayer and bash</title><link>https://cupdev.net/blog/003randommovies.html</link><pubDate>Thu, 08  Aug 2013 22:20:05 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/003randommovies.html</guid><author></author><description>&lt;p&gt;Suppose you have a bunch of movies in a directory and want
to play them randomly; switch into that directory and run:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ find -print0 | sort -zR | xargs -0 mplayer&lt;/code&gt;&lt;/pre&gt;
&lt;ol&gt;
&lt;li&gt;Generate a list of files in this directory and it&amp;#39;s
subdirectories; the list is zero terminated because I
have some special characters in my filenames&lt;/li&gt;
&lt;li&gt;Shuffle the list with &lt;code&gt;sort -R&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;Pass each line as an argument to &lt;code&gt;mplayer&lt;/code&gt;&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The zero-termination of the list is accomplished with
&lt;code&gt;find -print0&lt;/code&gt;, &lt;code&gt;sort -z&lt;/code&gt; and &lt;code&gt;xargs -0&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;You can of course alter the find command: For instance use
&lt;code&gt;find -maxdepth 1&lt;/code&gt; to skip subdirectories.&lt;/p&gt;
</description></item><item><title>Batch rename in Bash</title><link>https://cupdev.net/blog/002batchrename.html</link><pubDate>Sun, 12 May 2013 23:25:53 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/002batchrename.html</guid><author></author><description>&lt;p&gt;There are a few tools that provide batch renaming for the shell,
but most of them are quite huge and need installing.
It is not necessary to use these utilities,
because unix already all tools necessary:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls -d *.txt | sed &lt;span class=&quot;string&quot;&gt;'p;s/foo/bar/'&lt;/span&gt; | xargs -l2 mv&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first part should be quit clear: Print all files ending with
&lt;code&gt;txt&lt;/code&gt;.
The &lt;code&gt;\*.txt&lt;/code&gt; makes use of the shell&amp;#39;s globbing features
and filters all the &lt;code&gt;.txt&lt;/code&gt; files.
The &lt;code&gt;-d&lt;/code&gt; switch tells &lt;code&gt;ls&lt;/code&gt; not to print the contents of directories.&lt;/p&gt;
&lt;p&gt;The sed expression consists of two parts: &lt;code&gt;p&lt;/code&gt; prints
the current line and &lt;code&gt;s/foo/bar/&lt;/code&gt; is the actual transformation
(in this case: a replacement).
If I run this on my home directory I get this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls
down  duh  files  fuu  fuubar pr0j  tmp  usr

$ ls | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt;
down
down
duh
duh
files
files
fuu
bar
fuubar
barbar
pr0j
pr0j
tmp
tmp
usr
usr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that most files have just been printed twice,
but &lt;code&gt;fuu&lt;/code&gt;  and &lt;code&gt;fuubar&lt;/code&gt; where changed to &lt;code&gt;bar&lt;/code&gt; and &lt;code&gt;barbar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now comes the tricky bit: &lt;code&gt;xargs&lt;/code&gt; takes each two lines
and applies them to &lt;code&gt;mv&lt;/code&gt; as arguments,
so when I run xargs in debug mode I get this:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | xargs -l2 &lt;span class=&quot;built_in&quot;&gt;echo&lt;/span&gt; mv
mv down down
mv duh duh
mv files files
mv fuu bar
mv fuubar barbar
mv pr0j pr0j
mv tmp tmp
mv usr usr&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice that I did not use the &lt;code&gt;&amp;#39;-d&amp;#39;&lt;/code&gt; flag this time,
because I print the content of the directory &lt;code&gt;&amp;#39;.&amp;#39;&lt;/code&gt; this time,
not a list of given files.
This would happen if I did use &lt;code&gt;&amp;#39;-d&amp;#39;&lt;/code&gt;.&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls -d
.

$ ls | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | xargs -l2 &lt;span class=&quot;built_in&quot;&gt;echo&lt;/span&gt; mv
mv . .&lt;/code&gt;&lt;/pre&gt;
&lt;h3 id=&quot;getting-complicated&quot;&gt;Getting complicated&lt;/h3&gt;
&lt;p&gt;In the above example I did not do any filtering,
because the files &lt;code&gt;foo&lt;/code&gt; and &lt;code&gt;foobar&lt;/code&gt;
(which existed before I began to write this article)
do not have an extension, but I could use a filter to select only those files I
actually want to rename:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls -d *fuu* | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | xargs -l2 &lt;span class=&quot;built_in&quot;&gt;echo&lt;/span&gt; mv
mv fuu bar
mv fuubar barbar&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can get as elaborate as I want with my filter if I use grep;
here is the same as above using grep:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls | grep &lt;span class=&quot;string&quot;&gt;'fuu'&lt;/span&gt; | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | xargs -l2 &lt;span class=&quot;built_in&quot;&gt;echo&lt;/span&gt; mv
mv fuu bar
mv fuubar barbar&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Instad of using xargs you can also use a while loop;
I use that variant to save me the trouble of dealing with escaping in xargs:&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ ls | grep &lt;span class=&quot;string&quot;&gt;'fuu'&lt;/span&gt; | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | &lt;span class=&quot;keyword&quot;&gt;while&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;read&lt;/span&gt; a &amp;amp;&amp;amp; &lt;span class=&quot;built_in&quot;&gt;read&lt;/span&gt; b; &lt;span class=&quot;keyword&quot;&gt;do&lt;/span&gt; &lt;span class=&quot;built_in&quot;&gt;echo&lt;/span&gt; mv &lt;span class=&quot;string&quot;&gt;&quot;&lt;span class=&quot;variable&quot;&gt;$a&lt;/span&gt;&quot;&lt;/span&gt; &lt;span class=&quot;string&quot;&gt;&quot;&lt;span class=&quot;variable&quot;&gt;$b&lt;/span&gt;&quot;&lt;/span&gt;; &lt;span class=&quot;keyword&quot;&gt;done&lt;/span&gt;
mv fuu bar
mv fuubar barbar&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;One last example, where we replace files recursively in the home directory:
I use &lt;code&gt;find&lt;/code&gt; instead of &lt;code&gt;ls&lt;/code&gt; which lists a directory recursively
(I am not actually running this and neither should you):&lt;/p&gt;
&lt;pre&gt;&lt;code class=&quot;language-bash&quot;&gt;$ find | sed &lt;span class=&quot;string&quot;&gt;'p;s/fuu/bar/'&lt;/span&gt; | xargs -l2 mv
...&lt;/code&gt;&lt;/pre&gt;
</description></item><item><title>Hello World</title><link>https://cupdev.net/blog/001helloworld.html</link><pubDate>Mon, 06 May 2013 23:30:36 +0200</pubDate><guid isPermaLink="true">https://cupdev.net/blog/001helloworld.html</guid><author></author><description>&lt;p&gt;Soo. If you can see this it means I managed to setup my blog.
&lt;em&gt;Yaaay&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;A wonderful world awaits you on this blog…just not yet.
Move along. Nothing to see here.&lt;/p&gt;
</description></item></channel></rss>
