<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
	<title>Andrew Steinborn</title>
	<subtitle>Full-stack software engineer, coffee drinker living in NYC.</subtitle>
	
	<link href="https://steinborn.me/feed/feed.xml" rel="self"/>
	<link href="https://steinborn.me/"/>
	<updated>2025-03-05T00:00:00Z</updated>
	<id>https://steinborn.me/</id>
	<author>
		<name>Andrew Steinborn</name>
		<email>andrew@steinborn.me</email>
	</author>
	
	<entry>
		<title>☄️ Precipices</title>
		<link href="https://steinborn.me/posts/precipices/"/>
		<updated>2025-03-05T00:00:00Z</updated>
		<id>https://steinborn.me/posts/precipices/</id>
		<content type="html">&lt;div class=&quot;p-4 bg-teal color-black lh-normal&quot;&gt;
  &lt;strong&gt;This is a work of fiction&lt;/strong&gt;. Names, characters, businesses, places, events, locales, and incidents are either the products of the author’s imagination or used in a fictitious manner. Any resemblance to actual persons, living or dead, or actual events is purely coincidental.&lt;br /&gt;&lt;br /&gt;
    In particular, &lt;strong&gt;Caspoke&lt;/strong&gt; and &lt;strong&gt;Wedge&lt;/strong&gt; are fictional companies. Any resemblance to real companies is purely coincidental.
&lt;/div&gt;
&lt;h2 id=&quot;on-the-precipice-of-success&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Success &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-success&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Samuel strutted into the French bakery, the cold, bitter air outside biting at him. The aroma of freshly ground coffee beans and buttery pastries welcomed him in, a little haven in a world that was up in flames. He placed his order: a potato confit garlic quiche, a danish, and a latte with oat milk. While he waited for his order, Samuel glanced outside the window. An elevated train rumbled overhead, its steel frame casting a shadow over the street below, as it ferried people between the boroughs, a steady constant in the swirling chaos.&lt;/p&gt;
&lt;p&gt;Now with his food, Samuel scrolled through his phone while eating. His employer was on the verge of going public. Ten years ago, buying pizza for his family was a stretch. Now, he stood at the precipice of becoming a millionaire, even after taxes. Company DSCLSRE channels buzzed with dreams of early retirement, luxury cars, high-end vacations, mortgage payoffs, and kids&#39; college funds. Samuel, ever practical, had no debt, no significant other, and no major expenses beyond rent. His plan was modest: sell some stock, indulge in a nice vacation to Paris, and let the rest ride.&lt;/p&gt;
&lt;p&gt;Technically, Samuel was supposed to be out of office, but who in the startup world truly unplugged, especially with life-changing money in the pipeline? The boundary between work and rest had long since blurred. He justified his compulsion—he had earned the right to hover.&lt;/p&gt;
&lt;p&gt;After scrolling around DSCLSRE, he opened Facegrind, his sole link to home. Baby and truck pictures from rural Georgia filled his feed. Not many opportunities back home. &amp;quot;They could never imagine being a millionaire like me,&amp;quot; he thought. It was a poignant reminder of how far he&#39;d come.&lt;/p&gt;
&lt;p&gt;Then there was Oblivious. He hesitated but opened the app. Layoff gossip flooded the tech scene. Comments ranged from bitter to panicked to resigned. Older workers remarked that this was just 2008 all over again. Others shrugged it off—2008 was so long ago!&lt;/p&gt;
&lt;p&gt;A post caught his eye: &amp;quot;Got laid off. Severance won’t last. Any leads?&amp;quot; The user was from his company. Samuel hoped it was a mistake. He didn’t check. Sometimes ignorance was a blessing.&lt;/p&gt;
&lt;p&gt;Samuel locked his phone and wandered the neighborhood. The park, the sketchy-yet-reliable bodega—all staples of his routine. More kids played in the park these days, their parents conspicuously whiter and bearing pricy strollers. Remittance shops specializing in transfers to Latin America were substituted by artisanal coffee shops serving expensive pour-overs to the keyboard warrior class. Samuel, with his quarter-million-dollar salary, was part of that shift. Whatever. Rent was still acceptable—for now.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Jules lived in a dilapidated, dimly-lit basement apartment somewhere deep in Brooklyn. The persistent mold made his eyes itch daily, and rats scurried about, disrupting his sleep and fueling his nightmares. Despite the poor condition, the rent remained steep, the price of desperation after a rushed search for housing after his girlfriend broke up with him.&lt;/p&gt;
&lt;p&gt;Rent was just one layer of Jules&#39; problems. Jules chased his dreams of being a software engineer, attending the University of Michigan at Ann Arbor, where he did well—at the cost of his now omnipresent student loan debt. Opening up the student loan payment portal was a constant dread.&lt;/p&gt;
&lt;p&gt;Jules&#39; last job at a big tech company had ended in a layoff. Caspoke hadn&#39;t been his first choice, but given the job market back in 2022, he had to take it. Caspoke promised him the world—&amp;quot;home automation that &lt;em&gt;works&lt;/em&gt;&amp;quot;, unlimited opportunity, quick career progression, and a slightly higher salary.&lt;/p&gt;
&lt;p&gt;His manager, Samuel, was supportive, engaging, and genuinely interested in Jules’ growth. Samuel&#39;s guiding principle was that success was based on luck, but that you could improve your odds. He encouraged Jules to be an active contributor to Caspoke&#39;s engineering culture. To that end, Jules hosted a bi-weekly engineering meeting where other engineers would introduce projects they&#39;d been working on. Last meeting, he presented on build time improvements to the company&#39;s continuous integration process.&lt;/p&gt;
&lt;p&gt;He was at the precipice of being elevated—last week, Samuel said that he&#39;d compile a promotion packet for him for next quarter.&lt;/p&gt;
&lt;h2 id=&quot;on-the-precipice-of-being-undone&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Being Undone &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-being-undone&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A series of incredibly dumb events was about to unfold—events beyond Samuel&#39;s and Jules&#39; control, yet destined to reshape their lives. For the worse.&lt;/p&gt;
&lt;p&gt;First, the company&#39;s IPO was delayed. The markets were spooked, and leadership decided to hold off. Understandable—markets were known for their fickleness. That paled compared to what came next.&lt;/p&gt;
&lt;p&gt;Blitcoin cratered.&lt;/p&gt;
&lt;p&gt;Hard.&lt;/p&gt;
&lt;p&gt;The stock market crashed. Samuel had never touched cryptocurrency, thinking it immaterial to his life. But now? &lt;em&gt;Everyone&#39;s hands are in an empty cookie jar.&lt;/em&gt;&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Team,&lt;/p&gt;
&lt;p&gt;We regret to inform you that due to unforeseen developments, our IPO process has been indefinitely delayed. We know that many of you are deeply disappointed by this development. We share your frustrations as well.&lt;/p&gt;
&lt;p&gt;Over the next few weeks, we will be working to optimize liquidity for as many of our employees as possible through a tender round. We have had promising conversations with our investors, as well as with a prominent sovereign wealth fund in the Middle East. As soon as we have more news, we will share it with you all.&lt;/p&gt;
&lt;p&gt;Rest assured that no layoffs are planned.&lt;/p&gt;
&lt;p&gt;This news does not change our return-to-office policy, as part of our office rationalization strategy.&lt;/p&gt;
&lt;p&gt;In good spirits,&lt;br /&gt;
Bryce Peters&lt;br /&gt;
CEO, Caspoke&lt;/p&gt;
&lt;p&gt;— #announcements, Caspoke DSCLSRE&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Plans for Paris were shelved for good. Samuel figured the tender offer was a mirage.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Of course, the universe was conspiring against me&lt;/em&gt;, he thought. &lt;em&gt;and iff God exists, He seeks a joke at our expense.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;On the precipice of success, reality delivered its shove.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Samuel&#39;s manager, Kevin, scheduled an urgent one-on-one with him. His brain filled with chaos and fear.&lt;/p&gt;
&lt;p&gt;The call started, and to Samuel&#39;s surprise, the call was much warmer than expected.&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel, I know this is sudden, but let&#39;s start with the good news.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Okay.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Management has decided to reward you for your hard work.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;More work?&lt;/em&gt; &lt;em&gt;Worthless stock options?&lt;/em&gt; &lt;em&gt;No more office lunch?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;quot;Ok, what&#39;s the reward?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Well, first, some news that you might not like.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Don&#39;t sugar-coat it.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;You&#39;re getting an involuntary promotion. Effective immediately, you&#39;re the head for consumer product engineering. They chose you because you&#39;re great at untangling messes.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Ah, such a &#39;reward&#39;! I&#39;m &lt;em&gt;soooo&lt;/em&gt; flattered!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Exactly, you get two jobs for the price of one!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;So generous when most people would kill to have just one!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;In this economy? Certainly.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Anyway, was this &#39;promotion&#39; the only &#39;reward&#39; they were talking about?&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Jules&#39; stomach twisted as the invite showed up in his inbox. &amp;quot;Important News.&amp;quot; He knew what was coming.&lt;/p&gt;
&lt;p&gt;He was joined by 300 of his co-workers on the Velocity meeting. Bryce, Caspoke&#39;s CEO, started sharing his screen - not the usual company slides, but a dense dashboard of metrics: user engagement, retention cohorts, NPS scores.&lt;/p&gt;
&lt;p&gt;&amp;quot;The data tells a story,&amp;quot; Bryce began, his voice carrying an enthusiasm for data over people, &amp;quot;Our north star metrics have deviated from the mean. NPS is trending downwards in all cohorts, conversion rates have declined despite continued A/B testing, and returns have spiked to a critical level.&amp;quot;&lt;/p&gt;
&lt;p&gt;He switched to another dashboard. Red arrows everywhere.&lt;/p&gt;
&lt;p&gt;&amp;quot;We have had to optimize the company for the long haul. We ran the numbers. The most optimal strategy is a 20% reduction in our workforce, extending our runway whilst preserving operational capacity.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules texted Samuel. &amp;quot;Layoff.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Unfortunately, this is the end of your time here at Caspoke. To minimize security risk, your access to Caspoke systems will be revoked immediately. Two months severance, one month additional COBRA. We believe a single, standard severance package will help reduce our cash burn.&amp;quot;&lt;/p&gt;
&lt;p&gt;He switched to yet another dashboard, a projection of the company&#39;s recovery after the layoffs.&lt;/p&gt;
&lt;p&gt;&amp;quot;This is the only way forward.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules&#39; company laptop went dark.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;&lt;strong&gt;This VanillaBook is locked.&lt;/strong&gt;&lt;br /&gt;
To unlock this computer, please contact your system administrator.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;quot;No, but it&#39;s the most certain thing you&#39;re getting.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Damn, I was &lt;em&gt;so close&lt;/em&gt; to being a millionaire.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel&#39;s phone buzzed. It was a message from Jules. He said he&#39;d been laid off.&lt;/p&gt;
&lt;p&gt;Kevin continued as if nothing had happened, &amp;quot;I used to say that when I was younger and dumber. Now I know better.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel checked DSCLSRE. Jules&#39; account had been deactivated. &lt;em&gt;Oh dear&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;&amp;quot;Uhh, I just heard Jules got laid off?&amp;quot;&lt;/p&gt;
&lt;p&gt;Kevin paused. &amp;quot;Oh, shit.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;on-the-precipice-of-being-ruined&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Being Ruined &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-being-ruined&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&amp;quot;Why didn&#39;t I hear of this earlier?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;You don&#39;t stare at dashboards all day?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I have work to do!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Hey, Bryce treats his models like they&#39;re his kids!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;What are we, a data visualization company?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Actually, someone hacked our device to run Doom. Runs better than our software.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Brutally honest. Coffee?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Thanks... rent&#39;s becoming a problem for me, though. Eight weeks severance is nothing.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Wish I could do more. Do you want to grab a coffee?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;d appreciate that.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;What time?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;3 o&#39;clock?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Meet me at Elena&#39;s Coffee.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Can do.&amp;quot;&lt;/p&gt;
&lt;p&gt;Elena&#39;s was a small, cozy coffee shop not far from the Caspoke office. The thought of $9 lattes was foreign to Jules, and yet it was bustling, even in this economy. Samuel ordered a latte, Jules chose a drip coffee. Jules declined Samuel&#39;s offer to pay.&lt;/p&gt;
&lt;p&gt;&amp;quot;Time for the MacDonough&#39;s coffee life,&amp;quot; Samuel said, pulling out his metal credit card.&lt;/p&gt;
&lt;p&gt;Jules thought of his battered coffee maker he’d snagged off Denisetable and his giant bag of pre-ground Boldrin&#39;s.&lt;/p&gt;
&lt;p&gt;&amp;quot;Liked the coffee machine at work... well, &lt;em&gt;used to&lt;/em&gt;.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;That thing brews despair.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Guess I&#39;ve got different standards.&amp;quot; &lt;em&gt;He&#39;s never suffered a day in his life.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&amp;quot;Wish I could help you more.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;You’re simply not in my shoes.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;When I was a teenager, my family was on the brink of homelessness—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I have to pick between rent or my student loans!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Jules, I didn&#39;t mean—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I graduated from Michigan! You went to some state school in Georgia!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;The layoff didn’t discriminate by alma mater—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Now I have to ask whether I&#39;m paying my student loans or my rent!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I got lucky. I know.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;Wish&lt;/em&gt; I had your luck.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;The universe can be a cruel mistress—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Like you&#39;re being right now!&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules stormed out of the cafe. Guilt sat with Samuel with the bridge ablaze.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Jules hunched over his laptop. Not the company-provided VanillaBook he had to return, but a laptop he bought back in college. The poor thing wheezed as the machine used every ounce of its power trying to bring up his budgeting spreadsheet. Once it opened up, Jules could finally start taking stock of his situation.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Okay, rent is $2,000 per month. Student loan payment, $1,300 per month. $500 per month for groceries. $100 per month for entertainment. Utilities are $200 per month. Internet is $70 per month, cell service is $35 per month, thank goodness for bargain-basement plans. Health expenses, around $100 per month. Transportation, $100 per month.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Every keystroke lagged the computer, it too reflecting upon his grim reality. No more entertainment. $200 per month for rice and beans and trips to the food bank.&lt;/p&gt;
&lt;p&gt;He had five months of runway after the severance package and tapping his savings. Deferring student loan payments bought two more. After that? Beg his ex to take him in, or live with his parents in Florida. He hoped the job market would improve before he arrived at Morton&#39;s fork.&lt;/p&gt;
&lt;p&gt;Samuel&#39;s aloofness weighed heavily on Jules as he made his calculations. Samuel was annoyed about skipping $9 lattes, while Jules was living precariously.&lt;/p&gt;
&lt;p&gt;He finished the edits to his budget, closed the laptop, and cried in his bed. Today was a gut punch. Tomorrow, the countdown begins.&lt;/p&gt;
&lt;h2 id=&quot;on-the-precipice-of-being-lost&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Being Lost &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-being-lost&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Samuel walked out of the office. Winter had melted into spring, but the blossoms on the trees did little to lift his spirits. As he strolled down Broadway toward Union Square, his exchange with Jules replayed in his head on an endless loop. Each repetition tightened the knot in his chest. Jules&#39; biting remark about Samuel attending &amp;quot;some random state school in Georgia&amp;quot; echoed louder each time. Samuel had fought hard for every inch of progress. Georgia Southern wasn’t Michigan, but it had been his stepping stone. Rejection from Georgia Tech had been a wake-up call, but Georgia Southern gave him a second chance. He took it and thrived. Yet, Jules’ words reduced his effort to nothing.&lt;/p&gt;
&lt;p&gt;Samuel’s pace quickened as if he could outrun the thoughts, but the hurt lingered as he descended into the labyrinth beneath Union Square. As he searched for the L train, Samuel&#39;s thoughts turned to yesterday. Had Jules known that he had almost come to the precipice of being homeless? That his family had almost lost everything? That without the government&#39;s meager assistance, they would have been on the streets? It was so visceral, so real! Yet Jules looked at where Samuel was &lt;em&gt;now&lt;/em&gt;, and considered himself to be the one who had it rough.&lt;/p&gt;
&lt;p&gt;Samuel didn&#39;t have to wait long for the train. He boarded the train and took a seat by the window. The train was crowded, but Samuel was lost in his thoughts. The harsh, fluorescent lights of the subway beamed down on him, casting a harsh light on his face. He stared at his phone, longing for something, but uncertain of what he was looking for. The train rumbled on after First Avenue, dipping under the East River.&lt;/p&gt;
&lt;p&gt;As the train sped under the river, Samuel finally lost it all. He began to cry uncontrollably, dark thoughts entering his mind. &lt;em&gt;I&#39;m a failure. I&#39;m an overprivileged tech bro and I know it.&lt;/em&gt; He was consoled by a stranger, who offered him a tissue. He wiped his face with it.&lt;/p&gt;
&lt;p&gt;&amp;quot;I appreciate it. But I had such a difficult conversation with someone I had to lay off...&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;It&#39;s going be OK.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;&lt;em&gt;I can&#39;t&lt;/em&gt;! I can&#39;t connect on a human level!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Relax. We all make mistakes.&amp;quot;&lt;/p&gt;
&lt;p&gt;The anger in Jules&#39; voice played again, and Samuel cried yet again.&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m sorry... I&#39;m just so lost.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;We all have moments like this. Listen... what&#39;s your name?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Mike. I&#39;m not sure what you&#39;re going through, but I&#39;d like to help you out as much as I can.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel wiped his eyes. &amp;quot;I appreciate it, Mike. I&#39;m just... who are you? Can you help me?&amp;quot;&lt;/p&gt;
&lt;p&gt;The train now prepared to ascend into Brooklyn.&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m a philosophy professor at Columbia. We seek to have the world make sense.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Making sense of the world? How?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;There&#39;s always meaning. You just have to find it.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I don&#39;t know if I can do it.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Philosophy is for everyone. We have non-traditional student programs, too.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I appreciate it, Mike. I&#39;ll think about it.&amp;quot;&lt;/p&gt;
&lt;p&gt;Mike left a card with his office hours and contact information. &amp;quot;See me whenever you feel like you&#39;re ready. Until then—&amp;quot;&lt;/p&gt;
&lt;p&gt;The train&#39;s automated announcement system interrupted the moment. &amp;quot;This is Bedford Avenue.&amp;quot; A different voice continued, proudly exclaiming that the station was accessible by those with disabilities and where the elevator was located.&lt;/p&gt;
&lt;p&gt;He had many more stops to go before he could get home. That meant plenty of time to dwell, in a city where dwelling was a luxury few could afford.&lt;/p&gt;
&lt;p&gt;Samuel walked back to his apartment after getting off at his stop. This had been the heaviest day of his life. Samuel rubbed salt in the wound of someone who&#39;d just been laid off.&lt;/p&gt;
&lt;p&gt;His bed awaited him. He embraced it, with tears in his eyes. Jules left his cell phone number on the company DSCLSRE. Samuel saved it. He would try to text Jules when he was in a better state of mind, try to make amends.&lt;/p&gt;
&lt;p&gt;He fell asleep, his mind still racing.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Jules gasped for air as he woke up from the worst nightmare he&#39;d ever had.&lt;/p&gt;
&lt;p&gt;His ex demanded he move out immediately—worse, his apartment hunt was turning up nothing, and he hadn&#39;t found a job in six months. He was running on fumes and out of friends willing to let him couchsurf, so he bought a flight back home departing the following week. As he was making his way to Newark Airport on a nearly empty commuter train, a mentally ill man was saying that the planes were being manipulated by a shadowy force that he couldn&#39;t quite coherently identify. Midway through the flight to Florida, the plane suffered from a malfunction, crashing onto land somewhere in coastal North Carolina. Now here he was, the only survivor, and there was no calvary coming to the rescue. Fear struck deep into his heart, knowing that this was the end.&lt;/p&gt;
&lt;p&gt;Before he could finish filling in his fate, he woke up from his slumber. It was 5 AM. At this moment, he would probably be brushing his teeth, getting dressed, and preparing breakfast. Well, he still had eggs and bacon in the refrigerator, the one that always seemed to be on its last legs. He feared the day that a power outage would finally send the refrigerator to its fate—discarded like his ambitions.&lt;/p&gt;
&lt;p&gt;He turned on the stove. &lt;em&gt;Oh good, I remembered to pay the gas bill.&lt;/em&gt; He cracked the eggs, scrambled them, and let them cook. Next was the bacon, the smell deeply pleasing to Jules as it sizzled. Once it was ready, he decanted the grease for later disposal.&lt;/p&gt;
&lt;p&gt;Today, he was eating like a king. Tomorrow? Who knew.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Open to work&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Now, who wants to hire him?&lt;/p&gt;
&lt;p&gt;The poor laptop screamed as it was called upon to open his resume. Each keystroke caused the computer to pause, contemplating Jules&#39; next move.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;&lt;strong&gt;Caspoke&lt;/strong&gt;, May 2022 - April 2023&lt;br /&gt;
&lt;em&gt;Software Engineer&lt;/em&gt;&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Contributed substantially to a project to improve the efficiency of the data pipeline for Caspoke&#39;s consumer products.&lt;/li&gt;
&lt;li&gt;Rewrote a service responsible for ingesting data from IoT devices to support higher throughput, reducing cloud costs by 24%.&lt;/li&gt;
&lt;li&gt;Identified and resolved customer issues that were escalated to engineers.&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jules knew that these accomplishments meant little aside from showing he was potentially qualified. He couldn&#39;t show his work off or articulate what kind of societal value it had, aside from it trickling down into a bonus—oh, wait, they cancelled bonuses for the 2022 review cycle! What dumb luck!&lt;/p&gt;
&lt;p&gt;&lt;em&gt;The universe can be a cruel mistress&lt;/em&gt;. Samuel&#39;s words stung.&lt;/p&gt;
&lt;p&gt;His machine crashed with a blue screen of death. Jules rebooted the computer, to no avail—the operating system didn&#39;t come back to life. &lt;em&gt;Now I&#39;m really up shit creek without a paddle&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;He chose to buy a new computer, since he had been meaning to do so anyway. Not being able to recover the old computer wouldn&#39;t be catastrophic, since he kept a copy of his resume and budgeting spreadsheet in the cloud, along with using a password manager.&lt;/p&gt;
&lt;p&gt;As he navigated the maze sitting below Barclays Center, a homeless person came up to him and asked him for a dollar. Avoiding them, Jules continued to exit the complex and walked to his destination, a gleaming glass-encased monument to tech, the Orchid Store in Downtown Brooklyn. If he hoped to get a job anywhere, nevermind the rough and tumble tech industry, he&#39;d need to look the part.&lt;/p&gt;
&lt;p&gt;The store had a flatiron shape. Jules thought the exterior reminded him of a stapler. A brightly-lit representation of an orchid flower in bloom was prominently centered between the top of the door and the roof. The glass made the store&#39;s layout apparent: clean, warmly lit, and neatly organized into a grid of tables with Orchid&#39;s latest and greatest devices on display.&lt;/p&gt;
&lt;p&gt;He went inside. A beautiful, calming floral note wafted in the air while quiet, smooth muzak played in the background. The enormity of the store outside vastly diminished inside. His eyes were drawn to Orchid&#39;s most affordable laptop, the VanillaBook Bud, but also its upscale line for the aspirational, the VanillaBook Bloom. As he was looking, a &amp;quot;specialist&amp;quot; walked up to him and asked how he could help.&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m looking for a new computer,&amp;quot; Jules meekly replied, &amp;quot;I&#39;m a software engineer.&amp;quot;&lt;/p&gt;
&lt;p&gt;The specialist was chipper. &amp;quot;The base VanillaBook Bloom has a 8-core CPU as a minimum. How old is your current laptop?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;It&#39;s from 2016.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;The P1 Turbo chip will be perfect for—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I just need a computer!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Let me check what we have in stock... how about a 15-inch Bloom with 12 cores, 48GB memory, and 2TB SSD?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m on a budget.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;We also have a 15-inch Bloom with 10 cores, 32GB memory, and 1TB of storage.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Close enough.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;That&#39;s $2,399.00. With tax, $2,612.51.&amp;quot;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;That&#39;s two and a quarter months of rent. Or one month of runway.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Jules was resigned to his fate. He pulled out his black-matte metal credit card, a relic of better times, and paid for the laptop. To his relief, the transaction was approved. The specialist handed him the laptop.&lt;/p&gt;
&lt;p&gt;&amp;quot;Here you go! Do you have any questions or need any more help?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m good.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules went back to his apartment and unboxed the computer. The Orchid experience continued with its clean, minimalist packaging. The wrapper protecting the computer had a subtle yet beautiful vanilla scent. He took the laptop out of its protective wrapper and opened the lid. A reassuring chime played and the orchid flower bud lit up the display, as the new electronic and vanilla smells became one ornate ensemble. As the computer progressed through its boot-up sequence, the beautiful bud blossomed into a brilliant bloom.&lt;/p&gt;
&lt;p&gt;For just a moment, Jules could forget about his credit card statement and the mold.&lt;/p&gt;
&lt;h2 id=&quot;on-the-precipice-of-being-un-hired&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Being (Un)hired &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-being-un-hired&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Samuel found himself in a conference room across from Kevin, the head of engineering, the CTO, and Bryce, the CEO. The monitor displayed an endless loop of the company logo, the cheerful animation now a relic from a more optimistic era.&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel,&amp;quot; Bryce began, &amp;quot;As you know, our products resonate with millions of people, through the power of the internet of things. The data doesn&#39;t lie—you&#39;re our most important individual contributor, and ought to be compensated accordingly.&amp;quot;&lt;/p&gt;
&lt;p&gt;Kevin shot Samuel a sympathetic look. &amp;quot;Let&#39;s talk numbers.&amp;quot;&lt;/p&gt;
&lt;p&gt;The CTO leaned forward. &amp;quot;We&#39;ve proposed a substantial equity package that reflects our confidence in—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Equity?&amp;quot; Samuel cut in. &amp;quot;Who in their right mind wants to cut us a check? Our latest launch was a disaster!&amp;quot;&lt;/p&gt;
&lt;p&gt;Before Samuel could speak, Bryce cut in. &amp;quot;But do you know about the expected value—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Expected value? It&#39;s zero, because &lt;em&gt;our products don&#39;t fucking work!&lt;/em&gt;&amp;quot; Samuel exclaimed.&lt;/p&gt;
&lt;p&gt;Bryce ignored Samuel, continuing, &amp;quot;of your time here? You don&#39;t even know about all the future—&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel stood up, &amp;quot;I quit!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Please listen to me—&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Bryce,&amp;quot; the CTO cut in sharply, &amp;quot;Can you build out that TPS reporting model you&#39;ve been talking about?&amp;quot;&lt;/p&gt;
&lt;p&gt;Kevin nodded emphatically. After a moment of confused silence, Bryce left.&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel, please sit down. We can now discuss this properly,&amp;quot; Kevin said.&lt;/p&gt;
&lt;p&gt;Samuel sat down and took a deep breath. The CTO cleared his throat. &amp;quot;We can explore a cash bonus as well, though I want to emphasize our belief in the company&#39;s long-term—&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel interrupted him. &amp;quot;I&#39;m fighting a war with one arm tied behind my back. Half my team is gone. I&#39;ve been spending nights and weekends executing a turnaround of the consumer division. You &lt;em&gt;must&lt;/em&gt; appropriately compensate me.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel&#39;s right,&amp;quot; Kevin interjected, earning a sharp look from the CTO. &amp;quot;We&#39;ve asked him to take on an enormous, thankless responsibility. The consumer division needs a complete overhaul.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;What number did you have in mind?&amp;quot; the CTO said.&lt;/p&gt;
&lt;p&gt;Samuel stated his figure. The CTO visibly winced.&lt;/p&gt;
&lt;p&gt;&amp;quot;We&#39;ll need to discuss this internally,&amp;quot; the CTO said.&lt;/p&gt;
&lt;p&gt;&amp;quot;My best and &lt;em&gt;only&lt;/em&gt; offer,&amp;quot; Samuel said. Kevin gave him a subtle nod of approval.&lt;/p&gt;
&lt;p&gt;A short moment of silence. &amp;quot;We&#39;ll get back to you,&amp;quot; the CTO said.&lt;/p&gt;
&lt;p&gt;Samuel stood up. &amp;quot;Thank you. I expect an answer in the next two weeks.&amp;quot;&lt;/p&gt;
&lt;p&gt;As Samuel walked out of the conference room, he knew this was a gutsy move that was likely to backfire. Gone was the man from rural Georgia happy that he had a big boy tech job at all, uncritically swallowing all the promises and lies. Now this Samuel was much harsher in the wake of his broken dreams, politeness be damned. Either he would get what he asked for—in cash, not equity—or he would walk away from the company that had once been his dream job. The monitor&#39;s looping company logo caught his eye one last time as he closed the door, its cheerful animation now seeming more like a tombstone for his former self than a symbol of future prosperity.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;If there was one thing the VanillaBook Bloom was good at, it was being &lt;em&gt;fast&lt;/em&gt;. Jules didn&#39;t need all the power he had on tap, but it didn&#39;t matter as long as he could pursue Graphdegree connections, read reviews on Woodknock, tap Oblivious for tips and referrals, and join Velocity calls with hot startups backed by ZZCombinator. It didn&#39;t hurt that the webcam was better compared to his old computer, although that meant he&#39;d position himself towards the door instead of the moldy walls. More dignified than taking calls at the coffee shop.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;&lt;strong&gt;Seeking Referrals!&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was affected by the recent layoff at Caspoke. Can someone please refer me for a position at Facegrind, Hell Gate Trading, or Wedge? Thank you so much!&lt;/p&gt;
&lt;p&gt;TC: 🥜 (was $334k)&lt;br /&gt;
YOE: 3&lt;/p&gt;
&lt;p&gt;— verne1997 (ex-Caspoke), Oblivious &amp;quot;Jobs and Referrals&amp;quot; section&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;There were some helpful leads posted in the thread. Not many of them worked out in the end.&lt;/p&gt;
&lt;p&gt;He continued to apply everywhere.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Thank you for your interest in DSCLSRE. While your experience is a strong fit, we have moved forward with another candidate whose alignment with our core values better reflects our dynamic culture of transparency and innovation. Please check our careers page for future opportunities that match your passion for disclosure.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Jules, I wanted to thank you for your time interviewing with our team. Unfortunately, you will not be moving forward with the process at LongChain. We wish you the best of luck in your future opportunities.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Our team has reviewed your job application for the Senior Software Engineer (Trade Execution) position. Unfortunately, we have decided to move forward with other, more promising candidates. We cannot provide any feedback on your application. Thank you for considering Hell Gate Trading!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Hi Jules—thanks for applying, great resume. Currently we&#39;re looking for a head of engineering, I&#39;ll let you know when we&#39;ve found them!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Some companies ghosted him after promising interviews. Others wasted his time with endless interviews.&lt;/p&gt;
&lt;p&gt;The due date on his credit card statement grew closer, like a bomb&#39;s fuse slowly burning away, ready to ignite with interest.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Jules, we&#39;re pleased to extend you an offer as a Senior Software Engineer at BlockKit!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The salary was lower than what Caspoke paid him, but a pay cut trumps unemployment. He fired off an email to the recruiter, saying he&#39;d accept the offer.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Hi Jules, thanks for your response. Unfortunately, due to market conditions, we will need to rescind your offer...&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jules was dejected. The only things that kept him going were spite and the prospect of being forced back to Florida, networking at a sad &amp;quot;Tech Professionals of Central Florida&amp;quot; event over stale Publix sweet tea, begging his parents to take him out to Waffle House instead of going back to rice and beans, and maybe having to settle for taking contract work on legacy applications built upon equally legacy tech stacks.&lt;/p&gt;
&lt;p&gt;Then, finally, a breakthrough.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;Hi Jules, do you have some time for a call today?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Jules&#39; heart jumped. &lt;em&gt;Was he going to be rejected again?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;At five o&#39;clock, his phone buzzed.&lt;/p&gt;
&lt;p&gt;&amp;quot;Hi, is this Jules?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Yes. Is this Sylvia with Wedge?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Yes, it&#39;s Sylvia. We have excellent news to share with you.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules relaxed a bit.&lt;/p&gt;
&lt;p&gt;&amp;quot;We are pleased to extend you an offer as a Software Engineer.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules cried. &lt;em&gt;Finally? Only a day before the credit card statement became due?!?&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Sylvia chimed in, &amp;quot;Are you OK, Jules?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Yes. I&#39;ve been searching for so long.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;It&#39;s been a tough market, that&#39;s what I&#39;ve been hearing from candidates. We have no shortage of applications for the limited number of positions we do have.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Thanks, Sylvia. So what&#39;s the offer?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;$150,000 base. Substantial equity. I&#39;ll send you a copy of our benefits guide. Plus, a product that works.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;You&#39;ve heard about Caspoke?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Their smart remote makes a great e-book reader.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules chuckled. &lt;em&gt;I guess those metrics made a twisted amount of sense.&lt;/em&gt; &amp;quot;It sure does have a great use case!&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Better for reading Agatha Christie novels than turning on the lights. Still, a solid use case!&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;The next two months were a blur. Samuel held an all-hands to introduce himself to the team. Then came the real challenge—discovering all the skeletons in the closet.&lt;/p&gt;
&lt;p&gt;Samuel formulated a plan to turn things around. For the first time in months, the team felt like they had direction. They axed half-baked features in favor of prioritizing the core customer experience. A tactical team of engineers was laser-focused on shrinking cloud spend. A skunkworks team was hard at work reworking essential components that barely functioned. Engineers ran on pizza, soda, and a medically unadvisable amount of caffeine.&lt;/p&gt;
&lt;p&gt;The product performance indicators started trending positive: cloud cost basis down 10.2%, NPS delta +3 points week-over-week, and latency metrics improved 15% after a key service was rewritten by Samuel&#39;s skunkworks team. Bryce proudly shared these dashboards in the all-hands, but the whispers grew louder—someone was gathering data points for his inevitable exit.&lt;/p&gt;
&lt;p&gt;But now the day of reckoning came. The CTO called him back into the conference room. The company logo still played on the monitor, but the mood was different. The CTO&#39;s mood were more subdued, more respectful. They had made their decision. Samuel sat down, his heart pounding.&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel,&amp;quot; the CTO began, &amp;quot;we&#39;ve decided to approve your bonus.&amp;quot;&lt;/p&gt;
&lt;p&gt;A bit of the old, snarky Samuel returned. &amp;quot;Oh, that&#39;s good. Just wanted to make sure you knew my value.&amp;quot;&lt;/p&gt;
&lt;p&gt;The CTO chuckled. &amp;quot;We&#39;re going to wire it directly to your bank account.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel raised an eyebrow. &amp;quot;That&#39;ll make dealing with the taxman harder, but I&#39;ll take it.&amp;quot;&lt;/p&gt;
&lt;p&gt;The CTO smiled. &amp;quot;One more change. After today, you will now report to Kevin, who will be our new interim CTO.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel shook hands with the CTO, &amp;quot;Glad I could help. Best of luck on your future endeavors.&amp;quot;&lt;/p&gt;
&lt;p&gt;With that, the CTO left with nothing more to say. Samuel had stood up for himself and he&#39;d won. The next day, as promised, a wire transfer hit his bank account. With that, his bank account was now north of $100,000.&lt;/p&gt;
&lt;p&gt;But Samuel didn&#39;t care about the cash. He cared about the principle: did leadership treat him as the valuable employee they claimed he was? He made a, well, somewhat unreasonable demand, and they caved.&lt;/p&gt;
&lt;p&gt;He had won. But victory tasted like MacDonough&#39;s coffee.&lt;/p&gt;
&lt;h2 id=&quot;on-the-precipice-of-security&quot; tabindex=&quot;-1&quot;&gt;On the Precipice of Security &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/precipices/#on-the-precipice-of-security&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Looking at his bank account that evening, Samuel couldn&#39;t feel the rush he&#39;d expected. The six figures staring back at him from his phone screen felt less like victory and more like combat pay.&lt;/p&gt;
&lt;p&gt;Jules&#39;s desk was empty, and it stayed that way for months. The desk still bore the signs that it had been once his - a faded spot where a photo frame had blocked the sun, and an unplugged monitor cable dangling towards the floor. Every morning, the empty desk reminded Samuel of his &amp;quot;win.&amp;quot;&lt;/p&gt;
&lt;p&gt;He still went to that same French bakery, ordered the same quiche and danish, watched the same elevated train rumble overhead. But something had shifted. The comfort these rituals once provided had hollowed out. His coffee, despite its perfect roast and precise preparation, tasted bitter.&lt;/p&gt;
&lt;p&gt;Samuel stared at his metal credit card, heavy in his pocket. He had the means to go to Paris. But the money felt like a fortress he had to maintain, knowing his own position was more precarious than ever. The equity that was supposed to make him a millionaire still sat there, digital numbers in a digital account, worth less than the electricity used to display them.&lt;/p&gt;
&lt;p&gt;Bryce was now gone. Officially, he was leaving to &amp;quot;pursue other projects,&amp;quot; but everyone knew the truth—an investor who poured $120 million of fresh capital into Caspoke had insisted on Bryce’s departure, sweetened by a golden parachute. Was it that mythical Middle Eastern sovereign wealth fund? For all Samuel knew, this investor would&#39;ve done better incinerating the money.&lt;/p&gt;
&lt;p&gt;The CTO didn’t last much longer. His handling of Caspoke’s latest botched launch and ballooning cloud bills sealed his fate. In his place came Kevin, first as interim CTO, and later the permanent CTO, with Samuel reporting directly to him.&lt;/p&gt;
&lt;p&gt;Changes were swift. Instead of swooning over dashboards, data was now balanced with customer feedback. The return-to-office policy was scrapped. A large group of underperforming employees, whom Bryce believed could become effective employees with additional training and mentoring—a program that was bleeding cash and ineffective—were laid off, in a dignified fashion. Finally, to much employee delight, the office lunch program, based on a complex employee engagement and performance model that was hard to understand but easy to game, was replaced by a straightforward daily stipend.&lt;/p&gt;
&lt;p&gt;Samuel had always been the company’s go-to fixer. His turnaround of the consumer product had saved the company—at least for now. But Samuel felt no relief. If anything, he was standing on a different kind of precipice—personal, emotional, existential. Materially, things were better than ever. Inside, he was unraveling. The sleepless nights, the constant high-stakes decisions—each one chipped away at him, until he finally broke.&lt;/p&gt;
&lt;p&gt;He looked up Mike on Columbia&#39;s website, found his office hours, and decided to pay him a visit. A long journey to the campus on the 1 train followed.&lt;/p&gt;
&lt;p&gt;Mike&#39;s office was small, but cozy, with a bookshelf filled with old, dusty tomes. Mike looked up from his desk, a smile on his face.&lt;/p&gt;
&lt;p&gt;&amp;quot;Do you remember me?&amp;quot; Samuel asked.&lt;/p&gt;
&lt;p&gt;Mike squinted. &amp;quot;I&#39;m sorry, I see a lot of students. Can you remind me?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m Samuel. We met on the L train a few months ago. You offered me a tissue. Told me about philosophy.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Ah, Samuel! I remember now. How have you been?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Been better. Been worse.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;What&#39;s going on?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m still that same person. Richer, but still broken. I&#39;ve won, at an enormous cost. Therapy isn&#39;t helping.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Meaningless suffering is a curse. Meaningful suffering is a choice. That&#39;s what philosophy explores.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m done with tech. I&#39;m ready to explore.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;ll get you in touch with the right people in admissions.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Thank you, Mike. I appreciate it.&amp;quot;&lt;/p&gt;
&lt;p&gt;Returning now to the office, Samuel drafted an email to his boss. &amp;quot;Kevin, I&#39;ve decided to enroll in Columbia&#39;s philosophy program. I&#39;ve been feeling lost, and I think this is the right path for me. I am requesting a leave of absence for the next year to focus on the program full-time, and if this is not possible, I will have to resign. I hope you understand.&amp;quot;&lt;/p&gt;
&lt;p&gt;He hit send, and felt a weight lift off his shoulders. He was still on the precipice, but now he was moving forward. He was still lost, but now he was searching for answers.&lt;/p&gt;
&lt;p&gt;This led to a three-way conference between him, Jeff, the new CEO, and Kevin, his manager and the CTO.&lt;/p&gt;
&lt;p&gt;&amp;quot;Samuel, we understand your decision,&amp;quot; Jeff said. &amp;quot;But we don&#39;t want you to leave.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I&#39;m sorry, Jeff,&amp;quot; Samuel said. &amp;quot;I need the space.&amp;quot;&lt;/p&gt;
&lt;p&gt;Kevin spoke up. &amp;quot;We can offer you a sabbatical. You can take a year off, and we&#39;ll hold your position for you.&amp;quot;&lt;/p&gt;
&lt;p&gt;Samuel considered the offer. &amp;quot;I appreciate it. I&#39;ll take it.&amp;quot;&lt;/p&gt;
&lt;p&gt;Kevin nodded. &amp;quot;We&#39;ll get the paperwork started. We&#39;ll miss you, Samuel.&amp;quot;&lt;/p&gt;
&lt;p&gt;With that, Samuel spent a few weeks preparing for his sabbatical. He wasn&#39;t going to be paid during his leave, but he had enough to live in New York for two years without any income. He had enough to pay his rent, to buy food, to live comfortably. He had enough to find himself.&lt;/p&gt;
&lt;p&gt;He walked out of the office, the weight of the world off his shoulders. He was on the precipice of moving forward.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;&amp;quot;Jules? Mind if I sit down?&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules looked up from his coffee and his VanillaBook Bloom. They were at a small coffee shop close to Washington Square Park. &amp;quot;Samuel! Of course, sit down. Coffee&#39;s on me, if you want.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Hope the new gig is treating you well. I&#39;ll pay for my own coffee.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;It&#39;s great. Commute hits different since it&#39;s downtown.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Moved out of the basement?&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Indeed! I&#39;m in Long Island City now. Have a new girlfriend too.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Excellent! I&#39;m on sabbatical, beginning my philosophy study at Columbia. I had to find myself.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;Good to hear. I hope you find what you&#39;re looking for.&amp;quot;&lt;/p&gt;
&lt;p&gt;&amp;quot;I had everything I wanted, besides myself.&amp;quot;&lt;/p&gt;
&lt;p&gt;Jules nodded as he pointed at his laptop. &amp;quot;Materialism can only take you so far,&amp;quot; he said with a knowing smile, as to remind Samuel that he was the catalyst for Jules&#39; unplanned purchase.&lt;/p&gt;
&lt;p&gt;Jules never stood at the precipice of being a millionaire. Yet, he was ruined, lost, and gambled it all. Now he was at the precipice of material security.&lt;/p&gt;
&lt;p&gt;Samuel was no longer at the precipice of being a millionaire. He&#39;d been ruined, he&#39;d been lost, he too gambled it all. Now he was now at the precipice of security in self-actualization.&lt;/p&gt;
&lt;p&gt;Perhaps security is the most important precipice of all.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>🌀 Being nonlinear: A transition from modding</title>
		<link href="https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/"/>
		<updated>2025-01-06T00:00:00Z</updated>
		<id>https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/</id>
		<content type="html">&lt;p&gt;I&#39;ve written quite a bit about &lt;em&gt;Minecraft&lt;/em&gt; on this blog. For better or worse, it has defined a large chunk of my life. But there inevitably had to be a time where I&#39;d have to make the transition to a &amp;quot;real&amp;quot; job. Making this adjustment was painful but necessary.&lt;/p&gt;
&lt;div class=&quot;p-4 bg-rose-500 color-white lh-normal&quot;&gt;
  I&#39;m writing this blog post based on my experiences with &lt;em&gt;Minecraft&lt;/em&gt;, particularly its server modding scene, however I have taken great pains to make this applicable to any game. &lt;strong&gt;Your situation will be unique&lt;/strong&gt;, but I hope this post provides you with useful advice.
&lt;/div&gt;
&lt;p&gt;What I find in general is that modding can be excellent at providing a good foundation for your &amp;quot;hard skills&amp;quot; (the act of writing code and designing things), it does make it dangerously easy to not develop the &amp;quot;soft skills&amp;quot; that are so often needed in the workplace. I wish I&#39;d found a post like this before heading down the professional career path, and so I&#39;m immortalizing some of the hard lessons I had to learn.&lt;/p&gt;
&lt;h2 id=&quot;you-add-value&quot; tabindex=&quot;-1&quot;&gt;You add value! &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#you-add-value&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;As a mod developer, you&#39;re in a category of people known as &lt;em&gt;non-traditional candidates&lt;/em&gt;. This is a diverse category: career changers, parents returning to the workforce, and self-taught programmers. These people all bring their own unique talents and perspectives to the table.&lt;/p&gt;
&lt;p&gt;Specifically, what do you bring to the table?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;You can self-direct your work&lt;/strong&gt;. You can accomplish tasks without being prompted by others, and you have a bias towards action.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You have practical experience&lt;/strong&gt;. In some cases, you learned how to build software by yourself, showing that you are agile and can pick up new skills easily.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You are a creative problem-solver&lt;/strong&gt;. Mods can improve upon existing systems, or find creative ways to overcome game engine limitations.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You can interact with communities&lt;/strong&gt;. You have likely worked with other developers and supported your users in some way.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you choose the gaming industry, then you additionally bring:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;A deep understanding of the player experience&lt;/strong&gt;, because your mods build upon a base to add more depth, or correct perceived poor experiences.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Familiarity with game systems and mechanics&lt;/strong&gt;, especially if your mods add entirely &lt;em&gt;new&lt;/em&gt; game modes to an existing game.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Experience balancing technical constraints with user enjoyment&lt;/strong&gt;, because you&#39;ll find creative ways to work around limitations of game engines.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Simply put, your experience with modding need not be a liability. In recent years, more companies have begun to understand that diversity can strengthen teams. You are in a prime position to take advantage of this!&lt;/p&gt;
&lt;h2 id=&quot;where-do-you-want-to-work&quot; tabindex=&quot;-1&quot;&gt;Where do you want to work? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#where-do-you-want-to-work&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The most &amp;quot;natural&amp;quot; path to advance is to transition from modding to game development. After all, modding entails understanding a lot of industry-specific knowledge. You could easily take the experience you have and apply it to making your own games.&lt;/p&gt;
&lt;p&gt;The downside of this is that the gaming industry does not provide a good working environment:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Work-life balance is poor. &lt;a href=&quot;https://en.wikipedia.org/wiki/Crunch_(video_games)&quot;&gt;&amp;quot;Crunch&amp;quot;&lt;/a&gt; is a well-documented phenomenon, working additional hours beyond what a developer is paid for, often resulting in lower-quality work and health issues.&lt;/li&gt;
&lt;li&gt;The industry is unstable: layoffs and studio closures are common.&lt;/li&gt;
&lt;li&gt;Compensation is often lower. While just one data point (and only an approximation at most), Glassdoor cites a median salary of &lt;a href=&quot;https://www.glassdoor.com/Salaries/united-states-game-developer-salary-SRCH_IL.0,13_IN1_KO14,28.htm&quot;&gt;$106,000 for game developers&lt;/a&gt;, versus &lt;a href=&quot;https://www.glassdoor.com/Salaries/united-states-software-engineer-salary-SRCH_IL.0,13_IN1_KO14,31.htm&quot;&gt;$162,000 for software engineers&lt;/a&gt; in the United States. That&#39;s more than a 50% difference!&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another path that is available is to translate your experience to other fields outside of the gaming industry. This takes more time and preparation, since you&#39;ll likely need to develop a new set of skills to navigate that transition.&lt;/p&gt;
&lt;p&gt;I chose to transition into a non-gaming industry for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;I had a desire to understand how the &amp;quot;real world&amp;quot; works&lt;/strong&gt;. What&#39;s more real-world than software that other people depend on for their jobs? My work at Ramp touches not only the lives of accountants but also regular everyday people who need to travel for business.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I had previous experience with databases, networking, web development, and tackling scalability challenges&lt;/strong&gt;. At various points in my time in the &lt;em&gt;Minecraft&lt;/em&gt; scene, I handled some combination of all of the above, so a transition to working at a scaling startup made a lot of sense to me.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;have-a-solid-foundation&quot; tabindex=&quot;-1&quot;&gt;Have a solid foundation &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#have-a-solid-foundation&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is the only section I&#39;m going to devote to hard skills, because if you are an experienced modder, then you have a foundation to build off. The challenge is in developing skills that are industry-relevant and in demand. The good news is that the modding scene actually offers opportunities for this, if you know where to look.&lt;/p&gt;
&lt;p&gt;I&#39;ll take &lt;em&gt;Minecraft&lt;/em&gt; as an example. Disregarding &lt;em&gt;Bedrock Edition&lt;/em&gt;, the &lt;em&gt;Java Edition&lt;/em&gt; gives away a lot in the title: it&#39;s written in Java, and you are able to mod the game using Java (or, in fact, any JVM language you desire). As it turns out, Java is a rather common language used in actual software engineering jobs! You already have the fundamentals you need to learn, say, &lt;a href=&quot;https://spring.io/&quot;&gt;Spring Framework&lt;/a&gt; (a very common Java framework often used for web applications), so you may want to take some time to develop a web application using Spring. In addition, you can leverage this to learn web development using HTML, CSS, and JavaScript.&lt;/p&gt;
&lt;p&gt;Even if the modding language of choice isn&#39;t commonly listed on a job posting, it can still be applicable to learning another related language. For instance, if you understand Lua, then you already conceptually understand the core of JavaScript, as both languages are multi-paradigm and have prototypical object systems. Also, Lua has had some very large scale real-world applications - for many years, Cloudflare&#39;s HTTP reverse proxy logic was partially built with Lua!&lt;/p&gt;
&lt;p&gt;You can also work on projects related to the game of your choice in a language that is different from the one that the game is programmed in. At various points in my time in the Minecraft scene, I also made use of PHP (with Laravel), Python (with Django and Flask), Go, JavaScript/TypeScript, and even Rust. One network I worked on (Mineteria) was built on top of Kubernetes, so I also gained experience with that as well.&lt;/p&gt;
&lt;p&gt;Now, this comes with some obvious caveats:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Code standards that might fly for modding may not work in a professional setting&lt;/strong&gt;. Often, the priority in a game modding setting is just to &amp;quot;get the thing working&amp;quot;, which means that you will inevitably have code that is not clean or maintainable by others, or have poor documentation. These things will not fly in a professional setting. As Guido van Rossum, the creator of Python, would put it, &lt;a href=&quot;https://peps.python.org/pep-0008/#a-foolish-consistency-is-the-hobgoblin-of-little-minds&quot;&gt;&lt;em&gt;code is more often read than written&lt;/em&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Techniques useful for game development aren&#39;t broadly applicable to enterprise applications&lt;/strong&gt;. For instance, if you work in a garbage-collected language, then you have probably optimized your code to reduce the amount of garbage objects generated and value low pause times. Enterprise applications are often less sensitive to pause time and can afford to generate more garbage. Some of these techniques are even considered bad form in some contexts! The upshot is that in some applications that require low latency, such as high-frequency trading (where shaving off nanoseconds really matters), this can be a competitive advantage.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;You will necessarily have to get out of your comfort zone&lt;/strong&gt;. The types of applications you&#39;re going to work on in a professional context are different, so you will be best served by gaining experience outside of modding. That could be as simple as building a simple web-based tool to help simulate some key game mechanic.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;prepare-to-have-lowered-expectations&quot; tabindex=&quot;-1&quot;&gt;Prepare to have lowered expectations &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#prepare-to-have-lowered-expectations&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sadly, the median software engineer will be stuck at a large corporation focused primarily on internal CRUD (create-read-update-delete) applications that are obscure but also important enough to necessitate hiring someone to take care of it. This work may not be necessarily creative in nature. In some cases, you&#39;re doing this simply to &amp;quot;pay your dues&amp;quot; and set yourself up for greater things. Other employers may not offer a realistic path to advance.&lt;/p&gt;
&lt;p&gt;I can give you an actual example from my own life: from 2018 to 2021, I was working on Mineteria. During this time, I built key infrastructure for them (working across many different programming languages), and created my own &lt;em&gt;Minecraft&lt;/em&gt; server proxy, Velocity, which was later adopted by Mineteria and countless other &lt;em&gt;Minecraft&lt;/em&gt; servers. After leaving Mineteria behind and eventually landing at Ramp, the very first project I was assigned was &amp;quot;create a system to link a personal bank account&amp;quot; - quite the step down from &amp;quot;build out an efficient proxy that speaks the &lt;em&gt;Minecraft&lt;/em&gt; protocol&amp;quot;!&lt;/p&gt;
&lt;p&gt;The skills I got from my time were still helpful: thanks to previous work, I was familiar with Python, ORMs (although I had to make the transition from working with the Django ORM to SQLAlchemy), Celery (from a previous &lt;em&gt;Minecraft&lt;/em&gt; server list project I&#39;d worked on), and PostgreSQL (Ramp&#39;s backend database of choice).&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Much&lt;/em&gt; later on, having the skills needed to read a profile meant that when we had a particularly bad memory leak in one of our applications, I was able to pinpoint it and fix it easily. Over time, too, I established enough of a reputation and track record that I was entrusted to architect and execute upon much larger, more complex projects.&lt;/p&gt;
&lt;p&gt;So how can you still be happy while working a day job that might be less exciting? Well, you could still take up modding, but on a smaller scale. Even now, I still occasionally contribute to Velocity or update my existing &lt;em&gt;Minecraft&lt;/em&gt; mods for newer versions of the game. You could also take up new hobbies to get your creative energies flowing. For me, due to burnout and having less interest in &lt;em&gt;Minecraft&lt;/em&gt; in general, I found that redirecting my creative energies towards writing helped me a lot. If your employer has put you in a position where your job is effectively a dead-end with no realistic path to advance, then you should shake things up and find a new job that can make you happier!&lt;/p&gt;
&lt;h2 id=&quot;being-in-the-workplace&quot; tabindex=&quot;-1&quot;&gt;Being in the workplace &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#being-in-the-workplace&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Your company&#39;s internal chat is not going to be a Discord voice chat (if it is, I would probably run far away!)&lt;/p&gt;
&lt;p&gt;The top priority for anyone transitioning from a modding community to the workplace is to studiously separate your gaming life from your professional life. Gaming communities, particularly competitive ones, can foster toxic behavior that is almost normalized in that setting but would be unacceptable in a professional setting, where inclusivity, constructive feedback, and respect for diverse perspectives are a must.&lt;/p&gt;
&lt;p&gt;There are many, &lt;em&gt;many&lt;/em&gt; excellent online resources that can dive into way more detail about how to be effective in the workplace than this blog post could ever hope to accomplish. I will describe some broad categories of professional expectations below, how these could be treated in the context of a modding setting (potentially with an example with my own work), and provide resources for you to learn how to act professionally.&lt;/p&gt;
&lt;h3 id=&quot;project-management&quot; tabindex=&quot;-1&quot;&gt;Project management &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#project-management&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;You may or may not be practicing project management in your work, but it is essential in the workplace, not just to keep yourself organized and make sure you can advance a project, but also to provide a bird&#39;s eye view of the status of a project to other stakeholders, outside of updates you provide in writing or by hand.&lt;/p&gt;
&lt;p&gt;There are a number of approaches on how to learn project management and apply them to modding. You could go all out and take a free course on how to do project management on a site like &lt;a href=&quot;https://www.coursera.org/collections/project-management-for-beginners&quot;&gt;Coursera&lt;/a&gt;, but often, having a working knowledge of Agile can be sufficient, as many companies utilize Agile methodologies. I won&#39;t go into detail about Agile, but consider understanding the &lt;a href=&quot;https://agilemanifesto.org/iso/en/principles.html&quot;&gt;Agile Manifesto&lt;/a&gt; and putting it into practice yourself. Users of your mods are customers!&lt;/p&gt;
&lt;p&gt;You can also leverage tools such as Trello or Notion to be more organized. These tools can help you:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Break down large features into smaller tasks&lt;/li&gt;
&lt;li&gt;Track bugs and feature requests&lt;/li&gt;
&lt;li&gt;Manage release schedules&lt;/li&gt;
&lt;li&gt;Document design decisions&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;These tools and techniques can make your modding work more efficient and also provide practical, hands-on experience with professional project management practices.&lt;/p&gt;
&lt;h3 id=&quot;professional-writing&quot; tabindex=&quot;-1&quot;&gt;Professional writing &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#professional-writing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Some people in the modding scene may write documentation, but it&#39;s often not of the highest quality. Being able to express your ideas with clarity and specificity is important in a professional context, even if you&#39;re not going to be a software engineer.&lt;/p&gt;
&lt;p&gt;I cannot hope to recreate existing guidance on professional writing, so I will instead refer you to &lt;a href=&quot;https://developers.google.com/tech-writing/overview&quot;&gt;Google&#39;s technical writing courses&lt;/a&gt; which comprehensively covers this topic. While it is geared towards software engineers and engineering-adjacent roles, there is useful advice in it for everyone. Once you have the foundation, you can begin by providing detailed documentation of how what your mods do and how they work.&lt;/p&gt;
&lt;p&gt;Many projects have poor documentation, and one especially low-hanging fruit way to contribute is to improve the documentation. If there&#39;s something that trips up newcomers and is difficult to explain, take the time to put yourself in a newbie&#39;s shoes and write a guide to help them navigate the troubled waters.&lt;/p&gt;
&lt;p&gt;From personal experience, improving my writing skills was one of the most important factors in allowing me to progress at Ramp. Previously, I had &lt;em&gt;never&lt;/em&gt; written down important things about my software, or ever committed software design down to paper. Having to learn this habit was tough, as prior to Ramp, I only did this during my college studies! Since then, I rediscovered my strong command of writing and embraced it.&lt;/p&gt;
&lt;h3 id=&quot;interacting-with-coworkers&quot; tabindex=&quot;-1&quot;&gt;Interacting with coworkers &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#interacting-with-coworkers&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Professional relationships require respect and courtesy. While gaming communities often have casual or playful communication styles, workplace interactions require more care. A good rule of thumb: if your 13-year-old cousin would take offense at what you&#39;re about to say, it&#39;s probably not appropriate for work. Focus on building positive relationships with coworkers through clear, respectful communication. Even when you disagree with others, it&#39;s important to handle those gracefully and work towards an acceptable resolution - perhaps one party in the conversation simply lacks context on why the decision makes sense, for instance.&lt;/p&gt;
&lt;p&gt;In addition, your coworkers may come from different backgrounds, and you should be sensitive and respectful of those differences. Those different backgrounds bring valuable perspectives to the table, and you&#39;ll be expected to work effectively with people of different backgrounds.&lt;/p&gt;
&lt;p&gt;From my personal experience, this isn&#39;t difficult to do, but your old habits could take some time to shake off. Take advantage of free resources on workplace etiquette and communication. Many universities and online platforms offer professional skills courses. Once I found my bearings, though, I found it easy to establish good rapport with my coworkers, enough to the point where I am something of a &amp;quot;minor celebrity&amp;quot; at Ramp!&lt;/p&gt;
&lt;h3 id=&quot;having-respect-for-workplace-norms&quot; tabindex=&quot;-1&quot;&gt;Having respect for workplace norms &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#having-respect-for-workplace-norms&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;In most gaming contexts, there is little etiquette expected. This is absolutely not the case when you are working somewhere else!&lt;/p&gt;
&lt;p&gt;Every workplace has its own culture and expectations. This includes:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Meeting etiquette (being on time, coming prepared, actively listening)&lt;/li&gt;
&lt;li&gt;Communication channels (when to use email vs chat vs scheduling a meeting)&lt;/li&gt;
&lt;li&gt;Work hours and availability expectations&lt;/li&gt;
&lt;li&gt;Dress code and office behavior standards&lt;/li&gt;
&lt;li&gt;Using professional language and tone&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The nice thing that you can practice doing at least some of these things while still being involved in the modding scene:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Run a structured community meeting, if applicable&lt;/li&gt;
&lt;li&gt;Set up &amp;quot;office hours&amp;quot; to talk with anyone who needs help&lt;/li&gt;
&lt;li&gt;Utilize professional communication tools such as GitHub or Slack instead of Discord&lt;/li&gt;
&lt;li&gt;Have a consistent schedule for updates and communication&lt;/li&gt;
&lt;li&gt;Writing professional documentation and release notes&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There are many free resources online that can help you understand these societal norms. Consider taking a professional skills course such as &lt;a href=&quot;https://www.coursera.org/courses?query=professional%20skills&quot;&gt;one on Coursera&lt;/a&gt; and researching typical professional dress codes.&lt;/p&gt;
&lt;h2 id=&quot;actually-getting-a-job&quot; tabindex=&quot;-1&quot;&gt;Actually getting a job &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#actually-getting-a-job&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;So far, everything that&#39;s been discussed so far has focused pn what you are expected to do in the workplace. But how do you actually get a job with a non-traditional background?&lt;/p&gt;
&lt;p&gt;I will skip over the essentials of how to apply for a job, as this topic has been done to death by many others. Instead, I want to focus specifically on how people of non-traditional backgrounds can begin the process.&lt;/p&gt;
&lt;p&gt;Generally speaking, you have three options:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Ignoring your modding experience, going to college, getting internships, and then a full-time job after graduating. This works best if you&#39;re young.&lt;/li&gt;
&lt;li&gt;Make connections with others who can vouch for your ability.&lt;/li&gt;
&lt;li&gt;Being lucky enough to find an employer that independently values your experience, or is willing to take a chance on you.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;I&#39;m not going to cover the first option, simply because this is a well-trodden path. Instead, I&#39;ll talk about 2 and offer some advice that can help for 3. This isn&#39;t going to be a full guide on how to find a job, perform well in an interview, and understanding offers and whether or not to accept them, as this topic has been done to death by many others.&lt;/p&gt;
&lt;h3 id=&quot;building-a-resume&quot; tabindex=&quot;-1&quot;&gt;Building a resume &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#building-a-resume&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;There are many resources on how to format a resume, so I won&#39;t belabor the point here. However, translating your modding experience to software engineering can be difficult: perhaps poor documentation and record-keeping, working with particularly niche frameworks and languages, and the fact that a life of modding video games is a significant divergence from a typical software engineer&#39;s resume which would typically include a number of internships or student jobs prior to obtaining their first initial junior-level position.&lt;/p&gt;
&lt;p&gt;Feel free to use &lt;a href=&quot;https://steinborn.me/about/resume.pdf&quot;&gt;my own resume&lt;/a&gt;, in particular my experiences with Tebex and Mineteria, as inspiration. Some key advice:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Try to generalize your experiences&lt;/strong&gt;. For instance, I took on a number of roles at Mineteria, but I mostly honed in on web development, experience with Java, and work with Kubernetes, as these are the skills &lt;em&gt;most&lt;/em&gt; relevant to opportunities outside of the modding scene. If you don&#39;t have any direct experience with something an employer wants, discuss analogous, equivalent experiences in language a typical employer would understand.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Focus on concrete accomplishments&lt;/strong&gt;. I developed a &lt;em&gt;Minecraft&lt;/em&gt; server proxy called Velocity. However, on a resume, instead of noting that I &amp;quot;developed a &lt;em&gt;Minecraft&lt;/em&gt; server proxy&amp;quot;, I would emphasize that I &amp;quot;built an extensible, high-performance reverse proxy capable of supporting X &lt;em&gt;Minecraft&lt;/em&gt; players at a time.&amp;quot; This highlights that Velocity is a proxy that just happens to speak the &lt;em&gt;Minecraft&lt;/em&gt; protocol, which is a precise high-level description of what Velocity is.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Emphasize the underlying accomplishments behind your work&lt;/strong&gt;. Did you fix a particularly bad performance issue in a game you like? Did you use a profiler to examine why it was so bad? Congratulations, you have the unique skill of being able to diagnose and fix performance problems in applications.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Be ready to explain your unusual background&lt;/strong&gt;. I was very upfront about my experience being primarily with &lt;em&gt;Minecraft&lt;/em&gt; when I interviewed at all my prospective employers! One employer even had someone on the call who quizzed me about certain things related to &lt;em&gt;Minecraft&lt;/em&gt; and I provided the best answers I could. They actually extended me an offer, but I declined because Ramp offered me more money.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;networking&quot; tabindex=&quot;-1&quot;&gt;Networking &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#networking&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Other developers you work with can be a valuable resource, especially if they are also going down this road. Some people who create mods may already have full-time jobs and can potentially serve as potential job leads by referring you. For instance, through working on a &lt;em&gt;Minecraft&lt;/em&gt; component library, I was acquainted with a modder who was also a product manager at Cloudflare, and he referred me for a position working on Cloudflare Workers! This person was willing to vouch for my abilities and show how they apply to a context outside of &lt;em&gt;Minecraft&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;You can also pursue more traditional means of networking. Find local user groups for a programming language or technology that interests you. Many people who work professionally have a presence on LinkedIn. Connect with them and get inquisitive about their work!&lt;/p&gt;
&lt;p&gt;Ultimately, your goal is to establish connections that help you now and in the future. This is all the more reason to be respectful of others and to embrace diversity.&lt;/p&gt;
&lt;h3 id=&quot;finding-employers-willing-to-take-a-bet-on-you&quot; tabindex=&quot;-1&quot;&gt;Finding employers willing to take a bet on you &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#finding-employers-willing-to-take-a-bet-on-you&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is &lt;em&gt;much&lt;/em&gt; harder, since you&#39;ll need to start from the very bottom. For most positions, this is equivalent to applying to a job where it&#39;s not obvious that you meet the requirements for the job. Therefore, you&#39;ll need to start by looking at employers who may be more forgiving to candidates with less experience.&lt;/p&gt;
&lt;p&gt;You may need to start with local employers, who will typically focus on basic CRUD applications along with taking on junior maintenance work, and typically pay less. You could also consider contract positions. While they may be less complex than modding projects, these roles provide crucial professional experience and help you build a track record. They&#39;re also opportunities to learn how businesses operate, which is valuable knowledge that&#39;s hard to get from modding alone.&lt;/p&gt;
&lt;p&gt;Humble beginnings mark the career of a lot of software engineers. What matters is using these early positions to learn professional practices, build a network, and demonstrate reliability.&lt;/p&gt;
&lt;h2 id=&quot;tying-it-all-together-my-experience&quot; tabindex=&quot;-1&quot;&gt;Tying it all together: my experience &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#tying-it-all-together-my-experience&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;getting-my-job&quot; tabindex=&quot;-1&quot;&gt;Getting my job &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#getting-my-job&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;My last job search was in October 2021. Of the roughly 20 companies I applied to (through recruiters, referrals, or job applications), the most successful leads involved referrals from people who I knew from the &lt;em&gt;Minecraft&lt;/em&gt; scene that successfully made the transition to other employment. Of those, the furthest I got was with Ramp, for a few reasons:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I was referred by a former Ramp employee whose referrals were generally quite successful there. I worked with this person on many projects from 2012 to 2016. This baseline level of trust between Ramp and this former employee, along with keeping this connection alive, was necessary just to get me in the door.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://ramp.com/blog/the-art-of-hiring-insights&quot;&gt;Ramp likes to find &amp;quot;mispriced&amp;quot; talent&lt;/a&gt;: my background was unusual enough that curiosity and the desire to hire someone who could bring something unique to the table led them to seriously consider an obviously neurodivergent &lt;em&gt;Minecraft&lt;/em&gt; modder with unusual expertise. This is a bet that has paid off for them: I am often the &amp;quot;Minecraft whiz&amp;quot; being discussed.&lt;/li&gt;
&lt;li&gt;I had strong computer science fundamentals from not only a largely completed college education, but also my prior experience with &lt;em&gt;Minecraft&lt;/em&gt;. Ramp&#39;s interview process is a practical, and I was able to ace it with ease. I interviewed quite well and made a good impression upon the hiring team.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I chose to accept the Ramp offer as I believed the growth story (in terms of valuation and my career) was robust and that it would provide the best chance of success at establishing myself as credible with future employers.&lt;/p&gt;
&lt;h3 id=&quot;my-first-year-at-ramp&quot; tabindex=&quot;-1&quot;&gt;My first year at Ramp &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#my-first-year-at-ramp&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;At Ramp, I joined at a level that you might call &amp;quot;Software Engineer II&amp;quot; (internally, we call it IC4, being loosely based on Meta&#39;s similar ranking system). This reflected that I likely could deliver complete features on my own, unblock myself, and write production-quality code, and overall exhibit sound software engineering fundamentals. I entered this level having extensive &amp;quot;hard skills&amp;quot; experience &lt;em&gt;outside&lt;/em&gt; of a formal context, and so progressing at Ramp required me to develop a number of soft skills that I had only partially begun to develop.&lt;/p&gt;
&lt;p&gt;The projects I worked on at Ramp in my first year were representative of a newly-hired mid-level engineer at a rapidly-scaling fintech startup:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Integrate personal bank account linking.&lt;/li&gt;
&lt;li&gt;Finish work on integrating a new bank partner for our payments platform.&lt;/li&gt;
&lt;li&gt;Add the necessary support for representing wires completing more quickly than the days-long timeframes we already supported (ACH and printed checks).&lt;/li&gt;
&lt;li&gt;The biggest project of all: successfully integrate support for international payments through a third-party provider, Wise.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The first three projects primarily dwelled upon my &amp;quot;hard skills&amp;quot;: creating DB models, testing software, and getting code reviewed and approved by other engineers. The project scope and requirements were clearly defined, and the work primarily focused on hard skills and being an individual contributor at Ramp. I spent most of my time writing code compared to engaging in inter-team or cross-team collaboration.&lt;/p&gt;
&lt;p&gt;The Wise integration was the most complex project of all, because the requirements were poorly scoped and I was expected to take on most of the work of designing the implementation. As part of that, I had to collaborate with other teams at Ramp (product and legal), with an external team (a solutions team in New York and an operations team located in Estonia, so quite the extreme time difference!), write clear documentation for engineers to review, and clearly and timely communicate with other stakeholders. Along the way, I learned a lot about the U.S. financial system, the complexities of integrating with a non-trivial API, and solve challenges that I knew other teams would face. In particular, the need to automatically extract KYC data to provide to other third-party providers prompted me to build a reusable solution that has since been leveraged by other teams. The successful delivery of this complex project was a significant consideration in my promotion to senior software engineer (IC5) in March 2023.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot; tabindex=&quot;-1&quot;&gt;Conclusion &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/being-nonlinear-a-transition-from-modding/#conclusion&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Making the transition from game modding to professional software engineering won&#39;t be easy. You will need to learn new skills, adjust your expectations, and learn to navigate workplace dynamics. However, the fundamental skills you develop while modding - problem solving, coding, working with complex systems - can serve as an excellent foundation for a professional career.&lt;/p&gt;
&lt;p&gt;My journey from &lt;em&gt;Minecraft&lt;/em&gt; modding to fintech wasn&#39;t conventional, but it worked because I leveraged my existing technical skills while actively developing the professional skills I needed. The key is to be patient with yourself during the transition while remaining committed to growth and learning.&lt;/p&gt;
&lt;p&gt;If you&#39;re currently in the modding scene and considering making the transition, start preparing by:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Building a solid foundation in widely-used programming languages and tools&lt;/li&gt;
&lt;li&gt;Practicing professional communication&lt;/li&gt;
&lt;li&gt;Writing good, high-quality documentation&lt;/li&gt;
&lt;li&gt;Developing project management skills&lt;/li&gt;
&lt;li&gt;Building a network that can help you bridge the gap&lt;/li&gt;
&lt;li&gt;Being open to starting from humble beginnings&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Most importantly, don&#39;t view your modding experience as something to hide or minimize - it&#39;s a unique part of your journey that provides a unique perspective. The right employer will recognize and value that experience, even if it takes time to find them.&lt;/p&gt;
&lt;p&gt;The path forward might not be straightforward, but with dedication and the right approach, you can successfully transition from modding to a professional career in software engineering. Take me as an inspiring example of what &lt;em&gt;you&lt;/em&gt; can accomplish!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>📚 A 2024 dispatch</title>
		<link href="https://steinborn.me/posts/a-2024-dispatch/"/>
		<updated>2025-01-01T00:00:00Z</updated>
		<id>https://steinborn.me/posts/a-2024-dispatch/</id>
		<content type="html">&lt;p&gt;In classic Steinborn fashion, I forgot about my 2023 dispatch until &lt;a href=&quot;https://steinborn.me/posts/a-2023-dispatch/&quot;&gt;August 2024&lt;/a&gt;(!), and it wasn&#39;t necessarily a sufficient explanation of what had actually gone on. So it&#39;s time for me to digest all of 2024, and also try to be way more detailed about what went on, but I wound up starting on this post on New Years&#39; Eve. Why is that, you might ask?&lt;/p&gt;
&lt;p&gt;Logistical. I simply hadn&#39;t made it a priority then. I didn&#39;t even know people read this blog until relatively recently. For the longest time, it felt like I was simply shouting into the void.&lt;/p&gt;
&lt;p&gt;Now I get to dive into 2024, and let&#39;s just say... it was a decidedly mixed bag for me. A lot of unambigously &lt;em&gt;good&lt;/em&gt; things happened, but there were also quite a few low points that dragged me down. But let&#39;s waste no more time.&lt;/p&gt;
&lt;h2 id=&quot;sorrow&quot; tabindex=&quot;-1&quot;&gt;Sorrow &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#sorrow&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This year has been marked by one rather consistent theme: sorrow. With no way to control what&#39;s going on.&lt;/p&gt;
&lt;p&gt;The year began with me losing two family members: my grandmother died on January 30th, 2024, and my mother died on February 11th, 2024. Just now, into New Years Eve when I wrote this, I looked at the photos I took at the funeral: cold, embalmed, what once was is now no more. Thus, my first two trips of the year entailed me flying (at the last minute) from NYC to Atlanta to attend first my grandmother&#39;s and my mother&#39;s funerals.&lt;/p&gt;
&lt;p&gt;My grandmother&#39;s fate was explicitly chosen by her. Her kidneys had failed, and instead of dialysis, she chose to let nature take its course. I don&#39;t blame her for taking that course—having approached beyond 80, a thoroughly empty nest, and a progressive decline in her ability to do things, I wasn&#39;t shocked to see her take this path.&lt;/p&gt;
&lt;p&gt;My mother, on the other hand, had been in very poor health for years. There were many health scares, some sending her to the hospital. The episode that would finally claim her life started in late October 2023. She wound up at Grady for several months before being released to a rehabilitation facility, where she seemed to improve before her heart gave out through cardiac arrest. I still remember how much time I had with her: five minutes at the rehab facility, before they needed to do something with her and I had to go back to the airport (conveniently, this facility was located just south of Hartsfield-Jackson).&lt;/p&gt;
&lt;p&gt;After my mother died, this left me in a pickle: my brothers relied on her Social Security disability, while I was trying to live my own life in New York. This caused some tension. The good news is that my younger brother did finally manage to find a job and keep it down, so I&#39;m not as worried about them any more, and they&#39;re no longer having to rely on me to support their day-to-day needs, but there were a lot of very uncomfortable conversations with them and other family members in the wake of it all, and that&#39;s something I wish not to repeat ever again.&lt;/p&gt;
&lt;p&gt;All of this has been painful. It&#39;s part of the reason why I simply haven&#39;t worked on very many personal projects. (That said, I did manage to redo this website using UnoCSS and learned an entirely new way of CSS, so there is that.)&lt;/p&gt;
&lt;h2 id=&quot;writing&quot; tabindex=&quot;-1&quot;&gt;Writing &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#writing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Sometimes I consider myself a storyteller who just happens to be a software engineer.&lt;/p&gt;
&lt;p&gt;It was late in the year when I first started being serious about writing again. Prior to this, I had written &lt;a href=&quot;https://steinborn.me/posts/going-back-home-tapestry-of-time/&quot;&gt;a poem about grieving&lt;/a&gt;, before I gave my website a six month hiatus due to other events that were going on at the time (primarily work-related). As a result, my site hasn&#39;t taken off (on the orange site or anywhere else, in fact).&lt;/p&gt;
&lt;p&gt;I started being much more serious about writing starting in August. In fact, my most prolific topic was the &lt;em&gt;two&lt;/em&gt; website redesigns I did, &lt;a href=&quot;https://steinborn.me/posts/website-touch-up-2024/&quot;&gt;one in August&lt;/a&gt; (a fairly minor one, mostly adding dark mode to an HTML5 UP template) and &lt;a href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/&quot;&gt;one in October&lt;/a&gt; (basically a total redesign). The latter is not my best work, as I documented it quickly after doing the redesign and GitHub Copilot filled in some of the text with some rather awkward language. (Pro-tip: code completion LLMs produce rather boring English sentences. Prefer using a fully-fledged chatbot instead. I&#39;ve been mostly using Claude.)&lt;/p&gt;
&lt;p&gt;I also wrote my second longform technical article, &lt;a href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/&quot;&gt;&lt;em&gt;The Velocity Chronicles: Part 0&lt;/em&gt;&lt;/a&gt;, discussing quite a bit of my background in the &lt;em&gt;Minecraft&lt;/em&gt; scene, and the motivation behind me starting the Velocity project in the first place. I&#39;ve gotten some positive feedback on it, and I hope to get Part 1 out in the new year, primarily covering events that happened in late 2018 and 2019.&lt;/p&gt;
&lt;p&gt;I also started work on two pieces of fiction in earnest: a novel and a short story called &amp;quot;Precipices.&amp;quot; I started on the novel in September and while I&#39;ve made substantial progress, it&#39;s not at a point where I&#39;d be happy with publishing the work. &amp;quot;Precipices&amp;quot;, which I started on over the holiday break, is much closer to complete (it will probably be out in January 2025).&lt;/p&gt;
&lt;p&gt;Overall, a much more successful year in terms of writing things! I hope to continue doing more writing with a mix of fiction and technical writing, in the hopes of establishing a bigger &amp;quot;brand&amp;quot; for myself. I&#39;m obviously not looking to be some sort of &amp;quot;thought leader&amp;quot; or the like, I just want to keep my brain active. I&#39;m also hoping to write my 2025 dispatch as the year goes on instead of doing it all at one big spurt at the end of the year, just to reduce the cognitive load on myself.&lt;/p&gt;
&lt;p&gt;I do also feel as if my focus on writing at work has also greatly contributed to sharpening my writing skills overall. That said, if I had two things to focus on, it would be &amp;quot;sharpening my creative writing skills&amp;quot; and &amp;quot;actually remembering to write things.&amp;quot;&lt;/p&gt;
&lt;h2 id=&quot;ramp-ramp-ramp&quot; tabindex=&quot;-1&quot;&gt;Ramp, Ramp, Ramp! &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#ramp-ramp-ramp&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, let&#39;s talk about the good parts: 2024 was actually a banner year for me at Ramp! That year saw a few major accomplishments, which I hope to blog about either on the Ramp engineering blog or here (if they&#39;re not particularly Ramp-specific).&lt;/p&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/7fjEPN9DEy-768.webp 768w, https://steinborn.me/img/generated/7fjEPN9DEy-1024.webp 1024w, https://steinborn.me/img/generated/7fjEPN9DEy-1280.webp 1280w, https://steinborn.me/img/generated/7fjEPN9DEy-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Eric Glyman, celebrating his birthday, poses for a photo with me.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/7fjEPN9DEy-768.webp&quot; width=&quot;1536&quot; height=&quot;1541&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;My impact is recognized. Also, I sport a funky, graffiti-inspired credit card-themed tie.&lt;/div&gt;
&lt;p&gt;So far, Ramp has been the longest gig I&#39;ve ever worked, and that&#39;s including the &lt;em&gt;Minecraft&lt;/em&gt; server space (the longest was previously my time at Mineteria/Voldex? That was March 2018 to January 2021, so close to three years). Having this level of stability and longevity is previously unexplored territory for me. It has also been, arguably, the most interesting and impactful gig I&#39;ve ever had, albeit less exciting in some ways (only in &lt;em&gt;Minecraft&lt;/em&gt; would you be gutsy enough to write your own proxy at small scale and get away with it).&lt;/p&gt;
&lt;p&gt;I joined Ramp in November 2021, at what I consider to be the &amp;quot;Goldilocks zone&amp;quot;: early enough to continue to see the company scale, and yet late enough that almost all the risk was removed. (I also lucked out in joining at a time when the job market was unusually good for software engineers.) Ever since that point, Ramp has progressed from being a small, ~200 person startup, to having over 1,000 employees and penetrating the enterprise market. With this move upscale comes significant new challenges that we&#39;ll have to solve, and a lot of my work in 2024 was principally to prepare our issuing platform for this next stage of growth. We took a long, hard look at the issuing platform that got us to a $7.65 billion valuation at the time, and considered it unfit for purpose as we continued to scale. The responsibility for making it scale for future growth has largely fallen upon me. No pressure!&lt;/p&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/S48rZ6cM_a-768.webp 768w, https://steinborn.me/img/generated/S48rZ6cM_a-1024.webp 1024w, https://steinborn.me/img/generated/S48rZ6cM_a-1280.webp 1280w, https://steinborn.me/img/generated/S48rZ6cM_a-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Ramp metal card with branding &#39;Veni Vedi Vici&#39;.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/S48rZ6cM_a-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;This doesn&#39;t look like much, but it was actually a pretty significant milestone!&lt;/div&gt;
&lt;p&gt;Our team changed a lot over the year. Some of the new folks we hired were people I mentored was responsible for mentoring (&lt;a href=&quot;https://ramp.com/careers&quot;&gt;yes, we&#39;re hiring... come work with me!&lt;/a&gt;)&lt;/p&gt;
&lt;p&gt;I also got to work on some interesting side quests. I&#39;m hoping to write about those in the future (whether here or on the Ramp engineering blog), but a lot of those have the end effect of making the Ramp platform more reliable, important as we begin to be depended upon by larger customers.&lt;/p&gt;
&lt;p&gt;The personal tragedy of 2024 did spill over into my work. There were times where I almost wanted to give up. One such point came in early April, where I almost sought to leave my present team, but after carefully thinking it over and discussing it, cooler heads prevailed and I decided to stay and continue down my current path. It&#39;s been quite successful, all things considered.&lt;/p&gt;
&lt;p&gt;So, what does 2025 have in store for me? Ramp has only captured a very small fraction of the TAM of U.S. corporate spending, and an even lower percentage of global corporate spending. My job now is to keep the momentum going! That means evolving our issuing platform, helping build up a world-class financial technology primitives team providing leverage to the rest of Ramp, and supporting our move towards new markets for Ramp. It&#39;s going to be an exciting time to be at Ramp!&lt;/p&gt;
&lt;h2 id=&quot;travel&quot; tabindex=&quot;-1&quot;&gt;Travel &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#travel&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I only made two major trips in 2024, aside from funerals and a emergency trip related to estate matters. The first trip was to Miami, to work out of the Ramp office there for a week, and the second trip took me to a place I&#39;d never been before: Washington, D.C. Both trips were prompted by the above family deaths, the former being a welcome change of scenry, the latter being a much-needed break from work and the family situation I wound up in.&lt;/p&gt;
&lt;p&gt;Looking ahead to 2025, I&#39;m planning to keep my travel schedule light. While my trips to Miami and DC had their bright spots, 2024 reminded me just how draining travel can be – especially the multiple last minute flights to Atlanta for funerals, which took both an emotional and financial toll. The upside? Amtrak is very good and can make things less painful, at least if your destination is on the Northeast Corridor. Between those difficult journeys and the general hassles of travel (choosing transportation, booking hotels, navigating airports, and planning itineraries), I&#39;ve appreciated staying put. There&#39;s so much of New York I haven&#39;t seen yet!&lt;/p&gt;
&lt;h3 id=&quot;miami&quot; tabindex=&quot;-1&quot;&gt;Miami &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#miami&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I was in Miami in late March for a work trip, which I got permission to take in the aftermath of my mother dying. Because this was for work, I wasn&#39;t able to spend too much time doing other things, but I did at least visit the Wynwood Walls and the Museum of Graffiti, along with going to a gun range (which brought out a decidedly different side of me, closer to my origins than before).&lt;/p&gt;
&lt;p&gt;That said, there was a significant work-related milestone accomplished while I was here in the course of reworking our issuing platform...&lt;/p&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/l-BA3yOMpJ-768.webp 768w, https://steinborn.me/img/generated/l-BA3yOMpJ-1024.webp 1024w, https://steinborn.me/img/generated/l-BA3yOMpJ-1280.webp 1280w, https://steinborn.me/img/generated/l-BA3yOMpJ-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;A retired Chicago &#39;L&#39; 2400-series car at the Wynwood Walls, car number 2491&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/l-BA3yOMpJ-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Why is this Chicago &quot;L&quot; train lounging in the Miami heat?!?&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/z-VmgZRjWB-768.webp 768w, https://steinborn.me/img/generated/z-VmgZRjWB-1024.webp 1024w, https://steinborn.me/img/generated/z-VmgZRjWB-1280.webp 1280w, https://steinborn.me/img/generated/z-VmgZRjWB-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Graffiti typography overview at the Museum of Graffiti&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/z-VmgZRjWB-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Getting a lesson in graffiti typography&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/607SrKDTN2-768.webp 768w, https://steinborn.me/img/generated/607SrKDTN2-1024.webp 1024w, https://steinborn.me/img/generated/607SrKDTN2-1280.webp 1280w, https://steinborn.me/img/generated/607SrKDTN2-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Skateboards at the Museum of Graffiti&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/607SrKDTN2-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Some cool skateboards&lt;/div&gt;
&lt;h3 id=&quot;washington-d-c&quot; tabindex=&quot;-1&quot;&gt;Washington, D.C. &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#washington-d-c&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I decided to go on this trip in April 2024 for Memorial Day week. I &lt;em&gt;needed&lt;/em&gt; this: my last &amp;quot;break&amp;quot; was in late October 2023 and I stayed in the city after a particularly rough on-call cycle and &amp;quot;quality cycle&amp;quot; that sapped me. I had never been to D.C. before, not even for school, but surprisingly, there were a lot of connections that Ramp and even my team had to the D.C. area! It was where my aunt went to school, and I also knew someone from the &lt;em&gt;Minecraft&lt;/em&gt; scene that lived in the area.&lt;/p&gt;
&lt;p&gt;Arrival was smooth thanks to taking the Amtrak &lt;em&gt;Northeast Regional&lt;/em&gt; train from New York Penn Station, which drops you off at Union Station, not far from the Capitol and with convenient access to the Red Line of the Washington Metro. You can bet I enjoyed riding on perhaps America&#39;s greatest Great Society metro system...&lt;/p&gt;
&lt;p&gt;I got to see the obligatory things: the Capitol complex, the White House, various random government buildings, museums on the National Mall, the Metro, Arlington National Cemetery, Old Town Alexandria, and more.&lt;/p&gt;
&lt;p&gt;Perhaps most interesting of all, I spent time in the chaos known as &lt;a href=&quot;https://en.wikipedia.org/wiki/Tysons,_Virginia&quot;&gt;Tysons&lt;/a&gt; and the area around the Dulles Access Road (accessed via the Silver Line, of course) to meet up with an old buddy of mine from the Mineteria days. Tysons is a real mess of a place: highways, wide stroads and other auto-centric land uses, office towers, shopping malls, and even Washington Metro stations sprouting in a place that was once largely forest and farmland. On the particular Friday I went there, it was a well-appointed ghost town. But hey, now I can say I&#39;ve been there!&lt;/p&gt;
&lt;p&gt;The trip, unfortunately, did end with me contracting COVID-19. Totally worth it, though!&lt;/p&gt;
&lt;p&gt;Here&#39;s a few photos from that trip.&lt;/p&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/JoJeMRQyaG-768.webp 768w, https://steinborn.me/img/generated/JoJeMRQyaG-1024.webp 1024w, https://steinborn.me/img/generated/JoJeMRQyaG-1280.webp 1280w, https://steinborn.me/img/generated/JoJeMRQyaG-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;An Orange Line train bound for New Carrollton&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/JoJeMRQyaG-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;An Orange Line 7000-series train bound for New Carrollton has stopped at Farragut West. The Metro is known for its iconic &quot;waffle&quot; brutalist station design, especially in downtown D.C. and the stops closest to downtown.&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/Zx2bcXNBYb-768.webp 768w, https://steinborn.me/img/generated/Zx2bcXNBYb-1024.webp 1024w, https://steinborn.me/img/generated/Zx2bcXNBYb-1280.webp 1280w, https://steinborn.me/img/generated/Zx2bcXNBYb-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;The White House&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/Zx2bcXNBYb-768.webp&quot; width=&quot;1536&quot; height=&quot;1189&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Of course I went to the usual attractions and centers of power. Only do it once, though.&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/cIpSqEeJKI-768.webp 768w, https://steinborn.me/img/generated/cIpSqEeJKI-1024.webp 1024w, https://steinborn.me/img/generated/cIpSqEeJKI-1280.webp 1280w, https://steinborn.me/img/generated/cIpSqEeJKI-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Georgetown, Baltimore and Ohio Canal&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/cIpSqEeJKI-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Nice, almost bucolic Georgetown, the end of the Baltimore and Ohio Canal.&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/87kY4xuLmx-768.webp 768w, https://steinborn.me/img/generated/87kY4xuLmx-1024.webp 1024w, https://steinborn.me/img/generated/87kY4xuLmx-1280.webp 1280w, https://steinborn.me/img/generated/87kY4xuLmx-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;The Washington Monument&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/87kY4xuLmx-768.webp&quot; width=&quot;1536&quot; height=&quot;1016&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;I took a lot of photos of the Washington Monument but this was my favorite.&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/qRFJ2yzFI3-768.webp 768w, https://steinborn.me/img/generated/qRFJ2yzFI3-1024.webp 1024w, https://steinborn.me/img/generated/qRFJ2yzFI3-1280.webp 1280w, https://steinborn.me/img/generated/qRFJ2yzFI3-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;A scenic view of the Capitol Beltway and Tysons&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/qRFJ2yzFI3-768.webp&quot; width=&quot;1536&quot; height=&quot;1561&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Tysons is a secondary business district within the Washington metropolitan area, and it&#39;s a &lt;b&gt;weird&lt;/b&gt; place.&lt;/div&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/jc5Bg48nY1-768.webp 768w, https://steinborn.me/img/generated/jc5Bg48nY1-1024.webp 1024w, https://steinborn.me/img/generated/jc5Bg48nY1-1280.webp 1280w, https://steinborn.me/img/generated/jc5Bg48nY1-1536.webp 1536w&quot; sizes=&quot;(max-width: 768px) 100vw, (max-width: 1024px) 100vw, (max-width: 1280px) 100vw, (max-width: 1536px) 100vw&quot; /&gt;
  &lt;img alt=&quot;Pour-overs at the Capital One Tower with Joey&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/jc5Bg48nY1-768.webp&quot; width=&quot;1536&quot; height=&quot;1152&quot; /&gt;
&lt;/picture&gt;
&lt;div class=&quot;pic-caption&quot;&gt;Joey invited me in for pour-overs. I didn&#39;t lack for caffeination on this trip for sure!&lt;/div&gt;
&lt;h2 id=&quot;prediabetes-eating-disorders-and-weight-loss&quot; tabindex=&quot;-1&quot;&gt;Prediabetes, eating disorders, and weight loss &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#prediabetes-eating-disorders-and-weight-loss&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, a bit of context, since I haven&#39;t talked about this before.&lt;/p&gt;
&lt;p&gt;I&#39;d always been on the larger side. My parents would say my stomach was like a black hole since I would go back for seconds or even thirds. I hadn&#39;t known that I was actually planting the seeds of larger health problems down the line. That said, when I moved up to New York, the fact I was walking around everywhere caused me to begin losing at least some weight and be more fit.&lt;/p&gt;
&lt;p&gt;In 2022, I went for my first check-up in a long time, and it was determined that I had prediabetes. In late 2023, I was prescribed &lt;a href=&quot;https://en.wikipedia.org/wiki/Semaglutide&quot;&gt;semaglutide&lt;/a&gt; (specifically Wegovy), the blockbuster anti-obesity medication that costs a lot of money and is &lt;em&gt;very&lt;/em&gt; popular in America for obvious reasons. (In fact, &lt;a href=&quot;https://www.cbsnews.com/news/obesity-rate-us-adults-cdc-data-map/&quot;&gt;the U.S. obesity rate has stabilized&lt;/a&gt; and is likely to decline thanks to these medications). I had difficulty sourcing the medication in 2023, so I only started benefitting from it in 2024. In the meantime, I was prescribed &lt;a href=&quot;https://en.wikipedia.org/wiki/Metformin&quot;&gt;metformin&lt;/a&gt; to help with blood sugar control.&lt;/p&gt;
&lt;p&gt;I think the results really do speak for themselves:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am less likely to act on food-related urges, being better able to control them.&lt;/li&gt;
&lt;li&gt;I lost a lot of weight, going from 320 pounds at the end of 2023 to 250 pounds at the end of 2024, due to a combination of exercise, eating less food, and improving my diet. People in real life have noticed the significant weight loss.&lt;/li&gt;
&lt;li&gt;Hemoglobin A1c, an average of blood sugar levels in the body, went from being in the prediabetes range (peaking at 5.9% in September 2023) to being in the non-diabetic range (5.6% in December 2024). My prediabetes is now well-managed by medication.&lt;/li&gt;
&lt;li&gt;My blood pressure has also gone down.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I feel like a completely different person now, and I am hoping to build upon this progress in 2025. However, it has been hard to derive all the benefits due to all the other things that erupted in my personal life.&lt;/p&gt;
&lt;h2 id=&quot;finally-a-callout-to-an-old-colleague&quot; tabindex=&quot;-1&quot;&gt;Finally, a callout to an old colleague... &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2024-dispatch/#finally-a-callout-to-an-old-colleague&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://morepablo.com/2024/07/2023-in-review.html&quot;&gt;Pablo Meier was &lt;em&gt;also&lt;/em&gt; late in writing his 2023 in review post&lt;/a&gt;, but there is one memorable photo from it:&lt;/p&gt;
&lt;img alt=&quot;Pablo and Andrew meet for coffee before a doomed bridge-crossing attempt&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/H3D43fONyV-700.webp&quot; width=&quot;700&quot; height=&quot;526&quot; /&gt;
&lt;div class=&quot;pic-caption&quot;&gt;The offer to cross the Brooklyn Bridge (or any bridge of your choice) is still valid! 😀&lt;/div&gt;
</content>
	</entry>
	
	<entry>
		<title>🛠️ Fixing a broken Fedora 38 to 40 upgrade</title>
		<link href="https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/"/>
		<updated>2024-11-02T00:00:00Z</updated>
		<id>https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/</id>
		<content type="html">&lt;p&gt;I recently upgraded my gaming computer from Fedora 38 to 40 and it didn&#39;t go as planned. I went through a bunch of pain to attempt to fix my partially-completed upgrade, but luckily I was able to complete the upgrade. Here, I took some notes of the process I used to rescue my system.&lt;/p&gt;
&lt;p&gt;More regular programming will resume eventually. I have another Fedora-related bugbear to write about (related to Asahi Linux)... but that&#39;s for another day.&lt;/p&gt;
&lt;h2 id=&quot;disclaimer&quot; tabindex=&quot;-1&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#disclaimer&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This is a very specific set of steps that I took to fix my system. I can&#39;t guarantee that it will work for you, but it might be worth a shot if you&#39;re in a similar situation. Your mileage may vary. If you&#39;re in doubt, I would ask for help on the &lt;a href=&quot;https://ask.fedoraproject.org/&quot;&gt;Fedora forums&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;waiting-for-an-upgrade-to-complete&quot; tabindex=&quot;-1&quot;&gt;Waiting for an upgrade to complete &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#waiting-for-an-upgrade-to-complete&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First, I booted the system and ran &lt;code&gt;dnf upgrade&lt;/code&gt; to see if there were any packages that needed to be updated. There were (the machine hadn&#39;t been powered on since February), and I installed those and rebooted. So far, so good.&lt;/p&gt;
&lt;p&gt;Now, we need to begin the actual upgrade process using the GNOME Software application, as recommended in the Fedora documentation. Everything was downloaded successfully and I was able to reboot the machine. The upgrade started but did not progress much beyond 52% completion. I let the upgrade sit there for 45 minutes. After about 10 minutes of waiting, I decided to power off the machine and reboot, since the upgrade appeared stuck with no output or progress.&lt;/p&gt;
&lt;p&gt;Big mistake.&lt;/p&gt;
&lt;h2 id=&quot;the-reboot&quot; tabindex=&quot;-1&quot;&gt;The reboot &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#the-reboot&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After rebooting, the system was in a bad state. The system booted with a Fedora 38 kernel. I could not log into the desktop. When I switched to a shell with &lt;code&gt;Ctrl+Alt+F2&lt;/code&gt;, the system claimed to be on Fedora Linux 40. I was able to log in as my user on the shell successfully, which did tell me that there was a chance to recover the system, or at the very least, backup my data before a reinstall.&lt;/p&gt;
&lt;p&gt;So we have a system in a partially upgraded state: some chunk of the system is from Fedora 38, some other chunk is from Fedora 40. Let&#39;s try to fix it.&lt;/p&gt;
&lt;h2 id=&quot;fixing-the-partially-upgraded-system&quot; tabindex=&quot;-1&quot;&gt;Fixing the partially upgraded system &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#fixing-the-partially-upgraded-system&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My first step was to try the obvious thing, and run &lt;code&gt;dnf distro-sync --releasever=40&lt;/code&gt;. This command should sync the system to the Fedora 40 release. Unfortunately, this command failed with a deceptively simple error:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Traceback (most recent call last):&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  File &quot;/usr/bin/dnf&quot;, line 57, in &amp;#x3C;module&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;    from dnf.cli import main&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;ModuleNotFoundError: No module named &#39;dnf&#39;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh dear. Our package manager is broken. Are we screwed?&lt;/p&gt;
&lt;h3 id=&quot;a-python-scavenger-hunt&quot; tabindex=&quot;-1&quot;&gt;A Python scavenger hunt &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#a-python-scavenger-hunt&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I guessed that in the intervening period, the system Python version had been upgraded. (&lt;a href=&quot;https://fedoraproject.org/wiki/Changes/Python3.12&quot;&gt;It turns out that Fedora 39 upgraded to Python 3.12&lt;/a&gt;, up from Python 3.11 in Fedora 38. But it was late into the night and looking over changelogs was the last thing I wanted to do.) I opened a Python shell and confirmed that the system Python version was indeed 3.12.&lt;/p&gt;
&lt;p&gt;Now we just need to make sure the &lt;code&gt;dnf&lt;/code&gt; module actually existed somewhere, otherwise we would need to manually re-install &lt;code&gt;dnf&lt;/code&gt; via &lt;code&gt;rpm&lt;/code&gt; before we made any progress. While there&#39;s a more elegant, Pythonic way of doing it, I examined &lt;code&gt;/usr/lib/python3.12/site-packages&lt;/code&gt; and confirmed that the &lt;code&gt;dnf&lt;/code&gt; module was absent, and then tried &lt;code&gt;/usr/lib/python3.11/site-packages&lt;/code&gt;, and discovered that the module existed. I didn&#39;t know this at the time, but we now know that &lt;code&gt;dnf&lt;/code&gt; was &lt;em&gt;not&lt;/em&gt; yet upgraded at the time I rebooted the system. From there, I made my first leap of faith: I patched &lt;code&gt;/usr/bin/dnf&lt;/code&gt; to invoke &lt;code&gt;python3.11&lt;/code&gt; instead of &lt;code&gt;python&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Now we can run &lt;code&gt;dnf&lt;/code&gt; again. This time, the command runs successfully. Our system is far from fixed, but we now have a working package manager, which we will need to fix the rest of the system.&lt;/p&gt;
&lt;h3 id=&quot;fooling-the-system-into-thinking-its-fedora-40&quot; tabindex=&quot;-1&quot;&gt;Fooling the system into thinking it&#39;s Fedora 40 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#fooling-the-system-into-thinking-its-fedora-40&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that &lt;code&gt;dnf&lt;/code&gt; works, we can attempt to fix the system. That is where I found &lt;a href=&quot;https://discussion.fedoraproject.org/t/fixing-half-completed-system-upgrade/124484/12&quot;&gt;a really helpful forum post&lt;/a&gt; from a user experiencing a rather similar issue to me, except I had the &lt;code&gt;dnf&lt;/code&gt; hoop to jump through.&lt;/p&gt;
&lt;p&gt;First, we need to reinstall the &lt;code&gt;fedora-release&lt;/code&gt; package using the &amp;quot;correct&amp;quot; version. This package contains the release information for the system, and since it&#39;s probably not correct, it&#39;s important for what we need to do in order to proceed. We can do this with the following command:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;dnf&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt; --releasever=40&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; reinstall&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; fedora-release-&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D7BA7D&quot;&gt;&#92;*&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now, &lt;code&gt;dnf&lt;/code&gt; should believe that we are &amp;quot;supposed&amp;quot; to be on Fedora 40. I&#39;m still using &lt;code&gt;--releasever=40&lt;/code&gt; to ensure that we&#39;re installing the Fedora 40 packages, but it should not be necessary once you run this command.&lt;/p&gt;
&lt;p&gt;Note that you will need internet access for this to work. Luckily, the system was connected via Ethernet, so I didn&#39;t have to worry about configuring that myself, presumably as &lt;code&gt;NetworkManager&lt;/code&gt; was working correctly. (If you are on Wi-Fi, you might have to configure the network manually.)&lt;/p&gt;
&lt;h3 id=&quot;the-strategy&quot; tabindex=&quot;-1&quot;&gt;The strategy &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#the-strategy&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The system has duplicate packages (incompletely-removed Fedora 38 packages that were upgraded to Fedora 40, that &lt;code&gt;dnf&lt;/code&gt; hasn&#39;t cleaned up), and packages that simply haven&#39;t been upgraded to Fedora 40. Our goal is to remove all the duplicate Fedora 38 packages, finish up the upgrade using &lt;code&gt;dnf distro-sync&lt;/code&gt;, and then reboot to get to a hopefully-working Fedora 40 system.&lt;/p&gt;
&lt;h3 id=&quot;removing-duplicate-packages&quot; tabindex=&quot;-1&quot;&gt;Removing duplicate packages &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#removing-duplicate-packages&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, let&#39;s remove all the duplicate packages. We can do this with the following command:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;dnf&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; remove&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt; --duplicates&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt; --releasever=40&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In theory, this command should remove all the Fedora 38 packages and install the Fedora 40 equivalents. However, it didn&#39;t work for me, initially due to multi-arch conflicts. At this point, I wanted to prioritize safety over speed, so I opted to resolve each conflict by hand to ensure that I knew what I did, instead of specifying any &lt;code&gt;dnf&lt;/code&gt; options to go &amp;quot;nuclear&amp;quot; (like permitting broken dependencies).&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I was concerned about the large number of packages that I needed to download, but since &lt;code&gt;dnf&lt;/code&gt; was installing Fedora 40 packages in exchange, it was probably safe to proceed.&lt;/li&gt;
&lt;li&gt;After the download, &lt;code&gt;dnf&lt;/code&gt;&#39;s transaction test failed with a large volume of conflicts caused by multi-arch packages (this was an &lt;code&gt;x86_64&lt;/code&gt; system with &lt;code&gt;i686&lt;/code&gt; packages installed). I elected to remove all the &lt;code&gt;i686&lt;/code&gt; packages from the system using &lt;code&gt;dnf remove *.i686&lt;/code&gt; and temporarily losing the ability to run 32-bit applications on the system. We can reinstall those later.&lt;/li&gt;
&lt;li&gt;Next, I had conflicts related to the KDE Framework 5 to 6 upgrade. I removed all the &lt;code&gt;kf5-*&lt;/code&gt; packages from the system in order to proceed, since I don&#39;t use KDE on this machine.&lt;/li&gt;
&lt;li&gt;There was a conflict caused by the &lt;code&gt;mozjs78&lt;/code&gt; (this being the SpiderMonkey engine version bundled with Firefox 78) being missing in Fedora 38. I removed the &lt;code&gt;mozjs78&lt;/code&gt; package from the system. Nothing depended on it in my case.&lt;/li&gt;
&lt;li&gt;Finally, there was a conflict caused by the &lt;code&gt;cups-filters&lt;/code&gt; package being partially split with a &lt;a href=&quot;https://src.fedoraproject.org/rpms/cups-filters/c/f0c5de2a54228ebcc87ebeac9db4afc023808cbf?branch=rawhide&quot;&gt;&lt;code&gt;-driverless&lt;/code&gt; package in Fedora 40&lt;/a&gt;. I removed the &lt;code&gt;cups-filters&lt;/code&gt; package from the system. I don&#39;t print on this machine, so it was reasonably safe to remove.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;After all these steps, I was able to run the &lt;code&gt;dnf remove --duplicates --releasever=40&lt;/code&gt; command successfully. This command removed all the duplicate Fedora 38 packages from the system, and installed the Fedora 40 equivalents.&lt;/p&gt;
&lt;h3 id=&quot;the-distro-sync-and-solving-the-mystery-of-my-long-upgrade&quot; tabindex=&quot;-1&quot;&gt;The distro-sync and solving the mystery of my long upgrade &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#the-distro-sync-and-solving-the-mystery-of-my-long-upgrade&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we have removed all the duplicate packages, we can run the &lt;code&gt;dnf distro-sync --releasever=40&lt;/code&gt; command. This command will upgrade all the packages that have yet to be upgraded to Fedora 40. This command ran successfully for me, and I was able to reboot the system.&lt;/p&gt;
&lt;p&gt;But it was taking quite a while for the upgrade to complete. In particular, it was stuck on running a script for &lt;code&gt;smartmontools-selinux&lt;/code&gt;. After a few minutes, I open up another shell and run &lt;code&gt;htop&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Turns out, 100% of a CPU core is being pegged, running &lt;code&gt;restorecon&lt;/code&gt;. That means the system is relabeling the entire filesystem. Luckily, patience was key, and after another 30 minutes, the relabeling process completed and the rest of the upgrade proceeded smoothly. I did wonder whether or not this was why the upgrade had taken so long, since there was essentially no feedback for a lengthy period of time.&lt;/p&gt;
&lt;p&gt;Once the command completed, I rebooted the system, hoping for a working system.&lt;/p&gt;
&lt;h3 id=&quot;almost-there&quot; tabindex=&quot;-1&quot;&gt;Almost there &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#almost-there&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The reboot was successful, however the &lt;code&gt;dracut&lt;/code&gt; initramfs let me know that the system was still not fully upgraded, letting me know that Fedora 38 was end-of-life. However, I had a fully working system at this point. I still wanted to fix this issue, though.&lt;/p&gt;
&lt;p&gt;I had to find the latest &lt;code&gt;kernel-core&lt;/code&gt; version (&lt;a href=&quot;https://packages.fedoraproject.org/pkgs/kernel/kernel-core/&quot;&gt;ref&lt;/a&gt;) and reinstall it with &lt;code&gt;dnf reinstall kernel-core&lt;/code&gt;. After this, I rebooted the system and saw that the new kernel was present and ready to be booted into.&lt;/p&gt;
&lt;p&gt;My nightmare is over. I have a fully-upgraded Fedora 40 system.&lt;/p&gt;
&lt;h2 id=&quot;so-what-did-i-learn&quot; tabindex=&quot;-1&quot;&gt;So, what did I learn? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/fixing-a-broken-fedora-38-to-40-upgrade/#so-what-did-i-learn&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Don&#39;t interrupt a system upgrade.&lt;/strong&gt; This is the most important lesson. Interrupting an upgrade guarantees a hosed system, which might be difficult to recover.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;I was lucky that someone had a similar issue to mine&lt;/strong&gt;, but the fact that I had to rely on a random internet forum post to fix my system was unnerving. However, I understood what the commands were doing and was willing to accept the risks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Linux can be resilient.&lt;/strong&gt; The system actually booted to multi-user and I had working internet access, making the system recoverable.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;But it is also not anti-fragile.&lt;/strong&gt; It is &lt;em&gt;laughably&lt;/em&gt; easy to screw up a Linux system and put it in a broken or unbootable state. I was lucky that I was able to recover the system. If things had shaken out differently, I would had to resort to attempting to fix the system via a &lt;code&gt;chroot&lt;/code&gt; (there was also a Ubuntu install on a separate partition on the system) or reinstalling the system from scratch via a live USB.&lt;/li&gt;
&lt;/ul&gt;
</content>
	</entry>
	
	<entry>
		<title>🎨 Sprucing up my website for 2024, part 2</title>
		<link href="https://steinborn.me/posts/website-touch-up-2024-part-2/"/>
		<updated>2024-10-22T00:00:00Z</updated>
		<id>https://steinborn.me/posts/website-touch-up-2024-part-2/</id>
		<content type="html">&lt;p&gt;Well, it has only been... &lt;a href=&quot;https://steinborn.me/posts/website-touch-up-2024/&quot;&gt;2 months since I last did this exercise&lt;/a&gt;. But I&#39;ve been thinking about this for a while, even as I was redoing my previous design. This time around, I decided to just go ahead and do it and see where the cards fell, and I was very pleased with the result I came up with.&lt;/p&gt;
&lt;h2 id=&quot;so-why-now&quot; tabindex=&quot;-1&quot;&gt;So why now? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#so-why-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A lot of it has to do with a few factors:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I am moving away from technical writing, which has not been a major focus for this blog as of late (not withstanding that Ramp enjoys most of the fruits of that labor) in favor of creative writing.&lt;/li&gt;
&lt;li&gt;The old design was simply not suitable for long-form story telling, which is a topic I have gotten progressively more interested in. (As in, I am looking to post novels on this website.)&lt;/li&gt;
&lt;li&gt;The performance, readability, and accessibility of the old site could be much better.&lt;/li&gt;
&lt;li&gt;The old design worked best being image-heavy, but I simply don&#39;t provide images for every post, nor do I want to. (I also don&#39;t want to just use DALL-E or look up stock images for the sake of having images.) In some cases, images are just a flat-out tall order. One post in the works is a novel, and I don&#39;t have the resources or desire to commission an artist to draw things for it, especially when the universe is still, to some degree, fluid.&lt;/li&gt;
&lt;li&gt;Finally, I just felt &lt;em&gt;tired&lt;/em&gt; of fighting my extensively hacked-up template, and wanted a fresh start.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;so-whats-new&quot; tabindex=&quot;-1&quot;&gt;So what&#39;s new? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#so-whats-new&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I rebuilt the entire website&#39;s style with &lt;a href=&quot;https://unocss.dev/&quot;&gt;UnoCSS&lt;/a&gt;. This proved to be surprisingly less painful than expected. With only a few hours of effort, I got a sketch of a design I was happy with, and with a few more hours of work, I integrated it into my existing Eleventy setup.&lt;/p&gt;
&lt;p&gt;Some of the highlights of the new design:&lt;/p&gt;
&lt;h3 id=&quot;new-font-stack&quot; tabindex=&quot;-1&quot;&gt;New font stack &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#new-font-stack&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I am now using &lt;a href=&quot;https://rsms.me/inter/&quot;&gt;Inter&lt;/a&gt; as the primary font for the website. It&#39;s a very readable font, and will provide consistency across platforms. I may be a Mac user, but that doesn&#39;t apply to everyone who reads this blog. It also seems to work well enough with my creative writing, but we will see if I need to change things around.&lt;/p&gt;
&lt;p&gt;I am also embracing serif fonts, and I went with the &lt;a href=&quot;https://fonts.adobe.com/fonts/source-serif-4&quot;&gt;Source Serif 4&lt;/a&gt; font for this. It will prove to be a good font for my longest-form creative writing in particular, where I often have characters writing letters as part of the story. Previously, I used an italicized version of Source Sans Pro for this purpose, a font I was not attached to but was the only one I felt working with using the original template, as that&#39;s the font it used.&lt;/p&gt;
&lt;p&gt;Finally, I swapped out Source Code Pro for &lt;a href=&quot;https://www.jetbrains.com/lp/mono/&quot;&gt;JetBrains Mono&lt;/a&gt;. Turthfully, JetBrains Mono has been a font I have been using since it came out in 2019, and I have carried it over to every code editor I use. It looks great on the code snippets on this website.&lt;/p&gt;
&lt;h3 id=&quot;new-color-scheme&quot; tabindex=&quot;-1&quot;&gt;New color scheme &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#new-color-scheme&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Out with the messy mix of colors. We&#39;re going simple: hues of blacks and whites, with a corresponding dark/light theme to switch. This time, light mode wasn&#39;t an afterthought - I consciously considered it in the design.&lt;/p&gt;
&lt;p&gt;I otherwise kept this simple. I was certainly inspired by brutalist design, and I am mostly happy with the choices I made. My biggest hope is that the site is more legible and readable, which is important as I take the blog more decisively in that direction.&lt;/p&gt;
&lt;h3 id=&quot;improved-code-syntax-highlighting&quot; tabindex=&quot;-1&quot;&gt;Improved code syntax highlighting &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#improved-code-syntax-highlighting&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I swapped out &lt;a href=&quot;https://www.11ty.dev/docs/plugins/syntaxhighlight/&quot;&gt;Eleventy&#39;s official syntax highlighting plugin&lt;/a&gt; for &lt;a href=&quot;https://shiki.style/&quot;&gt;Shiki&lt;/a&gt; via its support for &lt;a href=&quot;https://shiki.style/packages/markdown-it&quot;&gt;&lt;code&gt;markdown-it&lt;/code&gt;&lt;/a&gt;. There were a few hiccups getting this working, mostly boiling down to the fact that Eleventy only supports &amp;quot;after the fact&amp;quot; asynchronous configuration, and it didn&#39;t seem that Eleventy was consistently applying the Shiki plugin to the &lt;code&gt;markdown-it&lt;/code&gt; integration after initializing, but it seems to &lt;em&gt;mostly&lt;/em&gt; work.&lt;/p&gt;
&lt;p&gt;The most notable difference is that the theme will change in light mode to an appropriate light theme. Enjoy this little delight!&lt;/p&gt;
&lt;h3 id=&quot;get-dropped-off-on-the-blog&quot; tabindex=&quot;-1&quot;&gt;Get dropped off on the blog &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#get-dropped-off-on-the-blog&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;...since you are not here to read a short blurb about me, that&#39;s what the &lt;a href=&quot;https://steinborn.me/about/&quot;&gt;about page&lt;/a&gt; is for (or my &lt;a href=&quot;https://www.linkedin.com/in/astei&quot;&gt;LinkedIn&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;You get a list of eight posts to read, and you can go back in the archives as far back as you please. I am not going to waste your time.&lt;/p&gt;
&lt;h3 id=&quot;a-touch-of-animation&quot; tabindex=&quot;-1&quot;&gt;A touch of animation &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#a-touch-of-animation&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I added a few animations to the site, mostly to make the site feel more alive. There&#39;s a nice &amp;quot;slide-in&amp;quot; effect that I use mostly for post listing and the header to each post.&lt;/p&gt;
&lt;h2 id=&quot;whats-next&quot; tabindex=&quot;-1&quot;&gt;What&#39;s next? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#whats-next&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You&#39;ll see me continue to publish technical content here, but I&#39;m going to have an increased focus on creative writing as that is where my passion and interest is right now. I have quite a few stories in the works, and I am looking forward to sharing them with you.&lt;/p&gt;
&lt;p&gt;There will probably be more changes coming to this site, but I think the &amp;quot;big bang&amp;quot; is finally over with. I do have some next steps ahead:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;I need to queue up some more content, both creative and technical in nature. Keep an eye out...&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/11ty/eleventy/releases/tag/v3.0.0&quot;&gt;Eleventy v3&lt;/a&gt; came out.&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;update-late-on-october-22-2024&quot; tabindex=&quot;-1&quot;&gt;Update, late on October 22, 2024 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024-part-2/#update-late-on-october-22-2024&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The Eleventy v3 upgrade was very trivial. The upgrade helper plugin indicated I had no issues to fix. On top of that, the ability to export an asynchronous configuration function was helpful, since Shiki now consistently initializes correctly (previously, it was a bit of a crapshoot).&lt;/p&gt;
&lt;p&gt;I am pretty happy with my choice of static site generator, even if was a bit of a pain to configure at times. I had to migrate this site from Eleventy&#39;s first v0.x releases to v2 as I tried to do more complex things with it, and I&#39;m pleased that the v2 to v3 upgrade was so trivial.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>✍️ The Velocity Chronicles, Part 0</title>
		<link href="https://steinborn.me/posts/the-velocity-chronicles-part-0/"/>
		<updated>2024-08-31T00:00:00Z</updated>
		<id>https://steinborn.me/posts/the-velocity-chronicles-part-0/</id>
		<content type="html">&lt;p&gt;I have spent a lot of time in the time in the &lt;em&gt;Minecraft&lt;/em&gt; server scene. I&#39;ve been highly visible, in both my good and bad moments. But perhaps my most substantial and consequential project in that scene, specifically the &lt;a href=&quot;https://papermc.io/software/velocity&quot;&gt;Velocity&lt;/a&gt; Minecraft server proxy, is the most interesting story to tell.&lt;/p&gt;
&lt;p&gt;Velocity is notable today for being the proxy in front of a number of notable servers. Want to &lt;a href=&quot;https://app.minehut.com/&quot;&gt;play on a network of completely user generated content servers&lt;/a&gt;? Powered by Velocity. Even the infamous &lt;a href=&quot;https://en.wikipedia.org/wiki/2b2t&quot;&gt;2b2t server&lt;/a&gt; uses Velocity, having moved from Waterfall (which Velocity replaces).&lt;/p&gt;
&lt;p&gt;This is the first in a series of posts. Here, I will discuss the earliest days of Velocity, along with the first &amp;quot;trick&amp;quot; it used to improve performance over its contemporaries.&lt;/p&gt;
&lt;h2 id=&quot;what-exactly-is-a-minecraft-server-proxy&quot; tabindex=&quot;-1&quot;&gt;What exactly is a &lt;em&gt;Minecraft&lt;/em&gt; server proxy? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#what-exactly-is-a-minecraft-server-proxy&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Throughout this series, I am going to assume the reader:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;has a technical background&lt;/li&gt;
&lt;li&gt;has some understanding of what &lt;em&gt;Minecraft&lt;/em&gt; is, but has never played it&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Therefore I need to define some terminology. Let&#39;s start from the beginning:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;A &lt;em&gt;Minecraft server&lt;/em&gt; is the server-side component of &lt;em&gt;Minecraft&lt;/em&gt;. It allows players to interact with a world hosted on a remote machine instead of on their own computer. Popular &lt;em&gt;Minecraft&lt;/em&gt; server software options include the server provided by Mojang themselves (&amp;quot;vanilla&amp;quot;), &lt;a href=&quot;https://www.spigotmc.org/&quot;&gt;Spigot&lt;/a&gt;, and &lt;a href=&quot;https://papermc.io/&quot;&gt;Paper&lt;/a&gt;. Modding frameworks such as &lt;a href=&quot;https://fabricmc.net/&quot;&gt;Fabric&lt;/a&gt; and &lt;a href=&quot;https://neoforged.net/&quot;&gt;NeoForge&lt;/a&gt; also permit custom modifications to the &lt;em&gt;Minecraft&lt;/em&gt; server. We&#39;ll call this a &lt;em&gt;server&lt;/em&gt;, except where we need to disambiguate.&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;Minecraft&lt;/em&gt; server proxy sits between the &lt;em&gt;Minecraft&lt;/em&gt; player&#39;s client and a group of servers (typically referred to as a &amp;quot;network&amp;quot;). The proxy accepts connections from players and routes them to a given &lt;em&gt;Minecraft&lt;/em&gt; server on the backend. We&#39;ll call this just a &lt;em&gt;proxy&lt;/em&gt; from now on, except where we need to disambiguate.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;From this broad viewpoint, a &lt;em&gt;Minecraft&lt;/em&gt; server proxy is no different from a typical reverse proxy, such as NGINX or HAProxy. Just as a reverse proxy manages and routes traffic to web servers, a &lt;em&gt;Minecraft&lt;/em&gt; server proxy offers similar benefits: you don&#39;t have to expose each server to the Internet and it enables load balancing. As an example, take &lt;a href=&quot;https://hypixel.net/&quot;&gt;Hypixel&lt;/a&gt;, by and far the largest &lt;em&gt;Minecraft&lt;/em&gt; server (at one point, it had over 200,000 concurrent users). A single &lt;em&gt;Minecraft&lt;/em&gt; server simply cannot handle 200,000 players on at once, and so Hypixel uses a web of proxies and a lot of backend &lt;em&gt;Minecraft&lt;/em&gt; servers to host their games on.&lt;/p&gt;
&lt;p&gt;Here&#39;s an example topology of a &lt;em&gt;Minecraft&lt;/em&gt; server network (with some thanks to &lt;a href=&quot;https://claude.ai/&quot;&gt;Claude&lt;/a&gt; for drawing up the graph):&lt;/p&gt;
&lt;img alt=&quot;A Minecraft server network topology. Multiple players connect through a central proxy server, which directs them to different game modes. The network includes active servers for Hub (the main lobby), Survival, Factions, and Creative gameplay. Two players are in the Hub, while Survival, Factions, and Creative each have one player. An inactive Prison server is also part of the network but currently has no players.&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/ZpRljySEkc-901.svg&quot; width=&quot;901&quot; height=&quot;278&quot; /&gt;
&lt;p&gt;&lt;em&gt;Minecraft&lt;/em&gt; server proxies, though, have a few unique features that make them different from your regular every day reverse proxy:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The proxy can force the client to move to a completely different &lt;em&gt;Minecraft&lt;/em&gt; server. We&#39;ll dig into this later. But the end result: imagine a bastion server that was &lt;em&gt;completely invisible&lt;/em&gt;: you use SSH to log into the bastion, and it directs you to a server that you want by default, then you initiate a command that can seamlessly log you into a different SSH server behind the proxy, without ever closing the original SSH session.&lt;/li&gt;
&lt;li&gt;Most proxies support &lt;em&gt;plugins&lt;/em&gt;, which extend the functionality of the proxy. You get the full power of the runtime and language the proxy uses - for Velocity, that means &amp;quot;any JVM language you want&amp;quot; - &lt;a href=&quot;https://kotlinlang.org/&quot;&gt;Kotlin&lt;/a&gt; being a popular choice in the community, but you could also use Scala, Clojure, or just about any language that can compile to the JVM, as long as it can interoperate enough with Java that Velocity can load it. Plugins can be as simple or as complex as you want: as simple as a plugin to manage server punishments like bans to plugins that add protocol translation support (everything from &lt;a href=&quot;https://viaversion.com/&quot;&gt;permitting newer versions of Minecraft to connect to servers running older versions of Minecraft&lt;/a&gt;, to even adding &lt;a href=&quot;https://geysermc.org/&quot;&gt;support for &lt;em&gt;Minecraft: Bedrock Edition&lt;/em&gt; to &lt;em&gt;Minecraft: Java Edition&lt;/em&gt; servers&lt;/a&gt;.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The two giants in the &lt;em&gt;Minecraft&lt;/em&gt; server proxy scene are &lt;a href=&quot;https://www.spigotmc.org/wiki/bungeecord/&quot;&gt;BungeeCord&lt;/a&gt; and the subject of this series, Velocity.&lt;/p&gt;
&lt;h2 id=&quot;first-the-story-of-my-first-minecraft-server&quot; tabindex=&quot;-1&quot;&gt;First, the story of my first Minecraft server &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#first-the-story-of-my-first-minecraft-server&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The month is August 2013. I had just recently started high school. I learn of a Minecraft server network in need of developers (this is another fascinating topic I&#39;ll be sure to devote some time to eventually), and it looks like an interesting opportunity.&lt;/p&gt;
&lt;p&gt;It was a more innocent time. Here, I&#39;ll even provide you some period-accurate videos of the three minigames that were on offer at the time.&lt;/p&gt;
&lt;p&gt;First, here&#39;s MinerWare, a &lt;em&gt;Minecraft&lt;/em&gt; clone of &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Mario_Party&quot;&gt;Mario Party&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;embed-container&quot;&gt;&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/lJHbgyTS-js?si=8OuB-eAN1uLnhK2h&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;Next is Ender, a &lt;em&gt;Minecraft&lt;/em&gt; clone of the 2012 video game &lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Slender:_The_Eight_Pages&quot;&gt;Slender&lt;/a&gt;&lt;/em&gt;:&lt;/p&gt;
&lt;div class=&quot;embed-container&quot;&gt;&lt;iframe src=&quot;https://www.youtube-nocookie.com/embed/TU6TlZ_YDTU?si=E-qgTZ6LNJMwKjYg&quot; title=&quot;YouTube video player&quot; frameborder=&quot;0&quot; allow=&quot;accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share&quot; referrerpolicy=&quot;strict-origin-when-cross-origin&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;&lt;/div&gt;
&lt;p&gt;Finally, there was Mineshooter, a clone of &lt;em&gt;Call of Duty&lt;/em&gt; in &lt;em&gt;Minecraft&lt;/em&gt;. Unfortunately, I had trouble finding a good contemporary video of the &amp;quot;old&amp;quot; Mineshooter (since there was a later rework), but I did find &lt;a href=&quot;https://www.youtube.com/watch?v=H1b1sbSGzXI&quot;&gt;this video (voiceover in Russian, game text in English) which should give you a good idea of what the gameplay was like&lt;/a&gt;. There was also a separate server called GLDesert with a custom map, but this was detached from the rest of The Chunk in early 2014 in order to exclusively focus on minigames.&lt;/p&gt;
&lt;p&gt;In those days, you had only one real option for having a proxy, and it was BungeeCord. (There was also &lt;a href=&quot;https://github.com/LilyPad/GoLilyPad&quot;&gt;LilyPad&lt;/a&gt;, but it required more involved set up and eventually fell by the wayside.) The Chunk used BungeeCord, and it had some special unique needs. In late September 2013, I began developing plugins for BungeeCord, moving away briefly from my previous focus on the minigames side of the house.&lt;/p&gt;
&lt;p&gt;It didn&#39;t take me very long to make my first BungeeCord plugins: &lt;a href=&quot;https://github.com/minecrafter/AdvancedBungeeAnnouncer&quot;&gt;AdvancedBungeeAnnouncer&lt;/a&gt; and &lt;a href=&quot;https://github.com/minecrafter/redisbungee&quot;&gt;RedisBungee&lt;/a&gt;. The former made global announcements across the network more consistent, the latter synchronized the player count and player list across all the proxies. Since it was and to some degree still is a common practice to add load balancing to the proxies as well, &lt;em&gt;Minecraft&lt;/em&gt; server network owners would run multiple proxies on different machines, much like you would scale up an application vertically by launching more than one instance of it on a different machine. The trouble was that because each proxy was independent, they would only report the player count of those players connected to a specific proxy. This was the problem that RedisBungee solved: it put all of this data into Redis and did its best to &amp;quot;fake&amp;quot; making a series of independent proxies look like one large proxy.&lt;/p&gt;
&lt;p&gt;The Chunk wound up being a fairly successful network. It peaked at about 1,500 to 1,600 players online during early 2014, particularly the period between February 2014 and May 2014, but then went into decline. The network would eventually be absorbed into a different &lt;em&gt;Minecraft&lt;/em&gt; network in early 2016 - I would do some development work for that network before leaving.&lt;/p&gt;
&lt;p&gt;After that, I would wonder around quite a bit, taking on roles with different &lt;em&gt;Minecraft&lt;/em&gt; servers and companies (some quite large, some quite small). I did work ranging from standard plugin development to custom modifications of &lt;em&gt;Minecraft&lt;/em&gt; server software (mostly Paper). Perhaps most notable was the time I worked for &lt;a href=&quot;https://www.tebex.io/&quot;&gt;Tebex&lt;/a&gt; (back when it was called Buycraft), where I rewrote their &lt;em&gt;Minecraft&lt;/em&gt; server plugin and built their second ever integration with &lt;em&gt;Minecraft: Bedrock Edition&lt;/em&gt;. I had a brief detour into making &lt;em&gt;Minecraft&lt;/em&gt; server lists using Django, Celery, and PostgreSQL, and this is where I honed some of my web development skills (along with learning how to work with Python web frameworks). I enrolled in college. Eventually, I took on some work for Mineteria, which is where we&#39;ll pick up the story.&lt;/p&gt;
&lt;h3 id=&quot;well-andrew-how-involved-were-you-in-the-proxy-scene&quot; tabindex=&quot;-1&quot;&gt;Well, Andrew, how involved were you in the &amp;quot;proxy scene&amp;quot;? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#well-andrew-how-involved-were-you-in-the-proxy-scene&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Quite a long time, I suppose.&lt;/p&gt;
&lt;p&gt;What&#39;s often lost in the discussion, and has been a seemingly rich vein of confusion over the years, is the role I played in the &lt;a href=&quot;https://docs.papermc.io/waterfall&quot;&gt;Waterfall&lt;/a&gt; project. I founded this project in January 2016 as an effort to lower the bar to adding contributions to BungeeCord. It used the same patching system as Spigot and Paper, and included a number of patches to improve BungeeCord&#39;s behavior, add new features, and included some performance improvements. People came and went, but I was the only real constant until I handed the project over to the Paper team in September 2018 to focus more on Velocity.&lt;/p&gt;
&lt;p&gt;The sad reality with Waterfall is that we were basically kind of stuck with the lowest common denominator. &lt;a href=&quot;https://github.com/electronicboy&quot;&gt;electronicboy&lt;/a&gt; would always relay the tale of trying to add improved scoreboard support to Waterfall (instead of a very raw API that BungeeCord exposed at the time by allowing plugins to just send packets if they wanted, a practice very quickly banished from the Velocity plugin API on day one) and dealing with broken plugins as a result, effectively killing any desire to make Waterfall a better BungeeCord in any way that mattered. In other words, a &lt;em&gt;Minecraft&lt;/em&gt; manifestation of &lt;a href=&quot;https://www.hyrumslaw.com/&quot;&gt;Hyrum&#39;s law&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;With a sufficient number of users of an API, it does not matter what you promise in the contract: all observable behaviors of your system will be depended on by somebody.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;After all of that, there was increased conviction to build an alternative proxy instead. This evolved into Velocity.&lt;/p&gt;
&lt;h2 id=&quot;you-said-you-d-discuss-another-minecraft-network-too&quot; tabindex=&quot;-1&quot;&gt;You said you&#39;d discuss another Minecraft network, too? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#you-said-you-d-discuss-another-minecraft-network-too&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In May 2018, after doing some initial web development work for Mineteria, I was enlisted to work on the actual Minecraft server. The server had a go-live date in July 2018, so I was thrown onto the project fairly late - development had previously began in early 2017. Like The Chunk and many &lt;em&gt;Minecraft&lt;/em&gt; networks before it, it also used BungeeCord.&lt;/p&gt;
&lt;p&gt;The server was pretty unique as it used Kubernetes as its native control plane. It was amongst the earliest examples of this, and so we&#39;d run into a lot of rough edges. Kubernetes on bare metal was not as mature back then, so our production set up wound up being run on &lt;a href=&quot;https://cloud.google.com/kubernetes-engine?hl=en&quot;&gt;Google Kubernetes Engine&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Those of you in the audience familiar with &lt;em&gt;Minecraft&lt;/em&gt; servers would immediately know that something is wrong here. Other people in the audience may be puzzled: isn&#39;t Google Cloud a pretty standard commodity cloud provider? They offer all the services you&#39;d expect, just like any other cloud provider.&lt;/p&gt;
&lt;h3 id=&quot;swiping-left-on-the-cloud&quot; tabindex=&quot;-1&quot;&gt;Swiping left on the cloud &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#swiping-left-on-the-cloud&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Proxies have two primary characteristics:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;They need to do a lot of I/O-intensive work, which means &lt;em&gt;lots&lt;/em&gt; of system calls. This was all after the impact of Spectre/Meltdown, which meant that everyone likely took massive performance penalties, which were further magnified by running inside of a virtual machine.&lt;/li&gt;
&lt;li&gt;Part of the proxy&#39;s job is compressing packets destined for players, and this process is very resource-intensive. Worse, we cannot just serve pre-compressed assets like a web server might do - we have to compress packets on the fly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This became apparent when we launched the server on July 1st. The servers did collapse under their weight and we had to add additional resources to keep things stable. We realized that for the proxy, we would need to run absurdly large instances (or scale out the proxy), in essence throwing a lot of money at the problem. That&#39;s what we did, for a while at least. But we knew that the persistently high CPU usage was not sustainable (we were seeing well over one or two cores used by a small number of players!) and so we sought a third option.&lt;/p&gt;
&lt;p&gt;It was also in July 2018 when I was on the PaperMC Discord complaining about BungeeCord, primarily around its development process (a cathedral) and its almost fanatical pursuit of backwards compatibility. At that time, I was experimenting with a fork of BungeeCord I had created, &lt;a href=&quot;https://github.com/astei/LibertyCord&quot;&gt;LibertyCord&lt;/a&gt;, seeking to make more radical changes. At the time, the owners of Mineteria were skeptical of Velocity, but I pressed on anyway. With encouragement from &lt;a href=&quot;https://github.com/electronicboy&quot;&gt;electronicboy&lt;/a&gt;, &lt;a href=&quot;https://github.com/kashike&quot;&gt;kashike&lt;/a&gt;, and even &lt;a href=&quot;https://github.com/aikar&quot;&gt;Aikar&lt;/a&gt;, I began work on Velocity. Progress did eventually get to the point where Mineteria made the move to Velocity starting in November 2018, and I could actually start &amp;quot;eating my own dogfood&amp;quot;.&lt;/p&gt;
&lt;h2 id=&quot;velocity-is-born&quot; tabindex=&quot;-1&quot;&gt;Velocity is born &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#velocity-is-born&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first commit to Velocity was on &lt;a href=&quot;https://github.com/PaperMC/Velocity/commit/666d07e2a8c26b35a68c7c711f83d2193b27c749&quot;&gt;July 24th, 2018&lt;/a&gt;. This initial version of Velocity didn&#39;t have much functionality. In fact, it was just barely capable of responding to server list ping packets from the Minecraft client. Still, it was pointing in the right direction, and we just needed to get Velocity relaying packets across the network.&lt;/p&gt;
&lt;p&gt;By July 27th, I had something that you could call a &amp;quot;proof of concept&amp;quot;: a player could connect to a Velocity server, be connected successfully to the proxy, which would open a connection to a specific server (&lt;code&gt;localhost:25565&lt;/code&gt;), and be able to switch to a different server (&lt;code&gt;localhost:25566&lt;/code&gt;). Furthermore, we had implemented the first &amp;quot;trick&amp;quot; Velocity used to gain an edge over BungeeCord and LilyPad. But before we do, we&#39;ll need to discuss a few more concepts.&lt;/p&gt;
&lt;h3 id=&quot;who-are-you-calling-me&quot; tabindex=&quot;-1&quot;&gt;Who are you calling, me? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#who-are-you-calling-me&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;A typical video game has entities contained within the game world. An entity is simply a object that exists in a given world.&lt;/p&gt;
&lt;p&gt;In a single-player game, we might be able to store direct memory references to other entities in the world. Suppose we were making a very simple tower defense game where we have turrets and enemies and we need to tick them (update them) on a periodic basis. We might refer to the entities in the world in code as follows:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-csharp&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Turret&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#9CDCFE&quot;&gt;_turrets&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;  private&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; List&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Enemy&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#9CDCFE&quot;&gt;_enemies&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But what if we are playing over the network? It would make no sense (and be a security risk) to pass around memory pointers. Instead, what we can do is assign an ID to each entity in the world, and refer to the entity by this ID alone when referring to a specific entity over the network.&lt;/p&gt;
&lt;p&gt;So far, so good, right?&lt;/p&gt;
&lt;p&gt;Here&#39;s the catch: we can move the player to a different server, &lt;em&gt;but we can&#39;t tell the Minecraft server to use a specific entity ID&lt;/em&gt;. Furthermore, if we just send packets referring to the connected player with a different entity ID than the one the client believes it has, then all sorts of interesting issues can occur on both the client and server sides. To add further complications, the tricks that proxies do are &lt;em&gt;technically&lt;/em&gt; not supported by Mojang, but are only tolerated because proxies are very popular in the server community!&lt;/p&gt;
&lt;p&gt;That said, we have two options:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The proxy can rewrite &lt;em&gt;every&lt;/em&gt; packet that contains an entity ID. Should it find that it needs to rewrite a packet, it will copy all the fields in the packet over. If it finds the server-side entity ID for the player in a packet bound for the player, it will rewrite it to include the entity ID that the client believes it uses. It also does this in the reverse direction for packets originating from the player towards the server they are connected to.&lt;/li&gt;
&lt;li&gt;Or, you can try to make the client use a different entity ID, and dispense with the need to rewrite packets entirely.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;BungeeCord and LilyPad opted to rewrite packets. Velocity chose the path of telling the client to use a different entity ID.&lt;/p&gt;
&lt;h3 id=&quot;so-how-do-we-fool-the-client&quot; tabindex=&quot;-1&quot;&gt;So, how do we fool the client? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#so-how-do-we-fool-the-client&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;First, let&#39;s understand what Velocity is sending the client. First, here is how Velocity told the client to change entity IDs and load the new world:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    public&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt; void&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; handleBackendJoinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;JoinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; joinGame) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (!spawned) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            spawned = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            currentDimension = &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDimension&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;            player&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(joinGame);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;            player&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(joinGame);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;            int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; tempDim&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDimension&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;() == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; ?&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; -&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt; 0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;            player&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; Respawn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(tempDim, &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDifficulty&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getGamemode&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getLevelType&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;            player&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getConnection&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;write&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; Respawn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDimension&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDifficulty&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getGamemode&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getLevelType&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            currentDimension = &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;joinGame&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;getDimension&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It should first be noted that this continues to be the base for &lt;a href=&quot;https://github.com/PaperMC/Velocity/blob/b14e7e651eab8111da58bbc76b103247d1541fcd/proxy/src/main/java/com/velocitypowered/proxy/connection/client/ClientPlaySessionHandler.java#L311&quot;&gt;Velocity&#39;s current implementation&lt;/a&gt;, which is more complex (notably, we can now omit one of the &lt;code&gt;Respawn&lt;/code&gt; packets starting in Minecraft 1.16), but the fundamental logic remains the same.&lt;/p&gt;
&lt;p&gt;What does this code do? First, we need to explain a few &lt;em&gt;Minecraft&lt;/em&gt; packets and how the client responds to them:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The &lt;code&gt;JoinGame&lt;/code&gt; packet is sent by the server when it indicates that the server has spawned the player into the server&#39;s world. It is sent very early after the player&#39;s connection to the server enters the &lt;code&gt;PLAY&lt;/code&gt; state (in other words, when the player has just logged into the server).&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Respawn&lt;/code&gt; packet it sent by the server when a player is moved to another dimension (i.e. going from the Overworld to the Nether), or if the player is respawning after dying.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Now we can explain what Velocity is doing:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;If this is the first server the player has connected to during this session, indicate as such and send the packet plain. There&#39;s nothing for us to do.&lt;/li&gt;
&lt;li&gt;Otherwise:
&lt;ul&gt;
&lt;li&gt;We send the original, unmodified &lt;code&gt;JoinGame&lt;/code&gt; packet from the new server to the client.&lt;/li&gt;
&lt;li&gt;The client drops its current state of the world, and crucially, &lt;em&gt;sets its entity ID to the one we sent&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;We send a &lt;code&gt;Respawn&lt;/code&gt; packet, set to a different dimension. At the time, the &lt;em&gt;Minecraft&lt;/em&gt; client did not behave correctly when we respawn the client into the &lt;em&gt;current&lt;/em&gt; dimension immediately after sending &lt;code&gt;JoinGame&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;We send another &lt;code&gt;Respawn&lt;/code&gt; packet to bring the player into the correct dimension.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;The server switch is done, and packets can stop flowing from the old server (if any) and start flowing from the new server.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This solves a couple of issues:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;It makes the codebase considerably simpler. Instead of maintaining complex, non-trivial packet rewriting logic, we could focus on other important attributes such as extensibility and performance of the overall networking pipeline. It also means that the code is less buggy, since we know that the client can update the entity ID it uses, so we don&#39;t need to worry about missing a packet we were supposed to rewrite.&lt;/li&gt;
&lt;li&gt;It made updating Velocity to work with newer versions of Minecraft &lt;em&gt;much&lt;/em&gt; easier. Some versions of Minecraft were supported simply by telling Velocity that it needs to recognize a new protocol version number.&lt;/li&gt;
&lt;li&gt;It worked with every version of &lt;em&gt;Minecraft&lt;/em&gt; that Velocity supports, from Minecraft 1.7.2 to 1.21 - nearly 11 years of compatibility.&lt;/li&gt;
&lt;li&gt;It causes less problems with mods. Entity ID rewriters don&#39;t know how to rewrite mod packets containing entity IDs, so these mods would simply break on a proxy that uses them.&lt;/li&gt;
&lt;li&gt;Perhaps most importantly, since we don&#39;t need to examine these packets, the proxy does essentially no processing on the packets except for uncompressing the packet from the server if needed, determining that no action is necessary, and forwarding it onto the client (compressing and encrypting the packet as needed).&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Of course, this wouldn&#39;t be the only trick Velocity employed in the service of performance, but it was amongst the first.&lt;/p&gt;
&lt;h2 id=&quot;thats-all-for-this-installment&quot; tabindex=&quot;-1&quot;&gt;That&#39;s all for this installment &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/the-velocity-chronicles-part-0/#thats-all-for-this-installment&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;With this post, I hope I&#39;ve began to lay down the foundations for how Velocity came to be. I&#39;ve introduced you to some key concepts along with three of the formative moments in my &lt;em&gt;Minecraft&lt;/em&gt; journey. I&#39;ve also given you an introduction to the earliest days of Velocity.&lt;/p&gt;
&lt;p&gt;In the next installment, we&#39;ll discuss some more of the early days of Velocity:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The plugin API.&lt;/li&gt;
&lt;li&gt;The lead up to, first the deployment of Velocity on Mineteria, and then Velocity 1.0.0.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Stay tuned for more. There&#39;s a lot of stories for me to tell, as these were some of my formative years as a software engineer. (Trust me, going from &lt;em&gt;Minecraft&lt;/em&gt; modding to fintech is a very unexpected turn of events!)&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>🎨 Sprucing up my website for 2024</title>
		<link href="https://steinborn.me/posts/website-touch-up-2024/"/>
		<updated>2024-08-24T00:00:00Z</updated>
		<id>https://steinborn.me/posts/website-touch-up-2024/</id>
		<content type="html">&lt;p&gt;Well, it sure has been a while since I last updated this website back in the far away time of... &lt;a href=&quot;https://steinborn.me/posts/a-2022-dispatch/&quot;&gt;October 2022&lt;/a&gt;. Naturally this means I now need to go in and actually give it a refresh, especially as I am trying to make this website a little bit more than a blog that gets an article roughly semi-annually, and start exploring doing more creative writing along with deeper technical reads.&lt;/p&gt;
&lt;h2 id=&quot;first-steps-first&quot; tabindex=&quot;-1&quot;&gt;First steps first &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024/#first-steps-first&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I did give brief contemplation to a complete overhaul of the website. I would continue to use &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt; as it&#39;s a reasonably fast site generator, and I&#39;ve already circulated through WordPress, Ghost, Jekyll, Hugo, and now Eleventy in the past and didn&#39;t want to go explore new site generators (or, &lt;em&gt;gasp&lt;/em&gt;, go write my own).&lt;/p&gt;
&lt;p&gt;In fact, my original plan &lt;em&gt;was&lt;/em&gt; to go rework this entire website with the hot new stuff, &lt;a href=&quot;https://tailwindcss.com/&quot;&gt;Tailwind&lt;/a&gt;, and retire my very boring and excessively modified HTML5 UP template that was a wonderful base to work with in 2014 but downright not even worthy of a yawn in 2024. But I didn&#39;t have the luxury of time to wrap myself around Tailwind, which is a very much a &lt;em&gt;fundamentally different&lt;/em&gt; way to view CSS. I do see the value in it, though, and I will probably adopt it for future projects (if I&#39;m able to get that far, that is).&lt;/p&gt;
&lt;p&gt;So I decided just to press on with updating my existing theme. To be honest, I was simply not happy with the customizations I made. There was some stuff that was just outright broken or difficult to see, and of course, the website very conspiciously lacked support for dark mode.&lt;/p&gt;
&lt;h2 id=&quot;tweaking-the-theme&quot; tabindex=&quot;-1&quot;&gt;Tweaking the theme &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024/#tweaking-the-theme&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The first thing you&#39;ll notice is that there&#39;s a lot less spacing all over the place, and the header is much slimmer than it once was. I&#39;ve decided to bite the bullet and adopt a widescreen view by default to improve readability and allow me to write more information-dense pages.&lt;/p&gt;
&lt;p&gt;The second thing you&#39;ll notice: this website now supports dark mode. There is a nice transition from the light theme to the dark theme, and there&#39;s a button to change the theme as you please. When you do, the background will alternate: in light mode, you get the classic shot of the Brooklyn Bridge that has been there since late 2022, and in dark mode, you get a black-and-white version of the Miami skyline from Wynwood, from a work trip I took earlier this year:&lt;/p&gt;
&lt;picture&gt;
  &lt;source type=&quot;image/webp&quot; srcset=&quot;https://steinborn.me/img/generated/UytH3tlM8v-912.webp 912w, https://steinborn.me/img/generated/UytH3tlM8v-1280.webp 1280w, https://steinborn.me/img/generated/UytH3tlM8v-4032.webp 4032w&quot; sizes=&quot;(max-width: 980px) 100vw, (max-width: 1280px) 100vw, 100vw&quot; /&gt;
  &lt;source type=&quot;image/jpeg&quot; srcset=&quot;https://steinborn.me/img/generated/UytH3tlM8v-912.jpeg 912w, https://steinborn.me/img/generated/UytH3tlM8v-1280.jpeg 1280w, https://steinborn.me/img/generated/UytH3tlM8v-4032.jpeg 4032w&quot; sizes=&quot;(max-width: 980px) 100vw, (max-width: 1280px) 100vw, 100vw&quot; /&gt;
  &lt;img alt=&quot;March 28, 2024: A view of Wynwood and the Downtown/Brickell skyline&quot; loading=&quot;lazy&quot; decoding=&quot;async&quot; src=&quot;https://steinborn.me/img/generated/UytH3tlM8v-912.jpeg&quot; width=&quot;4032&quot; height=&quot;3024&quot; /&gt;
&lt;/picture&gt;
&lt;p&gt;The third thing you&#39;ll notice is that a lot of little tiny nits (especially with regard to responsiveness) were fixed. Finally, you&#39;ll notice that the post headers now look a lot more &amp;quot;normal&amp;quot; rather than being a giant &lt;code&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; with the date and tags underneath.&lt;/p&gt;
&lt;p&gt;Other than that, I didn&#39;t fundamentally alter the base HTML5 UP template. It still looks largely the same, with the exception of removing a bunch of the 2014-era JavaScript that the template came bundled with (it even came with jQuery, and it is mildly amusing that &lt;a href=&quot;https://blog.jquery.com/2024/07/17/second-beta-of-jquery-4-0-0/&quot;&gt;jQuery is still under active development&lt;/a&gt;). In fact, the JavaScript I added for the theme switcher is the only JavaScript I&#39;ve since added, and this site should work just fine even with JavaScript disabled (but then you&#39;re getting the light theme). I didn&#39;t even change the font: it&#39;s still the venerable Source Sans Pro (although I did look at changing it, every alternative I looked at just had a different vibe I didn&#39;t like.)&lt;/p&gt;
&lt;h2 id=&quot;so-whats-next-for-you&quot; tabindex=&quot;-1&quot;&gt;So, what&#39;s next for you? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/website-touch-up-2024/#so-whats-next-for-you&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In the short term, I hope to have some more content here and make this blog more active than it is right now. I&#39;ve got a few things kicking around: toy projects using whatever I&#39;m interested in learning, some creative writing I&#39;ve been working on intermittently (mostly short stories), potentially some stories from Ramp that aren&#39;t quite worthy of a post on &lt;a href=&quot;https://engineering.ramp.com/&quot;&gt;our engineering blog&lt;/a&gt;, and some other assorted topics as they present themselves to me.&lt;/p&gt;
&lt;p&gt;Until then, here is a &lt;a href=&quot;https://steinborn.me/posts/questions-from-a-worker-who-reads-2024-edition&quot;&gt;2024 re-imagination of Bertolt Brecht&#39;s 1935 poem &amp;quot;Questions From a Worker Who Reads&amp;quot;&lt;/a&gt;, and a snippet from a story I am currently working on.&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;[...] Earth was a far, far cry from what it had once been. Once the cradle of human civilization, it now sat abandoned, a museum in all but name. Officially, it was called “neutral ground”, but everyone who had an interest in coming here was here to study the history of the planet or its former inhabitants. Oh, what a far cry from Wista, home to thriving metropolises and the National Research University of the Arctarian System, where she was a history professor specializing in 20th and 21st-century computing technology. Her maps indicated that she was in the vicinity of what was once Dulles International Airport, one of the airports serving what was the United States’s capital city of Washington, D.C. She immediately sized up the location. The layout of the buildings and the sprawling and curvy road network were immediately recognizable as typical of the suburban development of the United States in that time frame. In this part of the country, too, humanity built up large numbers of what were called “data centers” here. Dr. Mahone looked at her watch. The compute power it had probably dwarfed all the compute power this sad building had once hosted. How much has changed in 28 centuries! [...]&lt;/p&gt;
&lt;/blockquote&gt;
</content>
	</entry>
	
	<entry>
		<title>📚 A 2023 dispatch</title>
		<link href="https://steinborn.me/posts/a-2023-dispatch/"/>
		<updated>2024-08-12T00:00:00Z</updated>
		<id>https://steinborn.me/posts/a-2023-dispatch/</id>
		<content type="html">&lt;p&gt;I would&#39;ve written about 2023 some time ago, but quite a few developments happened in my life... and so, I held off for a bit. But now I am back to tell the story of 2023. It was probably one of the most stressful years in my life.&lt;/p&gt;
&lt;h2 id=&quot;dis-is-one-half&quot; tabindex=&quot;-1&quot;&gt;Dis is one half. &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2023-dispatch/#dis-is-one-half&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;January 1st, 2023 comes and my first order of business was to move apartments! My old building was not particularly well-maintained, looked ugly on the outside, had no air conditioning, had lead service pipes, and for the last month I lived there, had no internet, forcing me to either go out somewhere where there was Wi-Fi or tether to my cellphone. This was not great considering I had signed up to be on-call for the holiday. A wonderful first apartment for you to have in the city, huh?&lt;/p&gt;
&lt;p&gt;So starting in January, I went out and started apartment hunting. I narrowed it down to four potential options, applied for all of them, and was accepted for all of them as well. I ultimately chose an apartment located in a recently-built mixed-use apartment complex that would place me one stop closer to Manhattan.&lt;/p&gt;
&lt;p&gt;Then I had to go pack my things. Not fun. At least in New York City, everyone moves so often that the moving market is extremely competitive. At least it takes the sting out of the high rent.&lt;/p&gt;
&lt;p&gt;Some time later, I move into my new place. It&#39;s nice. I have my own fiber connection with all the works, even IPv6. There&#39;s AC that works. The building is maintained pretty well. The super is generally on top of things. I could stay here.&lt;/p&gt;
&lt;p&gt;I don&#39;t have much time to settle down. Offsite in Miami with the Ramp Bill Pay team. This is where I had a severe burnout episode crop up. I survive the offsite and immediately take a week off work, mostly to visit museums in New York. I enjoyed the experience. But when I returned, I had to decide whether or not I was going to leave the company I&#39;d joined more than a year ago, keep my current position, or try to make the situation on my current team work for me.&lt;/p&gt;
&lt;p&gt;I tried the second option for a bit. It was comforting, I had no real qualms with the work, and I had reason to believe I could become an effective tech lead within payments in due time.&lt;/p&gt;
&lt;p&gt;Silicon Valley Bank collapsed. I had to go jump into a war room meeting on a Friday to attempt to keep the spread of potential issues confined. In that one conference room inside a WeWork, I wrote scripts that would cancel payments to SVB and delay internal settlement of payments already initiated from SVB. We did not even know what the federal response would be. All of this was, thankfully, not necessary. The federal government de-facto nationalized Silicon Valley Bank and Signature Bank and took further actions to forestall a larger crisis.&lt;/p&gt;
&lt;p&gt;But for a time, it was rejuvenating, so I worked on launching support for Ramp&#39;s freshly-acquired money transmission licenses within our payments platform and making other improvements. I got promoted from merely &amp;quot;software engineer&amp;quot; to senior software engineer! For a while, it goes great. I&#39;m still having the conversations about moving teams, though, but it&#39;s at a slightly lower priority while I delivered for my existing team.&lt;/p&gt;
&lt;p&gt;I talked with Patrick Anderson, head of Ramp&#39;s core engineering team at the time, a few times as I evaluated my options. He saw some opportunities for me to either move to our product security engineering function or move into spend management engineering (the meat and potatoes of Ramp). I rejected product security since while I had aptitude for it, I did not feel like the work would be sufficiently challenging for me. After further discussions with relevant tech leads, I was leaning towards the closest thing I had for my team&#39;s equivalent on the spend management side of the house: spend platform.&lt;/p&gt;
&lt;p&gt;Then First Republic Bank collapsed. Then I was dropped several last-minute requirements for our money transmission launch. At that point, I pull the trigger and decide to leave teams. Over the following 6 months, effectively all of Ramp&#39;s original Bill Pay and Payments team had dissolved, and was replaced by an entirely new team.&lt;/p&gt;
&lt;p&gt;Thus we get to June 2023, and day 1 on my new team.&lt;/p&gt;
&lt;h2 id=&quot;my-spend-platform-era&quot; tabindex=&quot;-1&quot;&gt;My Spend Platform era &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2023-dispatch/#my-spend-platform-era&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It begins innocently enough. I&#39;m introduced to my teammates and a new manager. I had already established a rapport with the tech lead, who was already aware that I could bring valuable skills to the table. With my entry, the team counted five backend engineers, zero designers, and one product manager.&lt;/p&gt;
&lt;p&gt;If I left it at that, that would&#39;ve been a generously happy ending to a stressful first year of the year, right?&lt;/p&gt;
&lt;p&gt;I wish it got better, but it doesn&#39;t.&lt;/p&gt;
&lt;p&gt;Within the next three months, a lot would happen:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Engineers were forced to pause most of their work and focus on tech debt for a single sprint.&lt;/li&gt;
&lt;li&gt;Our tech lead goes on paternity leave.&lt;/li&gt;
&lt;li&gt;One of teammates would be fired.&lt;/li&gt;
&lt;li&gt;My manager would be shown the door, and our tech lead, who doesn&#39;t like managerial work, is forced to take on managerial work.&lt;/li&gt;
&lt;li&gt;My mother and my grandmother&#39;s health takes a turn for the worse. (Both would die in early 2024.)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The end of the year proved even more stressful. I had to pay for a last-minute flight to Atlanta and hotel for Thanksgiving week since my mother was in the hospital. I&#39;d also volunteered to be on-call for the end-of-year holidays as well.&lt;/p&gt;
&lt;p&gt;I would also be able to focus on a couple of important projects, but ultimately I would say that the time I spent that year was a bit of a wash. I didn&#39;t have too much trouble onboarding, I just had a bunch of unfortunate circumstances arise that made the year much less successful.&lt;/p&gt;
&lt;p&gt;To be honest, I&#39;m lucky I made it out of the other side without wanting to quit.&lt;/p&gt;
&lt;h2 id=&quot;thats-all-for-now&quot; tabindex=&quot;-1&quot;&gt;That&#39;s all for now &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2023-dispatch/#thats-all-for-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The story of 2024 is yet to be written, but it has been proving to be a mix of both a dumpster fire and one of the better years I&#39;ve had thus far. I&#39;ll see you in 2025...&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>🕯️ Going back home, a tapestry of time</title>
		<link href="https://steinborn.me/posts/going-back-home-tapestry-of-time/"/>
		<updated>2024-02-21T00:00:00Z</updated>
		<id>https://steinborn.me/posts/going-back-home-tapestry-of-time/</id>
		<content type="html">&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;A sojourn looms, heavy and stark&lt;br /&gt;
Homeward bound, today I shall embark,&lt;br /&gt;
Life does not pause for the mourner under this dome&lt;br /&gt;
But all I seek is home.&lt;/p&gt;
&lt;p&gt;Security cleared, what a tiresome charade&lt;br /&gt;
Scanners and conveyors, a pat-down, what a bother.&lt;br /&gt;
With each climb of the escalator,&lt;br /&gt;
Towards the gate I go, burdened by time.&lt;/p&gt;
&lt;p&gt;Chaos reigns, the cacophony unfolds&lt;br /&gt;
Amidst the crowd, solace a rare sight.&lt;br /&gt;
At least my coffee is quite bold,&lt;br /&gt;
My only champion is the sun’s light.&lt;/p&gt;
&lt;p&gt;A whispered prayer, for safety’s embrace,&lt;br /&gt;
To one funeral I head, another I cannot face.&lt;br /&gt;
In the sky, between lands, my fears are sown,&lt;br /&gt;
Stuck in this tube, my thoughts are my own.&lt;/p&gt;
&lt;p&gt;The ground greets me, a bittersweet peace,&lt;br /&gt;
Nearly home, but the ache won’t cease.&lt;br /&gt;
What cost is home, what price for this flight?&lt;br /&gt;
I seek solace, but it is far out of sight.&lt;/p&gt;
&lt;p&gt;Past this bridge, its corridors long&lt;br /&gt;
Towards where my memories belong.&lt;br /&gt;
My life and my home torn,&lt;br /&gt;
Mourning also the aggrieved and forlorn.&lt;/p&gt;
&lt;p&gt;The roads whisper tales of what was once a place,&lt;br /&gt;
Before the relentless march of what counted as progress,&lt;br /&gt;
Did they mourn, as I do, for what was erased?&lt;br /&gt;
Communities displaced, lives regressed.&lt;/p&gt;
&lt;p&gt;A man, his power, and his dream,&lt;br /&gt;
Who oversaw the landscapes being reshaped.&lt;br /&gt;
Did he weep as the night beamed?&lt;br /&gt;
These places, we could never have replaced.&lt;/p&gt;
&lt;p&gt;In a town forgotten by time, I arrive,&lt;br /&gt;
The locomotives whistled and spewed their exhaust,&lt;br /&gt;
I go to the chapel, at my own high cost,&lt;br /&gt;
For we seek solace in the stories that survive.&lt;/p&gt;
&lt;p&gt;A confluence of pasts, a tapestry of ties,&lt;br /&gt;
A clear sky, a cold day, but our shared sorrow still lies.&lt;br /&gt;
In this gathering, our grief finds a voice,&lt;br /&gt;
In remembering, together, we somewhat rejoice.&lt;/p&gt;
&lt;p&gt;Journey’s end, and I can only weep,&lt;br /&gt;
Closure elusive, in the town time forgot,&lt;br /&gt;
Never mind in the city that doesn’t sleep.&lt;br /&gt;
Life does not pause for the mourner in the gates.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id=&quot;context&quot; tabindex=&quot;-1&quot;&gt;Context &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/going-back-home-tapestry-of-time/#context&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;This poem is a reflection on two deaths in my family: my grandmother and my mother. In both cases, the funerals took place in rural railroad towns in the South, specifically those on the route between Atlanta and Birmingham.&lt;/p&gt;
&lt;p&gt;I flew out of LaGuardia Airport in New York City and transited both Hartsfield-Jackson Atlanta International Airport both times.&lt;/p&gt;
&lt;p&gt;I miss you, Bonnie and Natalie. At least you join Rex and Karl. Love from the city that never sleeps, where you are all proud that I&#39;ve made something of myself.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>🐦🔥 Misadventures with Phoenix Framework</title>
		<link href="https://steinborn.me/posts/misadventures-with-phoenix-framework/"/>
		<updated>2023-12-28T00:00:00Z</updated>
		<id>https://steinborn.me/posts/misadventures-with-phoenix-framework/</id>
		<content type="html">&lt;p&gt;Back in 2020, before the pandemic really hit, I started working on two projects built on top of &lt;a href=&quot;https://workers.cloudflare.com/&quot;&gt;Cloudflare Workers&lt;/a&gt;. One of those projects was the Mineteria Store, which jammed together server-side React running on top of an environment that server-side React didn&#39;t exactly run on at the time mixed with traditional client-side rendering, and a service to render Minecraft avatars called &lt;a href=&quot;https://crafthead.net/&quot;&gt;Crafthead&lt;/a&gt;, now maintained by Nodecraft. (Funny enough, the Mineteria Store is, to my knowledge, the only deployment of Elixir that was remotely close to the Minecraft server scene. What a time that was.)&lt;/p&gt;
&lt;p&gt;But I have a lot of holiday downtime and I wasn&#39;t exactly doing much of &lt;em&gt;anything&lt;/em&gt;. Plus, at Ramp, I am now part of the same team that works on our authorizer service (something legendary in its own right: written by &lt;a href=&quot;https://morepablo.com/&quot;&gt;Pablo Meier&lt;/a&gt;, who may not be with Ramp any more, &lt;a href=&quot;https://engineering.ramp.com/elixir-at-ramp&quot;&gt;but it is the subject of this classic blog post&lt;/a&gt;, and the authorizer service continues to faithfully handle millions of authorizations per day with the power of Elixir).&lt;/p&gt;
&lt;p&gt;So let&#39;s do the natural thing and rewrite Crafthead in Elixir...&lt;/p&gt;
&lt;h2 id=&quot;but-not-quite&quot; tabindex=&quot;-1&quot;&gt;...but not quite! &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#but-not-quite&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Crafthead is actually divided into two components:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The actual application, written in fairly standard TypeScript aside from some extensions to the runtime done by Cloudflare. It is basically a Service Worker running in a non-browser environment.&lt;/li&gt;
&lt;li&gt;A Rust library responsible for rendering images. There is a shim API that handles the JS-to-Rust translation, and this is ultimately compiled into WebAssembly.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The main reason for this was simple: I knew more TypeScript/JavaScript than I did Rust, and I wasn&#39;t excited about the prospect of writing a Worker entirely in Rust. (Also worth noting that you couldn&#39;t have even written a Worker entirely in a language that compiled to WebAssembly until Cloudflare added support for Liftoff tiering, since on a cold boot, the WebAssembly would &lt;em&gt;have&lt;/em&gt; to go through TurboFan compilation, a compiler not known for being fast.)&lt;/p&gt;
&lt;p&gt;Along the way, Crafthead makes use of Cloudflare Workers KV as its primary datastore. This is essentially a Memcached-like API with some extra bells and whistles we won&#39;t care about. We can substitute it for Memcached, Redis, a relational database, or &lt;a href=&quot;https://www.erlang.org/doc/man/ets.html&quot;&gt;an ETS table&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;so-whats-our-strategy&quot; tabindex=&quot;-1&quot;&gt;So what&#39;s our strategy? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#so-whats-our-strategy&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It&#39;s not really hard to deduce a strategy from here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;The actual application, written in Elixir, and built on top of the &lt;a href=&quot;https://www.phoenixframework.org/&quot;&gt;Phoenix Framework&lt;/a&gt;. Phoenix provides essentially everything including the kitchen sink.&lt;/li&gt;
&lt;li&gt;We will need a cache: we&#39;ll use &lt;a href=&quot;https://hexdocs.pm/nebulex/Nebulex.html&quot;&gt;Nebulex&lt;/a&gt; to handle this.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/wojtekmach/req&quot;&gt;Req&lt;/a&gt; reminds me a lot of &lt;code&gt;python-requests&lt;/code&gt; and is easy to add (it&#39;s built on top of Finch and Mint), so we will use this to call the Mojang API.&lt;/li&gt;
&lt;li&gt;A Rust library responsible for rendering images, using &lt;a href=&quot;https://hexdocs.pm/rustler/readme.html&quot;&gt;Rustler&lt;/a&gt; to handle the Erlang-to-Rust translation, and compiled as a NIF.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Fun! We have not even written a single line of code and we are already playing with fire by introducing NIFs into the mix. We will have to take care of that later, but first we need to get a Phoenix project going:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;mix phx.new crafthead --no-html --no-assets --no-ecto --no-mailer&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This creates the &lt;code&gt;crafthead&lt;/code&gt; project with an extremely barebones configuration. The only HTML files we&#39;ll serve are static assets anyway, and Ecto will not be necessary at the moment, since caching can be done locally using an ETS table.&lt;/p&gt;
&lt;p&gt;Now we can launch the project and start writing some code! First, let&#39;s install Nebulex:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; deps&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:nebulex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;~&gt; 2.5&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:decorator&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;~&gt; 1.4&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;mix deps.get&lt;/code&gt;, &lt;code&gt;mix nbx.gen.cache -c Crafthead.Cache&lt;/code&gt;, and then add &lt;code&gt;Crafthead.Cache&lt;/code&gt; as instructed, and then we have our cache!&lt;/p&gt;
&lt;h2 id=&quot;writing-a-mojang-api-client&quot; tabindex=&quot;-1&quot;&gt;Writing a Mojang API client &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#writing-a-mojang-api-client&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Right! Let&#39;s go ahead and build a minimal Mojang API client. &lt;a href=&quot;https://wiki.vg/Mojang_API&quot;&gt;The API is pretty well-documented&lt;/a&gt; but we only need a handful of things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Map a username to a UUID&lt;/li&gt;
&lt;li&gt;Obtain the profile and skin of a player by their UUID&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s where Req comes into the picture. Let&#39;s install it now:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; deps&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:req&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;~&gt; 0.4.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;},&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;mix deps.get&lt;/code&gt; and now we have a richly-featured HTTP client at our fingertips. Now we can write our Mojang API client:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Clients&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Mojang&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @username_to_uuid_mapping_url&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;https://api.mojang.com/users/profiles/minecraft/&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @uuid_to_profile_url&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;https://sessionserver.mojang.com/session/minecraft/profile/&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; username_to_uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(username) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    url &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; @username_to_uuid_mapping_url&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; username &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;?unsigned=false&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Req&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(url) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; resp.status &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        200&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp.body[&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;id&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        404&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        429&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:too_many_requests&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        500&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:internal_server_error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        503&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:service_unavailable&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;        _&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:unknown&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; uuid_to_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(uuid) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    url &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; @uuid_to_profile_url&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; uuid&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Req&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(url) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; resp.status &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        200&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp.body}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        204&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        404&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        429&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:too_many_requests&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        500&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:internal_server_error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        503&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:service_unavailable&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;        _&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:unknown&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There is a little bit more to it than this, because the actual skin is in the &lt;code&gt;properties&lt;/code&gt; object and requires some&lt;br /&gt;
unwrapping, so let&#39;s build that out:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  @doc &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  Implements a raw representation of a Minecraft profile, from the Mojang API. Includes a convenience function to&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  obtain the skin information for a player.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @permitted_texture_types&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; %{&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;SKIN&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;CAPE&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :cape&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defstruct&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:id&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:name&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:properties&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_skin_info&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    profile&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; find_texture_property&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; decode_texture_property!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_texture_urls&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; find_texture_property&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;    Enum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;find&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile.properties, &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; property &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      property[&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;] &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;textures&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; decode_texture_property!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(property) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;when&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; is_map&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(property) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    property[&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;value&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Base&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;decode64!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Jason&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;decode!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; decode_texture_property!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(property) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;when&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; is_nil&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(property), &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;do:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_texture_urls&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(textures_property) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;when&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; is_map&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(textures_property) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    @permitted_texture_types&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Enum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;filter&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {texture_type, &lt;/span&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;      Map&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;has_key?&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(textures_property[&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;textures&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;], texture_type)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Enum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;map&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {texture_type, texture_type_atom} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      {texture_type_atom, textures_property[&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;textures&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;][texture_type][&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;url&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Map&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_texture_urls&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(textures_property) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;when&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; is_nil&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(textures_property), &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;do:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We elide a bunch of error handling here since all profiles come from the same trusted source, namely the Mojang servers.&lt;/p&gt;
&lt;p&gt;While we are at it, it&#39;s also a good idea to write a unit test for this class, since it does something non-trivial:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;MinecraftTest&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  use&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; ExUnit&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Case&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  describe &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;get_skin_info/1&quot;&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    test &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;returns skin information&quot;&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      profile &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; %&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :id&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;652a2bc4e8cd405db7b698156ee2dc09&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :name&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;tuxed&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :properties&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          %{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;            &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;textures&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;            &quot;value&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;ewogICJ0aW1lc3RhbXAiIDogMTcwMzgyNzIzMTg0OCwKICAicHJvZmlsZUlkIiA6ICI2NTJhMmJjNGU4Y2Q0MDVkYjdiNjk4MTU2ZWUyZGMwOSIsCiAgInByb2ZpbGVOYW1lIiA6ICJ0dXhlZCIsCiAgInRleHR1cmVzIiA6IHsKICAgICJTS0lOIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS9kOWM1MjcwMzUwOWM3MDcwNDczMGIyZDg4MmIzNjdjMTEyMWM2NGYzZDZmNmE5ZDEyNmU0N2IxZmU2NTY4MGI5IgogICAgfQogIH0KfQ==&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      expected_result &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; %{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        skin:&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;http://textures.minecraft.net/texture/d9c52703509c70704730b2d882b367c1121c64f3d6f6a9d126e47b1fe65680b9&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      assert &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get_skin_info&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; expected_result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    test &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;returns cape information&quot;&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      profile &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; %&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :id&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;1ccef50bf6ae4542b1a9d434384a5b25&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :name&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;Jeff&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;        :properties&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          %{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;            &quot;name&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;textures&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;            &quot;value&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;ewogICJ0aW1lc3RhbXAiIDogMTcwMzgyOTE5NjM0NCwKICAicHJvZmlsZUlkIiA6ICIxY2NlZjUwYmY2YWU0NTQyYjFhOWQ0MzQzODRhNWIyNSIsCiAgInByb2ZpbGVOYW1lIiA6ICJKZWZmIiwKICAidGV4dHVyZXMiIDogewogICAgIlNLSU4iIDogewogICAgICAidXJsIiA6ICJodHRwOi8vdGV4dHVyZXMubWluZWNyYWZ0Lm5ldC90ZXh0dXJlL2Y3ZjdhNWFmYmY5NDZkYWUxOWZhMzhjMjIxZTMxMDM0NTE5YjE5OWViMWZkZTkwZTI0OTUxNzJlOWQ3ZDZhIgogICAgfSwKICAgICJDQVBFIiA6IHsKICAgICAgInVybCIgOiAiaHR0cDovL3RleHR1cmVzLm1pbmVjcmFmdC5uZXQvdGV4dHVyZS85NTNjYWM4Yjc3OWZlNDEzODNlNjc1ZWUyYjg2MDcxYTcxNjU4ZjIxODBmNTZmYmNlOGFhMzE1ZWE3MGUyZWQ2IgogICAgfQogIH0KfQ==&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      expected_result &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; %{&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        skin:&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;http://textures.minecraft.net/texture/f7f7a5afbf946dae19fa38c221e31034519b199eb1fde90e2495172e9d7d6a&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        cape:&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;http://textures.minecraft.net/texture/953cac8b779fe41383e675ee2b86071a71658f2180f56fbce8aa315ea70e2ed6&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      assert &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get_skin_info&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;==&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; expected_result&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;building-our-first-endpoints&quot; tabindex=&quot;-1&quot;&gt;Building our first endpoints &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#building-our-first-endpoints&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;At this point, we are able to fetch a skin from the Mojang API, which is awesome. We can now create our first endpoints. Specifically, we will implement the &lt;code&gt;/profile/&amp;lt;username|UUID&amp;gt;&lt;/code&gt; and &lt;code&gt;/skin/&amp;lt;username|UUID&amp;gt;&lt;/code&gt; endpoints.&lt;/p&gt;
&lt;p&gt;First, we need to be able to tell if we are working with a username or a UUID. It will also normalize the entity provided (such as lowercasing the username or removing dashes in UUIDs) so that equivalent entities will map to the same cached value, which will be important later on. The function is simple, so a doctest can suffice to document and serve as the entire test suite:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Util&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Request&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @mojang_uuid_regex&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; ~r/^[0-9a-f]{32}$/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @regular_uuid_regex&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; ~r/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  @doc ~S&quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  Given the Minecraft profile `entity`, determine if it refers to a UUID or a username.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  ## Examples&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    iex&gt; Crafthead.Util.Request.what_entity(&quot;1ccef50bf6ae4542b1a9d434384a5b25&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    {:uuid, &quot;1ccef50bf6ae4542b1a9d434384a5b25&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    iex&gt; Crafthead.Util.Request.what_entity(&quot;4525ca19-5825-4774-bb90-a004de1460c3&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    {:uuid, &quot;4525ca1958254774bb90a004de1460c3&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    iex&gt; Crafthead.Util.Request.what_entity(&quot;tuxed&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    {:username, &quot;tuxed&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    iex&gt; Crafthead.Util.Request.what_entity(&quot;LadyAgnes&quot;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    {:username, &quot;ladyagnes&quot;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  &quot;&quot;&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; what_entity&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    cond&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;      Regex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.match?(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;@mojang_uuid_regex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;      Regex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.match?(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;@regular_uuid_regex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;replace&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;-&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt;      true&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:username&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;downcase&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity)}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we can implement the first controller to fetch profiles:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;ProfileController&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Clients&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Mojang&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Util&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  use&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:controller&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; show&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(conn, %{&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;entity&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    result &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; entity&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Request&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;what_entity&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;    |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    case&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; result &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, profile} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        conn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_status&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_resp_header&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;cache-control&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;public, max-age=86400&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; json&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        conn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_status&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_view&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;json:&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;ErrorJSON&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:&quot;404&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;_&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;-&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        conn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_status&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:internal_server_error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_view&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;json:&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;ErrorJSON&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;        |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:&quot;500&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;    Mojang&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;uuid_to_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:username&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, uuid} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Mojang&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;username_to_uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;      get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, uuid})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Add this to the router:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;scope &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;/&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  pipe_through &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:api&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  get &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;/profile/:entity&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;ProfileController&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  get &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;/ping&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;PingController&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:show&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now if you go to &lt;code&gt;http://localhost:4000/profile/tuxed&lt;/code&gt;, you&#39;ll see my Minecraft profile. Our first endpoint is implemented! We should definitely stop and clean this up a bit, though - we&#39;re going to carry a lot of duplicated code around if we don&#39;t define a fallback controller. I will elide that, but assume it exists for any other controllers we implement.&lt;/p&gt;
&lt;p&gt;Next up, we&#39;re going to implement endpoints for fetching skins. This is pretty easy:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;SkinController&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Clients&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Mojang&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Minecraft&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Util&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Request&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  use&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:controller&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  action_fallback &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;CraftheadWeb&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;FallbackControlle&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; show&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(conn, %{&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;entity&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; raw_entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    entity &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; raw_entity &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;|&gt;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Request&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;what_entity&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, profile} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        texture_info &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Minecraft&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get_skin_info&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(profile),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;         {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, skin} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; fetch_skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(texture_info) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      conn&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;      |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_resp_header&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;cache-control&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;public, max-age=86400&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;      |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; put_resp_header&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;content-type&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;image/png&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;      |&gt;&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; send_resp&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;200&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, skin)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;    Mojang&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;uuid_to_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:username&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, entity}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, uuid} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Mojang&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;username_to_uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(entity) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;      get_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;({&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, uuid})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; fetch_skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(%{&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:skin&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; =&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; skin_url}) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    with&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp} &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;-&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Req&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;get&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(skin_url) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      case&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; resp.status &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        200&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, resp.body}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        404&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:not_found&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        429&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:too_many_requests&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        500&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:internal_server_error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;        503&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:service_unavailable&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;        _&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; -&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:unknown&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This concludes a very basic implementation of an skin and profile-fetching service for Minecraft written in Elixir, but we are far from done yet. We need to add in a few more creature comforts.&lt;/p&gt;
&lt;h2 id=&quot;caching-and-rate-limiting&quot; tabindex=&quot;-1&quot;&gt;Caching and rate-limiting &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#caching-and-rate-limiting&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Since the Mojang API has rate limits, we can&#39;t simply request data from it every time we need it, so we are expected to cache the data. Luckily, that&#39;s why we pulled in Nebulex earlier. Let&#39;s modify our Mojang API client:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Clients&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Mojang&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  alias&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Cache&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  use&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Nebulex&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Caching&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @username_ttl&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :timer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;hours&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @profile_ttl&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :timer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;hours&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#B5CEA8&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;  # ...same code...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @decorate&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; cacheable&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;cache:&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Cache&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;key:&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:username_to_uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, username}, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;opts:&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;ttl:&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; @username_ttl&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; username_to_uuid&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(username) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...same code...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  @decorate&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; cacheable&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;cache:&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Cache&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;key:&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:uuid_to_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, uuid}, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;opts:&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; [&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;ttl:&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; @profile_ttl&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;])&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; uuid_to_profile&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(uuid) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...same code...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Now we have a cache around the Mojang API - one hour for usernames, and one day for profiles. We can also easily ensure skin textures are also cached so we don&#39;t need to fetch them from Mojang every time too.&lt;/p&gt;
&lt;h2 id=&quot;time-to-bring-in-the-rustler&quot; tabindex=&quot;-1&quot;&gt;Time to bring in the Rustler! &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#time-to-bring-in-the-rustler&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You have sat here for a while, now it&#39;s time for the fun part: adding a NIF to this project. Let&#39;s install Rustler first:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; deps&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  [&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    {&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;~&gt; 0.30.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;runtime:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  ]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Run &lt;code&gt;mix deps.get&lt;/code&gt; and then create the Rustler module:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# mix rustler.new     &lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;This is the name of the Elixir module the NIF module will be registered to.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Module name &gt; Crafthead.Renderer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;This is the name used for the generated Rust crate. The default is most likely fine.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Library name (crafthead_renderer) &gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;* creating native/crafthead_renderer/.cargo/config.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;* creating native/crafthead_renderer/README.md&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;* creating native/crafthead_renderer/Cargo.toml&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;* creating native/crafthead_renderer/src/lib.rs&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;* creating native/crafthead_renderer/.gitignore&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Ready to go! See [...]/crafthead/native/crafthead_renderer/README.md for further instructions.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The first thing I did was copy the dependencies from the original Crafthead project into the new project&#39;s &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-toml&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#D4D4D4&quot;&gt;package&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;crafthead_renderer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;0.1.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;authors&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = []&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;edition&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;2021&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#D4D4D4&quot;&gt;lib&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;name&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;crafthead_renderer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;path&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;src/lib.rs&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;crate-type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = [&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;cdylib&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#D4D4D4&quot;&gt;dependencies&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;0.30.0&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;imageproc&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = { &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;0.22.0&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;default-features&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;false&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#D4D4D4&quot;&gt;dependencies&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#D4D4D4&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;# Make `image` more lightweight. We don&#39;t need every image format under the sun,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;# just PNG.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;version&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;0.23.14&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;default-features&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;false&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;features&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = [&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;png&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Following that, I copied all the remaining files into the new Rust project as well, and made a copy of the old &lt;code&gt;src/lib.rs&lt;/code&gt; for reference. Now we will set about moving the API from Wasm to Rustler. We&#39;ll start with simple cases and progressively move upwards. First, consider this function which serves as the gateway into the WebAssembly version:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;#[wasm_bindgen]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;pub&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt; fn&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; get_rendered_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;	skin_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Uint8Array&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;	size&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;	what&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;String&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;	armored&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;	slim&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) -&gt; &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Uint8Array&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;JsValue&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Consider an idiomatic Elixir interface:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;@type&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render_type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :avatar&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :helm&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :cube&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :body&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :bust&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :cape&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;@type&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; skin_type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;() &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :classic&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :slim&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;@spec&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;render_type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), [&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;armored:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; boolean&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;skin:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; skin_type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(), &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;size:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; integer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()]) &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(image, what, options &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&#92;&#92;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; []) &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    # ...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re not going to be using this interface exactly, but it helped give me a good mental model for converting the existing code into Rustler. I wound up with this:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-rust&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;mod&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; skin;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;mod&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; utils;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt; std&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;io&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Cursor&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt; image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;DynamicImage&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt; rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::{&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Env&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifResult&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifStruct&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifUnitEnum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;OwnedBinary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;use&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt; skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::{&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;BodyPart&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Layer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;MinecraftSkin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;SkinModel&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;};&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;mod&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; atoms {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;    rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;atoms!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;        // Error types.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        invalid_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        unable_to_render&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;#[derive(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Copy&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Clone&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifUnitEnum&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;enum&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; RenderType&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Avatar&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Helm&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Cube&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Body&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Bust&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;    Cape&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;#[derive(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifStruct&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;#[module &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;Crafthead.Renderer.RenderOptions&quot;&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;struct&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; RenderOptions&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    pub&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; render_type&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;RenderType&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    pub&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; size&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;u32&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    pub&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; armored&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;bool&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    pub&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; model&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;SkinModel&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;impl&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt; RenderType&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;    // ...elided...&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;#[rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;nif]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt;(&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    env&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Env&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    skin_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    options&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;: &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;RenderOptions&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) -&gt; &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;NifResult&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;&gt;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; image_copy&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;skin_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;as_slice&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;    let&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; skin_result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;load_from_memory_with_format&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;image_copy&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;ImageFormat&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Png&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    match&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; skin_result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;        Ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;skin_img&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) =&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;MinecraftSkin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;skin_img&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; rendered&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;options&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.render_type.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;render&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;skin&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;options&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;            // We can&#39;t predict the size of the output, so we can&#39;t just write directly into an OwnedBinary.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt; mut&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Vec&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;with_capacity&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;1024&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;            let&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt; mut&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; cursor&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Cursor&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;            return&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; match&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; rendered&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;write_to&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;mut&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; cursor&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;ImageFormat&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Png&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;                Ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(()) =&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;                    let&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt; mut&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;OwnedBinary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;len&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()).&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;unwrap&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;();&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;                    binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;as_mut_slice&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;().&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;copy_from_slice&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&amp;#x26;&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;result&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;[..]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;                    Ok&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;from_owned&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;binary&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;env&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;                }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;                Err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;_err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) =&gt; &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;Term&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;Box&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;atoms&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;unable_to_render&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()))),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            };&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;        Err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;_err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) =&gt; &lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Err&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#4EC9B0&quot;&gt;Error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;Term&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;Box&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;new&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;atoms&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;invalid_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()))),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#4EC9B0&quot;&gt;rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;::&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;init!&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&quot;Elixir.Crafthead.Renderer&quot;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, [&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;render_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;]);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The upshot is that we do not need to copy the original skin twice, unlike the Wasm version. Because of the neater FFI provided by Rustler, the &lt;code&gt;render_image&lt;/code&gt; function reads a lot more naturally. The only weird parts are that we need to copy the output twice and there is a lifetime now attached to the &lt;code&gt;render_image&lt;/code&gt; call bound to the NIF call, but it&#39;s not really a big deal.&lt;/p&gt;
&lt;p&gt;Now to load the NIF and expose the renderer:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Renderer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;RenderOptions&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defstruct&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt; render_type:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;            size:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; nil&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;            armored:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; false&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;            model:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#569CD6&quot;&gt; nil&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;defmodule&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt;Renderer&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; do&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  use&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Rustler&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;otp_app:&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :crafthead&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;crate:&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt; &quot;crafthead_renderer&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  def&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; render_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;_skin_image&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;_options&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;), &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;do:&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;()&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  defp&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;do:&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt; :erlang&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;nif_error&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;color:#0184BC;--shiki-dark:#D4D4D4&quot;&gt;:nif_not_loaded&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;end&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It works!&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;iex(5)&gt; render = Crafthead.Renderer.render_image(alex, %Crafthead.Renderer.RenderOptions{render_type: :avatar, size: 300, model: :slim})&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&amp;#x3C;&amp;#x3C;137, 80, 78, 71, 13, 10, 26, 10, 0, 0, 0, 13, 73, 72, 68, 82, 0, 0, 1, 44, 0,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  0, 1, 44, 8, 6, 0, 0, 0, 121, 125, 142, 117, 0, 0, 14, 15, 73, 68, 65, 84,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;  120, 156, 237, 212, 177, 206, 118, 233, 28, ...&gt;&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;h2 id=&quot;a-very-dirty-nif&quot; tabindex=&quot;-1&quot;&gt;A very dirty NIF &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#a-very-dirty-nif&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here is the problem with this NIF: although it is quite fast, it&#39;s not fast enough to be kept on the same scheduler as everything else. Quoting &lt;a href=&quot;https://www.erlang.org/doc/man/erl_nif#lengthy_work&quot;&gt;the Erlang documentation&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;As mentioned in the warning text at the beginning of this manual page, it is of vital importance that a native function returns relatively fast. It is difficult to give an exact maximum amount of time that a native function is allowed to work, but usually a well-behaving native function is to return to its caller within 1 millisecond.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;The easiest way around this is to just mark the &lt;code&gt;render_image&lt;/code&gt; as a dirty NIF. While it is slow, it is not catastrophically slow, so the warning attached to the Erlang documentation for dirty NIFs is not really applicable. We can specify this is a dirty NIF:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-elixir&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A0A1A7;font-style:italic;--shiki-dark:#6A9955;--shiki-dark-font-style:inherit&quot;&gt;#[rustler::nif(schedule = &quot;DirtyCpu&quot;)]&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;fn&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; render_image&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&#39;a&gt;(env: Env&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;skin_image:&lt;/span&gt;&lt;span style=&quot;color:#C18401;--shiki-dark:#4EC9B0&quot;&gt; Binary&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&amp;#x3C;&lt;/span&gt;&lt;span style=&quot;color:#50A14F;--shiki-dark:#CE9178&quot;&gt;&#39;a&gt;, options: RenderOptions) -&gt; NifResult&amp;#x3C;Binary&amp;#x3C;&#39;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;a&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#D4D4D4&quot;&gt;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;We&#39;re done! From here, we can implement all the other endpoints. Want to give it a spin? &lt;a href=&quot;https://github.com/astei/crafthead-ex&quot;&gt;I have pushed the code for your enjoyment&lt;/a&gt;. It still needs cleanup and isn&#39;t feature-complete yet, but it will be soon enough...&lt;/p&gt;
&lt;h2 id=&quot;did-you-enjoy-it&quot; tabindex=&quot;-1&quot;&gt;Did you enjoy it? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/misadventures-with-phoenix-framework/#did-you-enjoy-it&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It was better than falling asleep and being like a zombie the following day. Can&#39;t complain. Even if I had to fight with the borrow checker.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>🌳 A Tree Grows in Times Square</title>
		<link href="https://steinborn.me/posts/a-tree-grows-in-times-square/"/>
		<updated>2023-10-13T00:00:00Z</updated>
		<id>https://steinborn.me/posts/a-tree-grows-in-times-square/</id>
		<content type="html">&lt;p&gt;Times Square in 1978 was the dictionary definition of urban decay. Neon lights that once belonged to posh theaters now advertised peep shows and adult entertainment. Street corners were populated by sleazy motels, adult stores, and dodgy nightclubs and bars. The area was populated only with the lowest of American strata, those who had no other place to go. Below the cacophony of cars on the streets seeking to get the hell out as quickly as possible, the subway whirred, with its signs of neglect perhaps worse than what was present above ground. Outside of Times Square, the city burned. Riots, burglaries, and arson had consumed large blocks of Brooklyn and the Bronx. Nobody wanted to be next.&lt;/p&gt;
&lt;p&gt;And yet, a tree had taken root on a vacant lot. This tree was Ailanthus, known as “tree of heaven”, or more colloquially, “ghetto palm.” It was a typical weed of urban environments. Few bothered to pay it much mind; the city was burning in those times, and who cared about some weed in the seediest part of Midtown Manhattan, anyway?&lt;/p&gt;
&lt;p&gt;The tree grew. Nobody paid much heed.&lt;/p&gt;
&lt;p&gt;At first, it was all normal. Drug dealers would use it as a convenient background for their illicit transactions. The same happened with sleazy, unlicensed taxi drivers, and the men and women of loose morals offering their “services”.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;A strange sort of magnetism started to form around the tree, with strange occurrences happening within the vicinity of the tree.&lt;/p&gt;
&lt;p&gt;A man named Eddie, who had frequented the area for years, claimed the tree was speaking to him, filling his nights with nightmares and his days with an inescapable dread. &amp;quot;It&#39;s like a shadow&#39;s whisper, man,&amp;quot; he&#39;d say. His erratic behavior drew the attention of the authorities, and he was committed to a mental institution. Everyone dismissed Eddie as another lost soul swallowed by the city. But something in his eyes said otherwise.&lt;/p&gt;
&lt;p&gt;Jolie, a stripper who would often perform at Texas Sized, an early “breastaurant”, would often comment about how the tree would impact the patrons who came in. Everything from dark thoughts, people staring at the tree intently as if it had something to say, people sleeping underneath the tree for more than 18 hours on end, people dying immediately after injecting drugs next to the tree, she had seen everything. But nobody wanted to pay heed to this New Jerseyan who was just trying to scrape enough money together to go to college. She was just looking for attention, right?&lt;/p&gt;
&lt;p&gt;The tree kept growing, developing a robust canopy, shading the vacant lot it occupied.&lt;/p&gt;
&lt;p&gt;A major conglomerate, famous for a certain mouse mascot, sought to move in. Redevelop Times Square in its own image. A sanitized playground ideal for the average American family. A homage to commercialism. A celebration of American capitalism, rising out of chaos.&lt;/p&gt;
&lt;p&gt;Gentrification.&lt;/p&gt;
&lt;p&gt;In a corporate office in suburban Los Angeles, the tree was ever present in the thoughts of the executives and managers looking to execute upon their grand vision. Huddled around a drafting table, the tree was circled right there, on that lot, on a map where a grand celebration of capitalism was to be built. The company had already purchased the lot as part of the redevelopment project, ample loans and tax credits had made sure of that. It was time to decide whether or not to tear down the tree.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Tension continued to boil, back in the office. The tree had rapidly become a serious sticking point in the plan to transform Times Square. The lead architect spoke up. “This tree does not fit. It is nothing more than an out of control weed, a plant of inconsequential value. We are not building Central Park. It’s time to kill it off, and keep it dead.”&lt;/p&gt;
&lt;p&gt;A junior member of the project, associated with public relations, argued in favor of preserving the tree. &amp;quot;It&#39;s become a part of the local landscape, a monument in its own right. Can&#39;t we build around it? Incorporate it into the design?&amp;quot; she suggested, sketching a quick rendering that framed the tree as the centerpiece of a small park within the commercial empire.&lt;/p&gt;
&lt;p&gt;As the debate raged on, each side armed with its own set of reasons, the decision loomed large, growing in significance much like the tree itself had done amidst the decay of Times Square.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Miguel was walking on the street where the vacant lot stood. He was part of a Russian nesting doll of subcontractors hired by the major conglomerate in preparation for the megaproject that was unfolding. The blistering heat of July in New York City was coming down on him. He opened a cold beer he had bought from a nearby bodega. As he took a sip, the taste of beer was replaced by a rather most unfamiliar taste, a sweet but unexpected taste. He spat out his beer.&lt;/p&gt;
&lt;p&gt;Katherine, an auditor on the project’s accounting and finance team, was staying in a close family friend’s home in the Upper East Side. She hailed a taxi to the site to examine the property for herself. She had vaguely heard of the tree, but her interest was whether or not the company paid a fair price for the lot. As the cab approached the lot, the driver started to mumble. She grew worried as the cab came to a sudden halt, feet from the lot, with the engine still running, the doors locked, and the driver frozen in place.&lt;/p&gt;
&lt;p&gt;Meanwhile, the city continued to hum along. People would walk next to the vacant lot. Many times, nothing notable would happen. Other times, something spectacular and unusual would happen. The decay was slowing, but it was still present everywhere.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Robert was a manager at a major banking firm that had extended loans to the conglomerate for the project. He was also a closeted gay man in a marriage that was quickly falling apart. He found solace in visiting gay spaces in Greenwich Village and Times Square and visiting with someone who had very quickly became a spouse in all but formality. He was captivated by the tree. It was almost like it called out for him.&lt;/p&gt;
&lt;p&gt;After a bitter and messy divorce, he would buy a dilapidated apartment building across from the tree and convert it into his new home, and he and his new spouse, Jamie, would move in. Jamie didn’t understand why Robert wanted to move here when his life was so well in Connecticut, but he went along with it because he loved Robert.&lt;/p&gt;
&lt;p&gt;On many occasions, Robert would call out sick from work and spend hours looking at the tree. He admired it, respected it, worshiped it like a god. It annoyed the ever-living hell out of Jamie.&lt;/p&gt;
&lt;p&gt;A drug dealer who frequented Times Square who once made his sales in the shadow of the tree would report strange things about the tree. That it was making the drugs more potent. That the tree was speaking to people. That the tree was providing good fortune. He was arrested by police, and they moved onto the next common criminal.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;The decision had been made to tear down the tree. It was a nuisance.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Reactions to the impending demise of the tree were as mixed as the clientele that roamed Times Square. It was as though the tree had woven itself into the fabric of people’s lives, more tightly for some than for others. Rumors and whispers spread like wildfire—everyone from Miguel the contractor to Robert, who lived across from the tree, felt a sense of impending doom or at least change.&lt;/p&gt;
&lt;p&gt;Miguel, still puzzled by the bizarre taste of his beer, looked at the tree one last time before leaving the site. He wondered what else the tree might have influenced that he wasn&#39;t aware of. Katherine, shaken by her cab incident, started to research not just the lot’s financial aspects but also the strange occurrences tied to it. She couldn’t shake the feeling that this was about more than just real estate, that this was not something that an audit focused on the numbers would ever be able to solve.&lt;/p&gt;
&lt;p&gt;Robert felt a knot tighten in his stomach. For him, the tree had become a sanctuary, a constant amid the chaos of his personal life. Jamie could see that something was bothering Robert profoundly, but he could not understand what the tree had to do with it. All the better to kill off a weed, he thought.&lt;/p&gt;
&lt;p&gt;The clientele of Times Square continued to exchange their stories about the tree. The supernatural. The average. The merely bizarre.&lt;/p&gt;
&lt;p&gt;Word had spread about the tree and it had become something of a minor tourist attraction in its own right.&lt;/p&gt;
&lt;p&gt;Days before the planned removal, Robert found himself standing in front of the tree, as if to say a final goodbye. He felt a wave of sadness wash over him, only broken by Jamie&#39;s voice letting him know dinner was ready.&lt;/p&gt;
&lt;p&gt;Protests and petitions to save the tree sprang up, but the wheels of progress, lubricated by money and corporate power, seemed impossible to halt. Even the drug dealer, from his prison cell, muttered something about the foolishness of removing a source of good fortune.&lt;/p&gt;
&lt;p&gt;The night before the tree was scheduled for removal, strange occurrences peaked. Reports of eeriness, of whispering winds, and unexplained phenomena flooded the local police lines. Those who had never believed in the tree&#39;s &#39;powers&#39; were starting to doubt themselves.&lt;/p&gt;
&lt;p&gt;And despite all the efforts to cut it down, despite being labeled a nuisance, despite the chainsaws that were readied and aimed at its base—&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;And it devoured and disabled the equipment that was meant to bring its demise about.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;And it infiltrated the minds of those who sought to tear down the tree, clouding them in dark thoughts.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Back in California, an emergency meeting was convened. What had once been dismissed as a nuisance was now an object of both fascination and fear, leading to an atmosphere of uncertainty and chaos. The project was at risk of becoming not just a financial burden but a public relations nightmare.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;The lead architect, who had once dismissed the tree as an &amp;quot;out of control weed,&amp;quot; dwelled in a mix of anger and angst. The public relations junior member, who had once advocated for the tree&#39;s preservation, couldn&#39;t help but feel a sense of vindication mixed with newfound respect for the mysterious tree.&lt;/p&gt;
&lt;p&gt;Meanwhile, a new wave of stories about the tree swept through the city, intensifying the mythos surrounding it. Its branches now stretched high and wide, a towering spectacle that seemed to defy not just corporate will but nature itself.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;But the unstoppable will of corporate America demanded the death of this tree.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;No expense was spared, and the conglomerate sought to hire just about every expert out there. Biologists and chemists at the country’s top universities. Religious figures of every stripe. Voodoo practitioners. Even a handful of charlatans managed to get a slice of the pie. They set up shop in an old hotel near the lot, and converted it into a modern lab, all with the singular goal of killing the tree.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Nothing they did was any good.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Experimental herbicides served only to nourish the tree, and give the scientists both figurative and literal headaches. One would later develop cancer.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Physical treatments all suspiciously failed, with equipment malfunctions, bizarre accidents, and even deaths.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Shamans tried to curse the tree, but would be suspiciously and conveniently attacked with dark thoughts every time.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;The conglomerate even tried to hire nuclear scientists in an effort to poison or destroy the tree with the use of radioactivity. Operating a nuclear laboratory in the middle of New York City was a hard sell, especially with the memory of Three Mile Island so fresh, and so the plan was nixed.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;Dread became the order of the day back in the California boardroom. The project to kill the tree was quickly becoming a financial strain and a public relations disaster for the conglomerate. Shareholders grew restless, activists became more vocal, and even the most hardened executives started to question the wisdom of their endeavor. Slowly, dread turned into resignation. One faction considered the tree an insidious force that was to be ignored entirely, in hopes of having the rest of the project succeed. Others argued for respecting the tree and incorporating it into the plans.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
&lt;p&gt;And as the grand theaters of Times Square were restored, the seedy adult businesses shuttered, and family-oriented businesses moved in, the tree sat there, on the same vacant lot, observing the world around it as it changed. Times Square would morph into a wonderland of commercialism, the much lauded celebration of American capitalism that was envisioned, buzzing with more activity than it had gotten in over 50 years with tourists arriving from all around the world, some just to gawk at the tree.&lt;/p&gt;
&lt;p&gt;Urban legends would circulate about the tree, with its stories told in constantly evolving permutations. It simply blended into the urban and cultural fabric of New York. Some would continue to ascribe certain experiences with the tree.&lt;/p&gt;
&lt;p&gt;Some would remember the tree as an eternal reminder of the “old” New York, before it gentrified and became sanitized, boring, and uninspired. Others considered it a reminder that nature was always the last remaining check on man’s hubris. Others considered the tree to be part of a grand, sprawling conspiracy. Still others ascribed religious meaning to it, whether it was the Anti-Christ or a deity to be respected in its own right.&lt;/p&gt;
&lt;p&gt;It witnessed the ebb and flow of humanity around it, the changing seasons of a city that never sleeps, the neon lights and LEDs advertising America, and the cyclical nature of decay and rebirth. It absorbed the vibrations of a thousand stories, from Robert&#39;s newfound love and liberation to the unexplained phenomena that defied scientific scrutiny.&lt;/p&gt;
&lt;p&gt;The tree kept growing. And it would have the last laugh.&lt;/p&gt;
&lt;h2 id=&quot;epilogue&quot; tabindex=&quot;-1&quot;&gt;Epilogue &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-tree-grows-in-times-square/#epilogue&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The redevelopment of Times Square wound up being a smashing success for the conglomerate, but it came at a high price. The conglomerate was on the brink of declaring bankruptcy, but it was rescued by its creditors at the last minute. But it would be forever remembered in New York as “that company that tried to cut down the tree.”&lt;/p&gt;
&lt;p&gt;The lead architect was disgraced. Combined with a severe gambling problem, he was a desolate man. The last time anyone heard from him, he was living underneath a freeway overpass in Los Angeles.&lt;/p&gt;
&lt;p&gt;Katherine left the conglomerate and started advocating for protecting the tree as a historical landmark.&lt;/p&gt;
&lt;p&gt;Robert and Jamie would later move out, being offered a handsome sum to convert their home into a multi-story hotel. They gladly accepted, and they went into retirement in Florida together. It was hard on Robert, but they needed to enjoy the golden years somehow.&lt;/p&gt;
&lt;p&gt;Jolie returns to Times Square after college as an office worker working at an advertising company.&lt;/p&gt;
&lt;p&gt;Some would say that the tree had a strange magnetism about it. They were believed.&lt;/p&gt;
&lt;p&gt;The tree kept growing.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>📚 A 2022 dispatch</title>
		<link href="https://steinborn.me/posts/a-2022-dispatch/"/>
		<updated>2022-10-16T00:00:00Z</updated>
		<id>https://steinborn.me/posts/a-2022-dispatch/</id>
		<content type="html">&lt;p&gt;Well... a lot of big things happened this year. But to understand the context, we also need to understand what went down last year, which was significant in its own way.&lt;/p&gt;
&lt;h2 id=&quot;a-short-recap-of-2021&quot; tabindex=&quot;-1&quot;&gt;A short recap of 2021 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#a-short-recap-of-2021&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In 2021, I...&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;👾 began to say my final goodbyes to the &lt;em&gt;Minecraft&lt;/em&gt; scene. I am still minimally involved, but I&#39;m not going out of my way to support it.&lt;/li&gt;
&lt;li&gt;👾 ...and started what would be a 8-month stint at &lt;a href=&quot;https://branch.gg/&quot;&gt;Branch&lt;/a&gt;, which at the time was working on a &amp;quot;virtual office&amp;quot; platform, before pivoting to UGC, and then finally to producing &amp;quot;web3 video games&amp;quot; in October (along with a strong recommendation to move to Seattle, a move I was not yet ready to make), whereupon I left them.&lt;/li&gt;
&lt;li&gt;🎓 ...dropped out of college. It felt increasingly meaningless to me and I could no longer tolerate being bullied.&lt;/li&gt;
&lt;li&gt;💳 ...after I left Branch in October, I immediately looking for another job. Through the absolute 🐐 &lt;a href=&quot;https://twitter.com/yunyu_l&quot;&gt;Yunyu Lin&lt;/a&gt; (thank you so much!) through my days in the early days of the Minecraft server scene, I received an offer to work as a software engineer at &lt;a href=&quot;https://ramp.com/&quot;&gt;Ramp&lt;/a&gt; and started work in November 2021.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&#39;s where we&#39;ll leave it for 2021 - a big year, and while I can&#39;t enumerate everything that went down that year, getting a job at Ramp was absolutely the highlight of 2021. This is a job that is very difficult to leave and for good reason! Keep this in mind, for one event in 2022 ties to that.&lt;/p&gt;
&lt;h2 id=&quot;the-start-of-2022&quot; tabindex=&quot;-1&quot;&gt;The start of 2022 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#the-start-of-2022&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The start of 2022 was pretty uneventful. I had already substantially onboarded to Ramp in late 2021 (the first code that was entirely my work was pushed just before the company holiday break). Then I decided to visit the New York office in late March 2022 - I&#39;d never been and I wanted to go, since up to this point I hadn&#39;t left the Southeastern United States.&lt;/p&gt;
&lt;p&gt;It was great - perhaps I fell in love too quickly, because I wanted to come back for real. I already had thoughts about moving due to the last job, since I simply was tired of living in the Atlanta area and wanted a fresh start, a chance to stake out on my own. I found that opportunity in New York.&lt;/p&gt;
&lt;h2 id=&quot;welcome-to-new-york&quot; tabindex=&quot;-1&quot;&gt;🗽 Welcome to New York &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#welcome-to-new-york&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;After (too quickly) finding an apartment, I arrived back in New York on April 17, 2022. The next day, I moved into my very first apartment in NYC.&lt;/p&gt;
&lt;p&gt;I took a week off from work to settle in and check out my neighborhood some. Ever since I moved to New York, I started to really grow into myself. The shock was immense, but I was able to adjust very well after a few weeks - granted, I had some experience from my first trip. Furthermore, my mental and physical health improved with the move: I was no longer dreading about staying home all the time, because there was so much I could do in New York, whether it&#39;s to try something I&#39;d never done before, or enjoy working with coworkers, or just admire the beauty of the city... I wouldn&#39;t run out of options.&lt;/p&gt;
&lt;h2 id=&quot;ramp-builders-2022&quot; tabindex=&quot;-1&quot;&gt;🌴 Ramp Builders 2022 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#ramp-builders-2022&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In June, the entire product, engineering, and design teams had a chance to sync in-person at our first major internal conference, &lt;em&gt;Ramp Builders&lt;/em&gt;, held in Miami that year.&lt;/p&gt;
&lt;p&gt;The conference packed a lot into 3 days. It was certainly a major milestone. We spoke with some Miami-area customers, had discussions, thought about next steps, and began aligning on long-term projects we needed to ship.&lt;/p&gt;
&lt;h2 id=&quot;finally-redoing-my-website&quot; tabindex=&quot;-1&quot;&gt;📄 Finally, Redoing My Website? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#finally-redoing-my-website&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It took a while... but I redid my website. The previous design, while it worked, looked somewhat ugly, and I wanted to revamp things and brush off the frontend skills that I clearly have been rusting for some time... so I went back to the past, dusted off a template from the venerable &lt;a href=&quot;https://html5up.net/&quot;&gt;HTML5 UP&lt;/a&gt;, converted the template to Nunjucks for use with &lt;a href=&quot;https://11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;, and extensively customized it for my own needs, and topped it off with a photo of the beautiful (but tourist-choked, to my great chagrin) Brooklyn Bridge:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://steinborn.me/images/fulls/oct-15-2022-brooklyn-bridge.jpg&quot;&gt;&lt;img src=&quot;https://steinborn.me/images/thumbs/oct-15-2022-brooklyn-bridge.jpg&quot; alt=&quot;October 15 photo of the Brooklyn Bridge&quot; title=&quot;Brooklyn Bridge&quot; /&gt;&lt;/a&gt;&lt;br /&gt;
&lt;em&gt;Click the above image to expand. I might start posting some photography here! Taken with my iPhone XR on October 15, 2022 at 5:48PM, a bit before sunset.&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;thats-all-for-now&quot; tabindex=&quot;-1&quot;&gt;That&#39;s All For Now &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/a-2022-dispatch/#thats-all-for-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am sure there is a lot more ahead - this has been a year of extremes, largely for the worse. But I can take some comfort knowing that &lt;em&gt;I am finding myself&lt;/em&gt; and have become independent. The road ahead will be long and with many twists and turns, but at least I am walking down it now.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>How fast can you write a VarInt?</title>
		<link href="https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/"/>
		<updated>2021-05-08T00:00:00Z</updated>
		<id>https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/</id>
		<content type="html">&lt;p&gt;I often like to start my day by keeping myself abreast of interesting things in the world of computer programming. Often this means a visit to &lt;a href=&quot;https://news.ycombinator.com/&quot;&gt;Hacker News&lt;/a&gt; or &lt;a href=&quot;https://lobste.rs/&quot;&gt;Lobsters&lt;/a&gt;. I somehow managed to come across &lt;a href=&quot;https://richardstartin.github.io/posts/dont-use-protobuf-for-telemetry&quot;&gt;Richard Startin&#39;s article about why he doesn&#39;t use Google Protocol Buffers for telemetry&lt;/a&gt;. Near the bottom, he has an aside about VarInts and shares a few tricks to produce them more efficiently.&lt;/p&gt;
&lt;p&gt;Why was this relevant to me? That is because the &lt;em&gt;Minecraft: Java Edition&lt;/em&gt; protocol uses VarInts extensively. But what exactly are we looking at here? Let&#39;s dive a bit deeper.&lt;/p&gt;
&lt;h2 id=&quot;what-even-is-a-varint&quot; tabindex=&quot;-1&quot;&gt;What even is a VarInt? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#what-even-is-a-varint&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;A Protocol Buffers VarInt is a 1 to 10 byte sequence that encodes a specific number (usually up to 32-bit for up to 5 byte VarInts, 64-bit for up to 10 byte VarInts). The process for encoding a VarInt is simple:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Check if the value is less than &lt;code&gt;0x80&lt;/code&gt;. (This is usually done with a simple AND and comparison, i.e. &lt;code&gt;(value &amp;amp; ~0x7FL) == 0&lt;/code&gt;.) If so, write the value out to the next position in the buffer and return.&lt;/li&gt;
&lt;li&gt;Grab the lowest 7 bits of the value being written (&lt;code&gt;value &amp;amp; 0x7F&lt;/code&gt;) and set the 8th bit (&lt;code&gt;(value &amp;amp; 0x7F | 0x80)&lt;/code&gt;). Write this out into the next position in the buffer.&lt;/li&gt;
&lt;li&gt;Logically shift the value to the right by 7 bits and repeat from step 1.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here is the naive implementation (sourced from the Google Protocol Buffers library&#39;s &lt;code&gt;CodedInputStream&lt;/code&gt;):&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; ~&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7FL&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    buffer[position++] = (&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) value;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    buffer[position++] = (&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) (((&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;For the purposes of demonstration we will focus on the 32-bit VarInts only - the techniques shown here can be extended to 64-bit VarLongs (at a not-insignificant cost to your sanity).&lt;/p&gt;
&lt;p&gt;Now, for the main star of the show - the old VarInt writing implementation from Velocity:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;while&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is simply a version of the above method, but adapted to write to a &lt;a href=&quot;https://netty.io/&quot;&gt;Netty&lt;/a&gt; &lt;code&gt;ByteBuf&lt;/code&gt;. With the necessary background taken care of, let&#39;s have some fun.&lt;/p&gt;
&lt;h2 id=&quot;disclaimer&quot; tabindex=&quot;-1&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#disclaimer&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I am by no means an expert on how the JIT operates, but I am very interested in fun and unique ways to solve problems!&lt;/p&gt;
&lt;p&gt;The testing system is my home PC, featuring an AMD Ryzen 9 3900X processor with 32GB of DDR4-3600 memory, running Fedora 34 and Java 11 as packaged in Fedora. We use the flag &lt;code&gt;-Dio.netty.leakDetection.level=DISABLED&lt;/code&gt; as otherwise 1% of buffers will be selected for leak detection instrumentation, which would introduce unfavorable noise in the results.&lt;/p&gt;
&lt;p&gt;The benchmarks in question allocate a direct buffer 5 bytes long, write a VarInt into it, and then clear it. This is repeated for a pseudo-random sequence of 2,048 numbers in order to defeat the JVM&#39;s tendency to assume that a certain branch would always be taken.&lt;/p&gt;
&lt;h2 id=&quot;try-1-richard-startins-method&quot; tabindex=&quot;-1&quot;&gt;Try 1: Richard Startin&#39;s Method &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-1-richard-startins-method&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s try using Richard Startin&#39;s tricks. Here&#39;s the above method, but using his method:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; continuationBytes&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;31&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;Integer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;numberOfLeadingZeros&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value)) / &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;for&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; i&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;; i &amp;#x3C; continuationBytes; ++i) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(((&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)));&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;byte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) value);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What do we get?&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                      Mode  Cnt      Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite  thrpt    5  97618.250 ± 1682.211  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite      thrpt    5  73264.856 ±  664.202  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is actually &lt;em&gt;worse&lt;/em&gt; than we had before! But why?&lt;/p&gt;
&lt;h3 id=&quot;getting-to-the-bottom-of-it&quot; tabindex=&quot;-1&quot;&gt;Getting to the bottom of it &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#getting-to-the-bottom-of-it&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Is it because of the &lt;code&gt;Integer.numberOfLeadingZeros()&lt;/code&gt; call? The answer is probably a resounding &lt;em&gt;no&lt;/em&gt; - after all, &lt;code&gt;Integer.numberOfLeadingZeros()&lt;/code&gt; is an intrinsic on at least x86_64 (the only architecture where we are running these benchmarks) and Arm. Indeed, my Zen 2 processor can process 3 &lt;code&gt;LZCNT&lt;/code&gt; instructions every cycle, so in theory this should deliver performance improvements.&lt;/p&gt;
&lt;p&gt;In isolation, we can devise a small benchmark to see if this educated guess was right:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  @&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; lzcnt&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; sum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; number&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; numbers) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      sum += (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;31&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;Integer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;numberOfLeadingZeros&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(number)) / &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; sum;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  @&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;Benchmark&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#569CD6&quot;&gt;  public&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt; int&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt; byHand&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;() {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; sum&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    for&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; value&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; :&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; numbers) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      while&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#569CD6&quot;&gt;true&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          sum++;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;          break&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        sum++;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    return&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; sum;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The results:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                      Mode  Cnt       Score       Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.byHand  thrpt    5  323063.055 ±  1759.055  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.lzcnt   thrpt    5  570563.618 ± 17726.994  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At least in isolation, this doesn&#39;t seem to be the case. But as we&#39;ll see later, this benchmark doesn&#39;t really tell us anything meaningful. Perhaps this change makes the JIT compiler more trigger-happy in a way that tanks our performance, thanks to the more traditional loop style we now employ. I&#39;m not sure.&lt;/p&gt;
&lt;h2 id=&quot;try-2-unrolling-the-loop&quot; tabindex=&quot;-1&quot;&gt;Try 2: Unrolling the Loop &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-2-unrolling-the-loop&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Okay, let&#39;s go back a step. Remember that the loop we are running could run 1 to 5 times, depending on how large the VarInt will be. We also know that the number of bytes will increase with each 7 bits in the number. Given that, what if we simply unrolled the loop, accounting for all of the cases?&lt;/p&gt;
&lt;p&gt;Here&#39;s the code:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (value &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (value &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;128&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (value &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;16384&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (value &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;2097152&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (value &amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;268435456&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;What do we get now?&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                      Mode  Cnt      Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite  thrpt    5  95870.960 ± 4328.322  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite      thrpt    5  73097.880 ± 1116.550  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite     thrpt    5  95840.321 ± 2882.220  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There&#39;s no change, but perhaps we could have expected that from naively unrolling the loop and just figuring out when certain byte lengths would be written. We can, of course, do better than that.&lt;/p&gt;
&lt;h2 id=&quot;try-3-smartly-unrolling-the-loop&quot; tabindex=&quot;-1&quot;&gt;Try 3: Smartly Unrolling the Loop &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-3-smartly-unrolling-the-loop&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s take a look at that unrolled code again. It&#39;s clearly not optimal, since it repeats a lot of the same code, including multiple calls to &lt;code&gt;ByteBuf#writeByte()&lt;/code&gt;. Can we do better than this? In fact, we can:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFF80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This looks pretty gnarly already, but let&#39;s give it a shot:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite    thrpt    5   95113.915 ±  182.119  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite  thrpt    5  124865.620 ±  550.267  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite       thrpt    5   93953.405 ± 1530.158  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s very impressive - a nearly 30% performance improvement from improving the structure of the code. Can we improve this some more?&lt;/p&gt;
&lt;h2 id=&quot;try-4-the-numberofleadingzeros-mystery-solved&quot; tabindex=&quot;-1&quot;&gt;Try 4: The &lt;code&gt;numberOfLeadingZeros&lt;/code&gt; Mystery Solved? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-4-the-numberofleadingzeros-mystery-solved&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Let&#39;s try to use &lt;code&gt;Integer.numberOfLeadingZeros()&lt;/code&gt; to optimize this function. Perhaps it will give us a bit more performance.&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; continuationBytes&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;31&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; - &lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;Integer&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;numberOfLeadingZeros&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value)) / &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (continuationBytes == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (continuationBytes == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;1&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (continuationBytes == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;2&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; (continuationBytes == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;3&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;          value &gt;&gt;&gt;= &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;I can&#39;t wait for all the performance improvements!&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite  thrpt    5  110664.096 ± 1460.675  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s not good at all. We just regressed by more than 10%.&lt;/p&gt;
&lt;h2 id=&quot;try-5-remove-the-data-dependency&quot; tabindex=&quot;-1&quot;&gt;Try 5: Remove the Data Dependency &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-5-remove-the-data-dependency&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;That was a bust. Is there something else we can do? Well, there is a data dependency. We are bit-shifting to the right by 7 bits each time then seeing if we need to continue writing bytes or not. It&#39;s possible to get a little bit more parallelism out of the CPU by knowing how much we&#39;ll bit-shift by:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;    if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;      buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;      if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;        buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;        if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;          buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;        }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;    }&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;How does this attempt fare?&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5   94480.674 ± 1389.432  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartNoDataDependencyUnrolledVarintWrite  thrpt    5  129428.934 ± 7405.911  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite                  thrpt    5  126697.664 ± 5033.494  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;It looks like the two approaches are in fact similar in performance, with the newer version performing perhaps a tad better, but the results are too noisy to know for sure.&lt;/p&gt;
&lt;h2 id=&quot;try-6-training-ourselves-in-the-dark-arts&quot; tabindex=&quot;-1&quot;&gt;Try 6: Training Ourselves in the Dark Arts &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#try-6-training-ourselves-in-the-dark-arts&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Already we found a ~30% speedup from unrolling the loop carefully, but can we do better than that still? Yes, we can. As most performance-oriented engineers know, doing things in bulk can be a very profitable optimization. Up to this point, we&#39;ve been running 1 to 5 calls to write individual bytes. It turns out that if we get a little bit creative, we can either write the entirety of the bytes up front (1, 2, or 4 bytes worth) or combine one larger writing operation with writing one byte (2 + 1 for 3 bytes, 4 + 1 for 5 bytes – VarLong writing is left as an exercise to the reader). Luckily, we don&#39;t need to handle the 2 + 1 case specially as Netty &lt;code&gt;ByteBuf&lt;/code&gt; provides a &lt;code&gt;writeMedium()&lt;/code&gt; method. In order to do this, we will instead construct the VarInt as a number, and then write it to the buffer. Let&#39;s give it a try:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;  if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | (value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeShort&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | (value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeMedium&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt; if&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; ((value &amp;#x26; (&lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0xFFFFFFFF&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)) == &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | (((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;16&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | (value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeInt&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  } &lt;/span&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#C586C0&quot;&gt;else&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; {&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;    int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;            | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeInt&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;    buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;  }&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The end result is this:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite        thrpt    5  175968.604 ± 5195.657  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite    thrpt    5   94270.376 ± 2796.116  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite  thrpt    5  124524.690 ± 2929.593  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This is an &lt;em&gt;enormous&lt;/em&gt; improvement, to say the least. From our baseline we got a nearly 1.87x speedup! But there is a reason why this is suboptimal: the above code is definitely difficult to read and understand, and it is extremely fragile – extending it to 10-byte VarLongs would be a nightmare!&lt;/p&gt;
&lt;h2 id=&quot;bonus-exact-byte-length-encoding&quot; tabindex=&quot;-1&quot;&gt;Bonus: Exact byte length encoding &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#bonus-exact-byte-length-encoding&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Quoting Startin:&lt;/p&gt;
&lt;blockquote class=&quot;font-serif&quot;&gt;
&lt;p&gt;When I went back and read it again I was surprised to find that embedded messages are length-prefixed, but the length prefix is varint encoded, which means you don’t know how many bytes you need for the length until you’ve done the serialisation, and it’s recursive.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;Startin then argues that was one reason why he considered Protocol Buffers to be bad for reporting telemetry from the edge. But for those who are stuck with VarInts like I am, you can in fact write VarInts in a sequential fashion, and even with performance slightly above the traditional approach to writing VarInts. Specifically, it is possible for us encode any number that can be encoded as a VarInt in exactly 5 bytes:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-java&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#A626A4;--shiki-dark:#4EC9B0&quot;&gt;  int&lt;/span&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt; w&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; = (value &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;24&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;7&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;16&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;      | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;14&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x3C;&amp;#x3C; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;8&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | ((value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;21&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;) &amp;#x26; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x7F&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt; | &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;0x80&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeInt&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(w);&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span style=&quot;color:#E45649;--shiki-dark:#9CDCFE&quot;&gt;  buf&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;.&lt;/span&gt;&lt;span style=&quot;color:#4078F2;--shiki-dark:#DCDCAA&quot;&gt;writeByte&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;(value &gt;&gt;&gt; &lt;/span&gt;&lt;span style=&quot;color:#986801;--shiki-dark:#B5CEA8&quot;&gt;28&lt;/span&gt;&lt;span style=&quot;color:#383A42;--shiki-dark:#D4D4D4&quot;&gt;);&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Therefore, if you are willing to inflate the size of your messages, you can write the message out sequentially. Even better, you can even improve upon this result by encoding only the maximum amount you need. In the Minecraft protocol, compressed messages are always 21-bit or less, so we can encode the length of a compressed packet in just three VarInt bytes and save ourselves a memory copy. Very neat!&lt;/p&gt;
&lt;p&gt;But performance-wise, is it worth doing that?&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite                        thrpt    5  179321.732 ± 7610.742  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.lucky5VarintWrite                         thrpt    5  113540.019 ± 6062.895  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5   95748.224 ± 2531.663  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;If you have a need for this, then yes, it even beats the traditional loop. But despite appearances, this is not only not the fastest way to write a VarInt, it also completely defeats the point of using a VarInt. But it&#39;s a neat trick that could come in handy under certain circumstances.&lt;/p&gt;
&lt;h2 id=&quot;but-this-is-just-one-processor-i-need-more-than-that&quot; tabindex=&quot;-1&quot;&gt;But this is just one processor - I need more than that! &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#but-this-is-just-one-processor-i-need-more-than-that&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I ran the tests on a DigitalOcean CPU-optimized droplet with 4GB of memory and two dedicated CPU threads of an Intel Xeon E5-2650v4. The OS is Ubuntu 20.04 but we keep using Java 11.&lt;/p&gt;
&lt;p&gt;Here&#39;s the results:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite                        thrpt    5  103837.167 ±  629.934  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5   54538.692 ± 1312.263  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartNoDataDependencyUnrolledVarintWrite  thrpt    5   76576.717 ± 1051.005  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite                  thrpt    5   76325.907 ±  855.393  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite                        thrpt    5   46513.811 ±  706.059  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite                       thrpt    5   56751.155 ±  803.914  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;These results comport with the rest of the article. As for Arm, here are the results from my M1 MacBook Pro:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite                        thrpt    5  237790.486 ±  571.134  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5  165370.092 ± 1975.949  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartNoDataDependencyUnrolledVarintWrite  thrpt    5  188349.773 ± 2062.149  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite                  thrpt    5  187717.560 ±  755.758  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite                        thrpt    5  115166.912 ±  611.680  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite                       thrpt    5  183905.054 ±  766.400  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Okay, so the Intel processor is behind, probably better explained by the fact it&#39;s clocked lower and is an older chip from the Broadwell era. But the M1 mops the floor in this particular benchmark, beating out the Ryzen 9 3900X and the Intel Xeon E5-2650v4. Why?&lt;/p&gt;
&lt;h2 id=&quot;atomic-power&quot; tabindex=&quot;-1&quot;&gt;Atomic Power &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#atomic-power&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;When we call a write function on a Netty &lt;code&gt;ByteBuf&lt;/code&gt; there are several checks that have to be performed. These are typically performed in &lt;code&gt;AbstractByteBuf#ensureWritable0()&lt;/code&gt;. Specifically:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;It checks that the written bytes after writing &lt;code&gt;minWritableBytes&lt;/code&gt; would not exceed the buffer&#39;s current capacity.&lt;/li&gt;
&lt;li&gt;It ensures that the buffer&#39;s reference count is not zero.&lt;/li&gt;
&lt;li&gt;If the check in (1) passed, we are good to go (this is considered the &amp;quot;fast path&amp;quot;).&lt;/li&gt;
&lt;li&gt;Otherwise, if the new size of the buffer would exceed the buffer&#39;s current capacity (but not its maximum capacity), it will expand the buffer.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Since our buffer size is always 5, the first check will always succeed, and since the JIT knows that the branch is always taken, that just means we&#39;re left with the reference count check as our last source of slowdown. In Netty, reference counts are always accessed and modified atomically. &lt;a href=&quot;https://twitter.com/Catfish_Man/status/1326298205034696705&quot;&gt;We know that uncontended atomic access is fast on M1&lt;/a&gt;. Does this explain the performance difference? Let&#39;s run the tests on our Ryzen processor again but with the flag &lt;code&gt;-Dio.netty.buffer.checkAccessible=false&lt;/code&gt;:&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite                        thrpt    5  158655.053 ± 3702.731  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5  101722.002 ±  331.125  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartNoDataDependencyUnrolledVarintWrite  thrpt    5  131313.391 ±  392.404  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite                  thrpt    5  146280.007 ± 1271.907  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite                        thrpt    5   80280.574 ±  636.335  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite                       thrpt    5  101123.052 ±  915.786  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;That&#39;s certainly very different. &lt;code&gt;blendedVarintWrite&lt;/code&gt; actually &lt;em&gt;lost&lt;/em&gt; a bit over 10% of its throughput, but the other byte-by-byte approaches gained at least by 8%. What happens if we run it on the M1?&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;Benchmark                                                        Mode  Cnt       Score      Error  Units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.blendedVarintWrite                        thrpt    5  237697.049 ±  304.124  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.oldVelocityVarintWrite                    thrpt    5  166456.475 ±  384.274  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartNoDataDependencyUnrolledVarintWrite  thrpt    5  190258.830 ± 1163.047  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.smartUnrolledVarintWrite                  thrpt    5  189399.626 ±  186.078  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.startinVarintWrite                        thrpt    5  116002.657 ±  364.835  ops/s&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;VarIntWriterBenchmark.unrolledVarintWrite                       thrpt    5  184978.894 ± 3182.543  ops/s&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This essentially didn&#39;t change. So we can conclude that &lt;code&gt;blendedVarintWrite&lt;/code&gt; gets most of its performance through amortizing API calling costs in the Netty API.&lt;/p&gt;
&lt;h2 id=&quot;conclusions&quot; tabindex=&quot;-1&quot;&gt;Conclusions &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#conclusions&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;It is very possible to write VarInts very quickly, on the order of close to 500 million per second on commodity consumer hardware with only a single thread.&lt;/p&gt;
&lt;p&gt;Here&#39;s all the various methods by their time per operation:&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Method&lt;/th&gt;
&lt;th&gt;Intel Broadwell&lt;/th&gt;
&lt;th&gt;AMD Zen 2&lt;/th&gt;
&lt;th&gt;Apple M1&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Baseline&lt;/td&gt;
&lt;td&gt;8.95 ns/op&lt;/td&gt;
&lt;td&gt;5.1 ns/op&lt;/td&gt;
&lt;td&gt;2.93 ns/op&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Startin&lt;/td&gt;
&lt;td&gt;10.5 ns/op&lt;/td&gt;
&lt;td&gt;6.68 ns/op&lt;/td&gt;
&lt;td&gt;4.24 ns/op&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Smart Unrolling&lt;/td&gt;
&lt;td&gt;6.4 ns/op&lt;/td&gt;
&lt;td&gt;3.92 ns/op&lt;/td&gt;
&lt;td&gt;2.6 ns/op&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Dark Arts (#6)&lt;/td&gt;
&lt;td&gt;4.7 ns/op&lt;/td&gt;
&lt;td&gt;2.78 ns/op&lt;/td&gt;
&lt;td&gt;2.05 ns/op&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;p&gt;We have sped up the writing speed on the x86 platforms by more than 80%, whereas the M1 received a more modest but still substantial 43% performance boost.&lt;/p&gt;
&lt;p&gt;I invite critiques on the &lt;a href=&quot;https://github.com/astei/varint-writing-showdown&quot;&gt;GitHub repository&lt;/a&gt; where I have published the JMH tests.&lt;/p&gt;
&lt;h2 id=&quot;licensing&quot; tabindex=&quot;-1&quot;&gt;Licensing &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/performance/how-fast-can-you-write-a-varint/#licensing&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;You are free to use any of the code snippets under the terms of the &lt;a href=&quot;https://opensource.org/licenses/MIT&quot;&gt;MIT license&lt;/a&gt;.&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Catching up on things</title>
		<link href="https://steinborn.me/posts/catching-up-on-things/"/>
		<updated>2021-05-08T00:00:00Z</updated>
		<id>https://steinborn.me/posts/catching-up-on-things/</id>
		<content type="html">&lt;p&gt;It&#39;s been a long time coming, but I have bitten the bullet. My blog, once a fairly stodgy thing I hadn&#39;t updated in over 2 years has received a total redesign with a focus on extremely fast load times. My goal is function over form and I think I have delivered that. Of course, I did make some concessions to keep the format largely sane. But while my blog sat empty, many things have changed in my life.&lt;/p&gt;
&lt;h2 id=&quot;the-new-blog&quot; tabindex=&quot;-1&quot;&gt;The new blog &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#the-new-blog&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;My previous site was built on &lt;a href=&quot;https://gohugo.io/&quot;&gt;Hugo&lt;/a&gt;. Now I wave goodbye to Hugo and say hello to &lt;a href=&quot;https://www.11ty.dev/&quot;&gt;Eleventy&lt;/a&gt;. Eleventy is just as fast and much more flexible for my needs. I found Hugo to be somewhat limiting even as some of its features like image resizing were rather nice.&lt;/p&gt;
&lt;h2 id=&quot;how-the-coronavirus-pandemic-has-affected-me&quot; tabindex=&quot;-1&quot;&gt;How the coronavirus pandemic has affected me &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#how-the-coronavirus-pandemic-has-affected-me&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I&#39;ve been touched by the pandemic myself, even having a scare back in October. I have managed to avoid catching the virus, however I have family that have managed to catch the virus. Thankfully, they are fine and we haven&#39;t had to attend any funerals. Yet.&lt;/p&gt;
&lt;p&gt;The ongoing (as of this writing, of course) coronavirus pandemic has aroused a new sense out of myself. It has led me to some truly unique opportunities but it has shown my limitations and some of the past choices I&#39;ve made were not optimal. I&#39;m working to correct that this year.&lt;/p&gt;
&lt;h2 id=&quot;a-summary-of-my-2020&quot; tabindex=&quot;-1&quot;&gt;A summary of my 2020 &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#a-summary-of-my-2020&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I didn&#39;t stop working during 2020, of course - I made sure to keep myself busy with projects.&lt;/p&gt;
&lt;h3 id=&quot;block-by-blockwest&quot; tabindex=&quot;-1&quot;&gt;Block By Blockwest &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#block-by-blockwest&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I had the opportunity to participate in the Block by Blockwest event that was originally going to occur on April 25th, 2020, but was postponed to May 16th, 2020. This was largely because of higher than anticipated demand. In the span of 3 weeks, a new team (including me) managed to get Block by Blockwest up and running on a more scalable setup and the event finally succeded in holding a maximum of approximately 1,700 concurrent players. Perhaps my most important contribution would be the rapid deployment of the Velocity Minecraft proxy at scale.&lt;/p&gt;
&lt;h3 id=&quot;velocity&quot; tabindex=&quot;-1&quot;&gt;Velocity &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#velocity&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;For this, you could consider the announcements on the &lt;a href=&quot;https://forums.velocitypowered.com/c/announcements/12&quot;&gt;Velocity forum&lt;/a&gt; to be my &lt;em&gt;de facto&lt;/em&gt; blog for all of 2020, but 2020 saw the release of the Velocity 1.1.x series, which included a slew of new features and a sustained effort at optimizing the proxy as much as possible. The optimization work paid off handsomely, since larger Minecraft networks including LemonCloud, The Archon, and several others switched to Velocity. In particular, networks that have switched to Velocity from BungeeCord derivatives have reported that CPU utilization often goes down drastically.&lt;/p&gt;
&lt;h3 id=&quot;fabric&quot; tabindex=&quot;-1&quot;&gt;Fabric &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#fabric&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I also started dabbling in Fabric modding! My first ever Fabric mod was &lt;a href=&quot;https://github.com/VelocityPowered/CrossStitch&quot;&gt;CrossStitch&lt;/a&gt; but I also developed and released &lt;a href=&quot;https://github.com/astei/krypton&quot;&gt;Krypton&lt;/a&gt; and &lt;a href=&quot;https://github.com/astei/lazydfu&quot;&gt;LazyDFU&lt;/a&gt; which have seen some popularity. It&#39;s only a matter of time to see how much Minecraft will continue to capture my interest given recent developments.&lt;/p&gt;
&lt;h2 id=&quot;where-i-am-now&quot; tabindex=&quot;-1&quot;&gt;Where I am now &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#where-i-am-now&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Of course, that was last year. Now it is 2021. We&#39;ve already seen quite a bit happen, especially with America seemingly filrting with yet another far-right authoritarian disaster thanks to the Capitol insurrection, egged on by the now-former president of the United States himself! How fun.&lt;/p&gt;
&lt;h3 id=&quot;branch&quot; tabindex=&quot;-1&quot;&gt;Branch &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#branch&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The most exciting news I have to share this year is that since February I am now employed by &lt;a href=&quot;https://branch.gg/&quot;&gt;Branch&lt;/a&gt;. Of course, this was somewhat assisted by the fact Dayton has worked with me before on another project of his, Statscraft (later purchased by Tebex). I am mostly taking this opportunity to begin shifting away from Minecraft into other interests.&lt;/p&gt;
&lt;p&gt;Branch is in an industry that could have never been viable without the COVID-19 pandemic: virtual, spatially-oriented offices. Work-from-home is destined to outlast the COVID-19 pandemic and I&#39;m proud to be a part of that trend. As a company founded by gamers trying to stake a middle grouhd between &lt;em&gt;Minecraft&lt;/em&gt; but for enterprise and &lt;em&gt;Zoom&lt;/em&gt; but not boring, Branch is quite unique. I am looking forward to working with Branch!&lt;/p&gt;
&lt;h3 id=&quot;slowing-down-my-minecraft-involvement&quot; tabindex=&quot;-1&quot;&gt;Slowing down my Minecraft involvement &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#slowing-down-my-minecraft-involvement&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I&#39;m still committed to most of my Minecraft projects but I&#39;m winding down my involvement on some of them.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;NuVotifier&lt;/strong&gt; has been effectively in maintenance mode for a while. This will continue to be the case. It has matured and doesn&#39;t need many changes. Bug fixes and support for newer versions of Minecraft are the main priority at this point.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;SuperbVote&lt;/strong&gt; is also largely mature. There are some bugs that need to be fixed, but it&#39;s mature. Therefore it is now in maintenance mode only, with only bugs being fixed and features only considered when sent as a pull request.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The following projects will continue:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Velocity&lt;/strong&gt; will continue to evolve and be developed, but it was always my intention to turn over control of the project to other members of the community. There is now a second active developer on the project that cares deeply about Velocity and we both cooperate. However, right now the project still relies almost completely on me.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;LazyDFU&lt;/strong&gt;, &lt;strong&gt;CrossStitch&lt;/strong&gt;, and &lt;strong&gt;Krypton&lt;/strong&gt; will continue to be developed. They are relatively new, but LazyDFU can be considered somewhat stable now (only needing minor adjustments for future Minecraft updates).&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;college&quot; tabindex=&quot;-1&quot;&gt;College &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#college&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I have been ambivalent about college since late 2019. That ambivalence has now snowballed into an active distaste for it. The reason is simple: I haven&#39;t been intellectually stimulated enough by my classes.&lt;/p&gt;
&lt;p&gt;Therefore I have decided to put college on hold for the coming year, working on Branch and some personal projects. The first few days of not having class have been extremely liberating to me. I&#39;ve been able to focus on things that really stimulate me - see for instance my recent work on writing VarInts very quickly. It&#39;s been exciting to be liberated from college work. I want to keep this up and have a good balance of work and leisure for once.&lt;/p&gt;
&lt;h3 id=&quot;as-for-the-blog&quot; tabindex=&quot;-1&quot;&gt;As for the blog... &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/catching-up-on-things/#as-for-the-blog&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This blog will get periodic updates. I can not and will not promise when things will get posted, though I have provided &lt;a href=&quot;https://steinborn.me/feed/feed.xml&quot;&gt;an RSS feed&lt;/a&gt; in case you want to subscribe. I promise to write about interesting things.&lt;/p&gt;
&lt;p&gt;I also decided to change up the hosting situation. My previous blog was hosted with &lt;a href=&quot;https://workers.cloudflare.com/sites&quot;&gt;Cloudflare Workers Sites&lt;/a&gt;. Workers is a great product, but I did not wind up using its full functionality. I decided to use another recently-introduced Cloudflare solution, &lt;a href=&quot;https://pages.cloudflare.com/&quot;&gt;Cloudflare Pages&lt;/a&gt;. With the fast build times of Eleventy, I think it&#39;s a good match!&lt;/p&gt;
</content>
	</entry>
	
	<entry>
		<title>Tuning Minecraft for OpenJ9</title>
		<link href="https://steinborn.me/posts/tuning-minecraft-for-openj9/"/>
		<updated>2019-05-25T00:00:00Z</updated>
		<id>https://steinborn.me/posts/tuning-minecraft-for-openj9/</id>
		<content type="html">&lt;h2 id=&quot;disclaimer&quot; tabindex=&quot;-1&quot;&gt;Disclaimer &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#disclaimer&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Mineteria is long gone. It stopped using OpenJ9 in April 2020. I have limited interest in Minecraft nowadays. I&#39;m keeping this post up since lots of links to it exist on the internet. &lt;em&gt;Follow the advice in this post at your own risk.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Andrew Steinborn, October 16, 2022&lt;/em&gt;&lt;/p&gt;
&lt;h2 id=&quot;original-introduction&quot; tabindex=&quot;-1&quot;&gt;Original introduction &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#original-introduction&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;https://mineteria.com/&quot;&gt;Mineteria&lt;/a&gt; ran the &lt;a href=&quot;https://www.eclipse.org/openj9/&quot;&gt;OpenJ9&lt;/a&gt; JVM from July 2018 to April 2020. Our own experience with OpenJ9 has led us to continually tweak our set up and ensure that our servers are not subjected to long garbage collection pauses.&lt;/p&gt;
&lt;p&gt;Our servers (which span long-lived lobbies, to a creative-like server with frequent chunk loading, to short-lived game servers), while likely not representative of all Minecraft servers, have been using these flags for many months and have virtually eliminated any issues with garbage collection pauses.&lt;/p&gt;
&lt;p&gt;My research started with &lt;a href=&quot;https://aikar.co/2018/07/02/tuning-the-jvm-g1gc-garbage-collector-flags-for-minecraft/&quot;&gt;Aikar&#39;s flags for G1&lt;/a&gt; and moved towards how to apply a similar set of flags for OpenJ9. He can not be thanked enough for both inspiring my OpenJ9 garbage collection research and providing a well-tested set of flags to improve server performance.&lt;/p&gt;
&lt;h2 id=&quot;why-use-openj9&quot; tabindex=&quot;-1&quot;&gt;Why use OpenJ9? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#why-use-openj9&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The biggest reason why OpenJ9 appealed to me was because it was container-friendly. This was important as the Linux kernel was reaping our Java processes. We were strapped for cash and so upgrading VM instances was a last resort option, and we did not have the capability to turn off OOM killing in our containers because our setup was based on a managed Kubernetes solution (at the time, it was Google Kubernetes Engine - we have since moved to DigitalOcean Kubernetes).&lt;/p&gt;
&lt;p&gt;Up until then, we had been using the standard HotSpot VM. HotSpot is a very proven JVM implementation, but only in Java 10 did it become container-aware. OpenJ9 goes much further and has a flag (&lt;code&gt;-Xtune:virtualized&lt;/code&gt;) which optimizes the JVM for lower CPU usage. Funny enough, my adventure with OpenJ9 began when I was tuning our HotSpot-based setup for better garbage collection performance with Aikar&#39;s flags in preparation for our beta launch in July 2018.&lt;/p&gt;
&lt;p&gt;This primary consideration helped sell us, but OpenJ9 has also helped deliver lower memory usage, which is important for Minecraft servers as they often have a lot of chunks loaded. In our particular case, we have cloud virtual servers focused on providing more CPU and varying memory needs for each server, so a set of flags that was easily tuned was crucial.&lt;/p&gt;
&lt;h3 id=&quot;why-does-it-matter-for-me&quot; tabindex=&quot;-1&quot;&gt;Why does it matter for me? &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#why-does-it-matter-for-me&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Not everyone uses containers, but everyone can still benefit from OpenJ9&#39;s many unique features compared to OpenJ9:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Idle garbage collection&lt;/strong&gt;: when your server is idle, OpenJ9 can perform a full garbage collection to clean out the tenured space and nursery without negatively impacting performance.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Shared classes and ahead-of-time compilation&lt;/strong&gt; mean that your server can restart and ramp back up much more quickly compared to HotSpot.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Lower memory usage&lt;/strong&gt; compared to HotSpot.&lt;/li&gt;
&lt;li&gt;The best part is that in most cases, &lt;strong&gt;you can just drop in OpenJ9 and your plugins will &amp;quot;just work&amp;quot;&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;tuning-the-openj9-vm&quot; tabindex=&quot;-1&quot;&gt;Tuning the OpenJ9 VM &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#tuning-the-openj9-vm&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Now with some reasons why to use OpenJ9 out of the way, we can turn to the Minecraft-tuned garbage collection settings for OpenJ9. These settings will result in &lt;strong&gt;short&lt;/strong&gt; (usually 1 to 5 millisecond) GC pauses, which is quite good. The memory settings will need to be tweaked depending on your memory usage, but I&#39;m providing a shell script that will take care of the entire process for you.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;TL;DR&lt;/strong&gt;: Here&#39;s a shell script that takes care of the entire process. Just drop it in your server directory as, e.g. &lt;code&gt;start.sh&lt;/code&gt;, edit it to tweak your memory setting, &lt;code&gt;chmod +x start.sh&lt;/code&gt;, and then &lt;code&gt;./start.sh&lt;/code&gt;. It will &amp;quot;just work&amp;quot; with no further set up required. For your convenience, I&#39;ve also made it &lt;a href=&quot;https://steinborn.me/extra/openj9-minecraft.sh&quot;&gt;wgettable&lt;/a&gt;.&lt;/p&gt;
&lt;pre class=&quot;shiki shiki-themes one-light dark-plus&quot; style=&quot;background-color:#FAFAFA;--shiki-dark-bg:#1E1E1E;color:#383A42;--shiki-dark:#D4D4D4&quot; tabindex=&quot;0&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#!/bin/bash&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Properly tunes a Minecraft server to run efficiently under the&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# OpenJ9 (https://www.eclipse.org/openj9) JVM.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Licensed under the MIT license.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;## BEGIN CONFIGURATION&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# HEAP_SIZE: This is how much heap (in MB) you plan to allocate&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#            to your server. By default, this is set to 4096MB,&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#            or 4GB.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;HEAP_SIZE=4096&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# JAR_NAME:  The name of your server&#39;s JAR file. The default is&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#            &quot;paperclip.jar&quot;.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#            Side note: if you&#39;re not using Paper (http://papermc.io),&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;#            then you should really switch.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;JAR_NAME=paperclip.jar&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;## END CONFIGURATION -- DON&#39;T TOUCH ANYTHING BELOW THIS LINE!&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;## BEGIN SCRIPT&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Compute the nursery size.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NURSERY_MINIMUM=$(($HEAP_SIZE / 4))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;NURSERY_MAXIMUM=$(($HEAP_SIZE * 2 / 5))&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;# Launch the server.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;CMD=&quot;java -Xms${HEAP_SIZE}M -Xmx${HEAP_SIZE}M -Xmns${NURSERY_MINIMUM}M -Xmnx${NURSERY_MAXIMUM}M -Xgcpolicy:balanced -Xdisableexplicitgc -jar ${JAR_NAME}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;echo &quot;launching server with command line: ${CMD}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;${CMD}&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;line&quot;&gt;&lt;span&gt;## END SCRIPT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;With the default settings, your server will launch with &lt;code&gt;java -Xms4096M -Xmx4096M -Xmns1024M -Xmnx1638M -Xgcpolicy:balanced -Xdisableexplicitgc -jar paperclip.jar&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;We will break down each of these flags, but there is other important context to get out of the way.&lt;/p&gt;
&lt;h3 id=&quot;sizing-the-heap&quot; tabindex=&quot;-1&quot;&gt;Sizing the heap &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#sizing-the-heap&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The first and natural set of flags to turn to are our humble friends &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt;. &lt;strong&gt;You should set &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt; to the same value&lt;/strong&gt;, whether you use HotSpot or OpenJ9.&lt;/p&gt;
&lt;p&gt;In the case of OpenJ9, this is even more important because OpenJ9 tends to be quite conservative in requesting more memory from the operating system. In our experience, when the heap is insufficient to satisfy allocations, OpenJ9 will prefer to perform aggressive garbage collection first and only when it can&#39;t free up a significant amount of memory will it request more from the operating system. This is bad because it will degrade server performance due to frequent garbage collection pauses.&lt;/p&gt;
&lt;p&gt;Now we need to actually decide on the heap size. The best policy to take here is to allocate as much as you reasonably can, but make sure to leave enough room for the operating system and for the JVM&#39;s overhead, otherwise the operating system may kill the server to free up memory. For instance, if you have a 4GB VPS, you should stay in the 2-3GB range so that the operating system will still run smoothly and the JVM can allocate overhead.&lt;/p&gt;
&lt;h3 id=&quot;selecting-a-gc-policy&quot; tabindex=&quot;-1&quot;&gt;Selecting a GC policy &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#selecting-a-gc-policy&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;OpenJ9 features five different garbage collection policies:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;gencon&lt;/code&gt;: This is the default GC policy in OpenJ9. This policy breaks the Java heap into a &lt;strong&gt;nursery&lt;/strong&gt; and a &lt;strong&gt;tenured&lt;/strong&gt; space. All objects are allocated initially into the nursery. If an object survives a certain number of collections while in the nursery, it will be moved into the tenured space, which is only collected when it is full.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;balanced&lt;/code&gt;: This is the closest analogue that OpenJ9 has to the HotSpot G1 garbage collector. It breaks the heap into &lt;strong&gt;regions&lt;/strong&gt;, each of which is individually managed and garbage-collected.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;optthruput&lt;/code&gt;: This policy is similar to &lt;code&gt;optavgpause&lt;/code&gt; but does not mark concurrently, resulting in longer pauses. Because of this, it is a poor choice for a Minecraft server.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;optavgpause&lt;/code&gt;: This is a fully concurrent mark-and-sweep collector which aims to minimize the pause time. It is however mostly suited for very large heaps.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;metronome&lt;/code&gt;: This is a policy available on AIX and x64 Linux. It is interesting as it places a focus on minimizing GC pause times to ensure precise response times. However, we will not need this policy for Minecraft.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;For Minecraft 1.12.2 and below, the right answer was the default &lt;code&gt;gencon&lt;/code&gt; policy. However, with 1.13 and above, &lt;code&gt;gencon&lt;/code&gt; proves to be a bad fit for servers due to the severely increasedstrain on the garbage collector subsystem. The &lt;code&gt;balanced&lt;/code&gt; policy is the next-best.&lt;/p&gt;
&lt;h3 id=&quot;sizing-the-nursery&quot; tabindex=&quot;-1&quot;&gt;Sizing the nursery &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#sizing-the-nursery&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Now that we have selected our desired GC policy and sized our heap, we need to tune the behavior of the garbage collector.&lt;/p&gt;
&lt;p&gt;The size of the nursery is key to improving Minecraft performance. By default, &lt;code&gt;-Xmns&lt;/code&gt; is 25% of &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmnx&lt;/code&gt; is 25% of &lt;code&gt;-Xmx&lt;/code&gt;. Since you will be setting &lt;code&gt;-Xms&lt;/code&gt; and &lt;code&gt;-Xmx&lt;/code&gt; to the same value. This means that by default, the nursery will never grow. Since Minecraft tends to allocate lots of very short-lived objects, this will result in very frequent garbage collections and will tenure garbage objects more often, degrading server performance.&lt;/p&gt;
&lt;p&gt;Instead, you should set &lt;code&gt;-Xmns&lt;/code&gt; to 25% of your &lt;code&gt;-Xmx&lt;/code&gt; and &lt;code&gt;-Xmnx&lt;/code&gt; to 40% of your &lt;code&gt;-Xmx&lt;/code&gt;. This allows OpenJ9 to expand the nursery when needed and is a more realistic nursery size for a Minecraft server.&lt;/p&gt;
&lt;h2 id=&quot;disabling-explicit-gc&quot; tabindex=&quot;-1&quot;&gt;Disabling explicit GC &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#disabling-explicit-gc&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The other flag we provide is &lt;code&gt;-Xdisableexplicitgc&lt;/code&gt;, which protects us from plugins that think they&#39;re being smart by asking the garbage collector to do a collection when one is not needed, and may actually hurt server performance later on by bringing a full GC cycle closer.&lt;/p&gt;
&lt;h2 id=&quot;other-settings-to-change&quot; tabindex=&quot;-1&quot;&gt;Other settings to change &lt;a class=&quot;direct-link&quot; href=&quot;https://steinborn.me/posts/tuning-minecraft-for-openj9/#other-settings-to-change&quot; aria-hidden=&quot;true&quot;&gt;#&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;If you are on a VPS or some sort of cloud environment, you should add in the &lt;code&gt;-Xtune:virtualized&lt;/code&gt; flag. This tunes OpenJ9 to reduce CPU and memory usage.&lt;/p&gt;
&lt;p&gt;My script does not configure OpenJ9&#39;s ahead-of-time compiler or the shared classes functionality. This can improve startup times, but we can&#39;t fully exploit this feature due to the unique peculiarities of our setup.&lt;/p&gt;
</content>
	</entry>
</feed>
