<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:itunes="http://www.itunes.com/dtds/podcast-1.0.dtd" xmlns:googleplay="http://www.google.com/schemas/play-podcasts/1.0"><channel><title><![CDATA[Minsoo Choo]]></title><description><![CDATA[FreeBSD Kernel Developer • CHERI Alliance Ambassador • University of Waterloo Computer Engineering (Class of ’30)]]></description><link>https://minsoo.io</link><image><url>https://substackcdn.com/image/fetch/$s_!v4hh!,w_256,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F251537e3-ac76-4a30-adf6-1072fe518d0d_1280x1280.png</url><title>Minsoo Choo</title><link>https://minsoo.io</link></image><generator>Substack</generator><lastBuildDate>Sun, 23 Aug 2026 23:40:06 GMT</lastBuildDate><atom:link href="https://minsoo.io/feed" rel="self" type="application/rss+xml"/><copyright><![CDATA[Minsoo Choo]]></copyright><language><![CDATA[en]]></language><webMaster><![CDATA[minsoochoo@substack.com]]></webMaster><itunes:owner><itunes:email><![CDATA[minsoochoo@substack.com]]></itunes:email><itunes:name><![CDATA[Minsoo Choo]]></itunes:name></itunes:owner><itunes:author><![CDATA[Minsoo Choo]]></itunes:author><googleplay:owner><![CDATA[minsoochoo@substack.com]]></googleplay:owner><googleplay:email><![CDATA[minsoochoo@substack.com]]></googleplay:email><googleplay:author><![CDATA[Minsoo Choo]]></googleplay:author><itunes:block><![CDATA[Yes]]></itunes:block><item><title><![CDATA[I'm now a FreeBSD committer]]></title><description><![CDATA[Yippee!]]></description><link>https://minsoo.io/p/im-now-a-freebsd-committer</link><guid isPermaLink="false">https://minsoo.io/p/im-now-a-freebsd-committer</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 31 Jul 2026 16:56:11 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9a88cab9-8250-4d39-b5a7-98d5666d7101_1200x800.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Today&#8217;s post is a short one because 1) it&#8217;s an announcement, and there&#8217;s nothing really new, and 2) final exams are coming up next week, so I don&#8217;t have time to write a lengthy blog post.</p><p>On July 24th, I received an email from srcmgr@ informing me that I had been granted a src commit bit. After that, the FreeBSD accounts team created a freefall.FreeBSD.org account and a FreeBSD email address (mchoo@) for me. Then, I created patches for <a href="https://reviews.freebsd.org/D58507">src</a> and <a href="https://reviews.freebsd.org/D58508">doc</a> to complete <a href="https://docs.freebsd.org/en/articles/committers-guide/#commit-steps">the steps for new committers</a>. They landed in the FreeBSD repositories yesterday (<a href="https://cgit.freebsd.org/src/commit/?id=a28c2890f44877b6399f1a87bd6e67634757b08c">src</a>, <a href="https://cgit.freebsd.org/doc/commit/?id=8821b5318e0794f8f6e0e0f1a4e21fbdf305e24f">doc</a>).</p><p>As I had an issue with my current PGP key, I created a new one and updated <a href="https://minsoo.io/about">my about page</a> to reflect it. This is my third PGP key. My first one was RSA 4096, and I created a new one a year ago because of the Ed25519 hype. It was stored on a YubiKey, but I forgot to back up the original master key. The key was moved to the YubiKey permanently, where keys are writable but not readable for security. After realizing this recently, I created a new Ed25519 PGP key.</p><p>This time, I not only backed up the original master key, but also created separate subkeys for authentication, encryption, and signing. I issued revocation certificates for the RSA 4096 key and the first Ed25519 key so that I can announce that they are no longer in use and prevent others from tampering with them. I hope this is the last time in my life that I have to create a new PGP key and revoke the old one.</p><p>Lastly, I would like to thank everyone in the FreeBSD community who has helped me on my journey to becoming a committer, especially Ed Maste (emaste@), Warner Losh (imp@), and my mentor, John Baldwin (jhb@).</p>]]></content:encoded></item><item><title><![CDATA[Why I Chose Metal API]]></title><description><![CDATA[In the end, the deciding factor is ease of use]]></description><link>https://minsoo.io/p/why-i-chose-metal-api</link><guid isPermaLink="false">https://minsoo.io/p/why-i-chose-metal-api</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 26 Jul 2026 06:23:09 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/137321bd-9ba2-44f8-880f-233344b04253_1200x800.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In the <a href="https://minsoo.io/p/vulkan-sucks">previous post</a>, I explained why I didn't choose Vulkan for future graphics programming projects even though I'd had high expectations. For the last few days, I've been learning the Metal API (Metal 4.0 specifically), and in this post I'll explain why I decided to choose Metal for future projects.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;aa1fddcd-ac3b-45fd-9e10-a9e60b61fcbe&quot;,&quot;caption&quot;:&quot;Usually my tone is gentle when I write titles. Instead of Vulkan Sucks, usually I would've written titles like Why Vulkan Is Not the Right One for Me or Why Vulkan Falls Behind Other Graphics APIs. But I'm making this post an exception. Vulkan sucks.&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Vulkan sucks&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:167787206,&quot;name&quot;:&quot;Minsoo Choo&quot;,&quot;bio&quot;:&quot;FreeBSD Kernel Developer &#8226; CHERI Alliance Ambassador &#8226; University of Waterloo Computer Engineering (Class of &#8217;30)&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/930ec2b0-2266-4098-a89e-76652d7b0c68_2769x2769.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2026-07-24T16:49:35.624Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/acd15803-2cc6-4649-9b7c-3bcab76a5c06_1200x675.png&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://minsoo.io/p/vulkan-sucks&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:208337762,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:1,&quot;publication_id&quot;:8751651,&quot;publication_name&quot;:&quot;Minsoo Choo&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!v4hh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F251537e3-ac76-4a30-adf6-1072fe518d0d_1280x1280.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>The <a href="https://github.com/mchoo7/renderer">renderer</a> project now has the Metal backend, and I used metal-cpp to wire it up with GLFW (I'll explain later why metal-cpp is painful). At first, I was leaning towards starting with Metal 3 and then transitioning to Metal 4, because Metal 4 is more verbose and gives more optimization opportunities like Vulkan, but since I didn't have enough time, I decided to start with Metal 4 right away. Then I created a <a href="https://github.com/mchoo7/metal-template">project</a> which is a native macOS application with MetalKit. This is the base template I will use over the metal-cpp one, for the reasons I will mention later.</p><p>For the renderer project, I asked Claude to write the whole backend first so I could see how Metal works. Then I read several resources on Metal 3+ and overhauled the code to reflect those. For the native application, Claude wrote everything other than <code>Renderer.swift</code>. After I made an initial version of <code>Renderer.swift</code>, I asked Claude to make it use native Swift syntax because my Swift code was in a C++ style. Unlike the Vulkan backend, I handwrote most parts of the code this time because I enjoyed writing Metal code, but due to time constraints like FreeBSD scheduler improvements and final exam preparation, I had to leave the rest to Claude and move on.</p><h2>Favourite things about Metal</h2><p>The first thing that impressed me was the API. Compared to OpenGL and Vulkan, everything was straightforward and easy to remember. Metal 4 became more verbose compared to the previous versions, but it&#8217;s still nowhere close to Vulkan when it comes to verbosity and boilerplates. It offers most of the optimization opportunities that Vulkan does and still has better ergonomics and design. I also love the Metal Shading Language (MSL). To me, it looks even better than Vulkan&#8217;s Slang.</p><p>The tooling around Metal is also nice. Xcode&#8217;s Metal debugger and Instruments&#8217; Metal System Trace are fantastic tools to work with Metal. The fact that I can integrate SwiftUI without extra rendering logic is another advantage over other graphics APIs that need GLFW. The ImGui rendering logic has always required too much extra code, while SwiftUI provides sharper fonts and a more native-feeling design.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!p3Ls!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!p3Ls!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 424w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 848w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 1272w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!p3Ls!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png" width="1456" height="809" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:809,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:676717,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:&quot;https://minsoo.io/i/208513261?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!p3Ls!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 424w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 848w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 1272w, https://substackcdn.com/image/fetch/$s_!p3Ls!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F5af97b77-f0b3-4455-a0fb-a5dddee5da3a_2024x1124.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>glTF renderer with Metal 4 and SwiftUI</em></figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Feq-!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Feq-!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 424w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 848w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Feq-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png" width="1456" height="844" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:844,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1607486,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://minsoo.io/i/208513261?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!Feq-!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 424w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 848w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 1272w, https://substackcdn.com/image/fetch/$s_!Feq-!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F9e8bdb33-529a-43c1-a912-41b9bffe073d_3104x1800.png 1456w" sizes="100vw"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Xcode's Metal debugger on the glTF renderer</em></figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!CNtX!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!CNtX!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 424w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 848w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 1272w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!CNtX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png" width="1456" height="941" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:941,&quot;width&quot;:1456,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:1357613,&quot;alt&quot;:null,&quot;title&quot;:null,&quot;type&quot;:&quot;image/png&quot;,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:&quot;https://minsoo.io/i/208513261?img=https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png&quot;,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="" srcset="https://substackcdn.com/image/fetch/$s_!CNtX!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 424w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 848w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 1272w, https://substackcdn.com/image/fetch/$s_!CNtX!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd1b8f1b2-52b4-4f57-abca-ffcd5ce5c7f7_2792x1804.png 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption"><em>Instruments' Metal System Trace on the glTF renderer</em></figcaption></figure></div><p>These easy-to-use GUI tools help me save time otherwise spent studying old and complicated debugging and tracing tools for other graphics APIs and operating systems. This is a huge plus for me because I&#8217;m not planning to pursue graphics programming as a job but just as a hobby, and I&#8217;m already busy with my university studies and FreeBSD work.</p><h2>Don&#8217;t use metal-cpp</h2><p>Apple provides <a href="https://developer.apple.com/metal/cpp/">C++ Metal headers</a> for video game developers, where C++ is the dominant language. However, there are a few shortcomings that I encountered while developing.</p><p>First, the integration with window libraries like GLFW is bad. If I remember correctly, Apple used to provide essential functions for getting <code>CAMetalLayer</code> through metal-cpp-extensions obtained from the <a href="https://developer.apple.com/metal/LearnMetalCPP.zip">Learn Metal with C++</a> sample code. Now those functions are omitted from the header, so people have two choices left: either fetching the old headers from a random GitHub repository or writing their own <code>objc_msgSend</code> hack to interact with Objective-C code from C++. Neither is ideal.</p><p>Second, the API isn't written in a C++ style; it feels like they transcribed Objective-C to C++. For example, descriptors are initialized by <code>MTL*Descriptor::alloc()&#8594;init()</code>. You need an <code>NS::AutoReleasePool</code> around the render loop, and it becomes more obvious that you are writing Objective-C in a C++ file. If your company already has an established C++ coding style, metal-cpp will keep being the special one that stands out from the rest of the code, adding to the burden of both reading and writing.</p><p>When I started the native Metal application project, I could immediately tell that the developer experience was way better on Swift with Xcode. Not only did I not need to care about allocations, but Xcode's tab suggestions were also way superior to CLion's. I could call the Metal debugger right away without locating an external executable, and everything felt so smooth. So please, unless you have an outstanding reason to avoid Swift or Objective-C and need pure C++, I recommend going with them and forgetting about metal-cpp completely.</p><h2>Conclusion</h2><p>What I expect from my graphics projects is very simple: just real-time rendering where I don&#8217;t need to spend too much energy on the technical side. As I said before, I just want to visualise atmospheric and space environments for my own interest, so being cross-platform or microtuning through low-level APIs like Vulkan is not that important. All I want is that when my work is over and I&#8217;m lying on the sofa, I can just prototype stuff on my MacBook and be happy with the visual itself.</p><p>In this scenario, OpenGL&#8217;s design was archaic. None of my machines had a Windows installation. I tried Vulkan, but it was too painful. WebGPU is still immature and no one knows when the spec will be finalized. Then I tried Metal, and I was very satisfied. Although metal-cpp was hard to use, the native Swift API was good enough. The tooling around the Metal API, such as the Xcode Metal debugger and Instruments, was very satisfactory. Because of this, there is no reason for me to choose a graphics API other than Metal.</p><p>I&#8217;m not saying everyone should use Metal. For beginners, there are way more resources around OpenGL, and I think it will be the same for a while, as it&#8217;s the only cross-platform API that is accessible to beginners. Some might prefer Vulkan because it provides opportunities to squeeze maximum performance out of a GPU. Some might use Direct3D because it has good integration with the Windows ecosystem, like the Win32 API and the PIX debugger. But to me, it seems like ease of use is the most important thing, above all those attractive features.</p><h2>Resources</h2><p>The following are the resources I used for the projects:</p><ul><li><p><a href="https://developer.apple.com/metal/LearnMetalCPP.zip">Learn Metal with C++</a> (This one is very outdated, but it&#8217;s the only metal-cpp resource from Apple)</p></li><li><p><a href="https://developer.apple.com/metal/cpp/">Getting started with Metal-cpp</a></p></li><li><p><a href="https://developer.apple.com/documentation/metal">Apple Metal Documentation</a></p></li><li><p><a href="https://developer.apple.com/videos/play/wwdc2025/205/">Discover Metal 4</a></p></li><li><p><a href="https://developer.apple.com/documentation/metal/drawing-a-triangle-with-metal-4">Drawing a triangle with Metal 4</a></p></li><li><p><a href="https://metalbyexample.com/metal-4/">Getting Started with Metal 4</a> and <a href="https://github.com/metal-by-example/metal-4-basics">sample code</a></p></li></ul>]]></content:encoded></item><item><title><![CDATA[Vulkan sucks]]></title><description><![CDATA[The worst API I've ever dealt with]]></description><link>https://minsoo.io/p/vulkan-sucks</link><guid isPermaLink="false">https://minsoo.io/p/vulkan-sucks</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 24 Jul 2026 16:49:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/acd15803-2cc6-4649-9b7c-3bcab76a5c06_1200x675.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><span>Usually my tone is gentle when I write titles. Instead of </span><em>Vulkan Sucks</em><span>, usually I would've written titles like </span><em>Why Vulkan Is Not the Right One for Me</em><span> or </span><em>Why Vulkan Falls Behind Other Graphics APIs</em><span>. But I'm making this post an exception. Vulkan sucks.</span></p><p>A few weeks ago, I found an <a href="https://blog.maximeheckel.com/posts/on-rendering-the-sky-sunsets-and-planets/">article</a> on rendering the atmosphere and the universe. Because I have been interested in graphics programming, specifically real-time rendering for games, since high school, I decided to do some graphics projects in the future. As I'm transferring to mathematical physics, I thought it would be nice to visualize physical phenomena such as the bending of light around a black hole, or realistic rendering of the Earth and the universe, using a graphics API.</p><p>Since I have already learned the basic concepts of real-time rendering and OpenGL usage through <a href="https://learnopengl.com">LearnOpenGL</a>, I wanted to go on with a "modern" graphics API for two reasons. First, most OpenGL resources are written with GLSL and binding APIs, and I hate those two. Secondly, even though there are SPIR-V and Direct State Access in OpenGL 4.6, my MacBook doesn't support the latest OpenGL specification, as macOS ceased updating its OpenGL implementation at OpenGL 4.1 and moved to Metal a decade ago.</p><p>The first candidate was DirectX 11/12. They have great tooling backed by Microsoft, tons of resources online, and have been battle-proven for more than a decade. But they're Windows-only, and I removed all my Windows installations a few months ago because I hate Windows 11, so I didn't pick DirectX 11/12.</p><p>The second candidate was Vulkan. It's cross-platform, a choice of open-source enthusiasts, and supports a niche shader language called Slang. I had such high expectations because it was the successor to OpenGL, but eventually it disappointed me a lot while I was learning it. I wrote a <a href="https://github.com/mchoo7/renderer">glTF model renderer with multiple backends</a> (OpenGL, Vulkan, Metal coming soon) to compare how these APIs work and choose one for my future projects. In this blog post I will show why I was disappointed by Vulkan.</p><p>Before I start criticizing Vulkan, I want to note that the project was heavily written by an LLM, although I had to modify a lot of code (I will discuss this in the bonus section). So if you are an LLM-paranoid person who believes that what I wrote here can't be trusted just because I didn't write the whole code myself (i.e. you can't learn if an LLM wrote some of your code), close this window. Seriously, reading this article will be a waste of time for you. The sole goal of the project was comparing the ergonomics of different graphics APIs, and I used an LLM because not only did I not have much time (I have a bunch of scheduled work right now), but it turned out that Vulkan is painful to write and I would have faced burnout without the LLM's help. When I need to practice a graphics API in the future, either for a job or research, I will rewrite this from scratch.</p><h2>Tooling issues</h2><p>I went through so many tooling issues with Vulkan. The Khronos Group is a typical example of a high school or university group project. Everyone wants their project to succeed, but no one wants to put in maximum effort. DirectX and Metal don't have this problem because Microsoft and Apple have full responsibility for managing their APIs.</p><p>The first issue is the Vulkan SDK. I encountered a bug in the Slang CMake config shipped by the SDK, where project configuration fails because the Slang CMake config points to the wrong directory. I found a <a href="https://vulkan.lunarg.com/issue/view/6a22f8d6c2cf0451740b5e54">bug report</a> on the issue tracker and the maintainer acknowledged that this is a regression in the latest release. This is good, but the problem is this: the maintainer said the issue will be fixed in the next SDK release. What? There is a misconfigured CMake file that basically makes all projects depending on Slang fail, and the fix will come in the next release, which will arrive in a few months? I was quite surprised that they didn't make a patch release for this regression, so I had to write a hack in my CMakeLists.txt file to work around this issue.</p><p><span>The second issue is the graphics debugger. The de facto debugger for OpenGL and Vulkan is RenderDoc, a piece of software maintained by an individual. I encountered an issue where RenderDoc couldn't capture a frame on Linux, and it turned out that I hadn't built with XWayland (GLFW has a </span><code>GLFW_PLATFORM_X11</code><span> flag for this). Now imagine this: what happens if there is a bug that only occurs on Wayland? How are developers supposed to debug this if they are planning to ship their application as a Wayland application? Finding the root cause would be a nightmare because they cannot use a graphics debugger for Wayland. RenderDoc is used by many graphics programmers, some from big game studios making video games with Vulkan, but surprisingly no one has stepped up to add Wayland support. Remember I said the Khronos Group is a typical group project? This is exactly what I mean: more than a decade has passed since Vulkan was made, but the tooling is still bad because everyone only wants to make the application that can be monetized.</span></p><h2>Problems with the API itself</h2><p>The Vulkan API is too verbose. Sometimes far too much. Things like <code>sType</code> in <code>*CreateInfo</code> structures, memory allocation, device and logical device handling, swapchain, image, and image view management, and so on.</p><p>Some of the boilerplate around <code>*CreateInfo</code> structures and object destruction can be reduced by using <code>vulkan.hpp </code>instead of <code>vulkan.h</code>. The RAII version of <code>vulkan.hpp</code> reduces the boilerplate further. Memory allocation can be simplified with VulkanMemoryAllocator, and the startup boilerplate can be reduced with vk-bootstrap; these were what I used for my project.</p><p>But the issue is that many of the essential Vulkan libraries aren&#8217;t managed directly by the Khronos Group. Both VMA and vk-bootstrap are third-party libraries, but I believe these should be first-party libraries led by the Khronos Group.</p><p>I also think this level of verbosity is useless for ordinary users. Yes, there might be some users who need to squeeze maximum performance out of the API, but I think that&#8217;s a minority. For ordinary users, things like image transitions (stage mask, access mask, and layout) and memory types (host, GPU, optimal, etc.) are pretty useless. A common excuse I see on the internet from Vulkan proponents is that people can choose OpenGL if they feel Vulkan is too verbose, but don&#8217;t say that. We all know OpenGL&#8217;s design is archaic, and Vulkan could&#8217;ve been a higher-level API similar to Metal.</p><p>The Khronos Group was right to judge that many OpenGL drivers were poorly written. Some decisions were good, like moving from GLSL to SPIR-V, because many drivers had different parsing rules. But the idea of letting the graphics programmer do the low-level optimization is bogus. The micro-optimization cases they worried about only apply to a few pieces of software, but by making that mandatory, now all the burden is on the graphics programmer and everyone needs to write the same boilerplate. In most cases this ends up being unnecessary premature optimization that doesn&#8217;t bring any visible improvement, and developers waste time and resources. This is critical for indie game studios, where they have limited time and money.</p><h2>What did the Khronos Group miss?</h2><p>Vulkan is a common graphics driver interface, not an application programming interface. The designers of Vulkan only focused on reducing the burden of device driver programmers and did not consider application programmers at all. This might be a successful interface for GPU manufacturers, but it&#8217;s a total failure for application programmers. There is a reason why Apple was involved in the creation of Vulkan but chose to make their own API in the end. They definitely knew Vulkan was too complicated for the average application programmer, and this was the right move. I thank Apple for creating an alternative, and this is one of the rare occasions where I thank Apple.</p><p>People suggest learning graphics programming with OpenGL and then moving to Vulkan, but this is a bad idea. Not only do you need to start with an archaic API that you won&#8217;t use in most cases, but the transition from OpenGL to Vulkan is hard because there are too many discrepancies. The pipeline and synchronization concepts should be enough. Device-level optimization should be left to advanced programmers who really need to squeeze out maximum performance (e.g. simulations and AAA video games).</p><p>The minimum they should do here is make a simpler version of Vulkan with less boilerplate. They could implement a graphics API library on top of Vulkan, like Zink, and the majority of graphics programmers would spend less time writing boilerplate and more time implementing the actual logic, improving productivity. This is crucial for small indie game studios.</p><p>Unfortunately, I don&#8217;t think this will happen. The Khronos Group will keep focusing on adding more extensions to Vulkan without considering the true pain point for many programmers. That has been the case over the last decade.</p><h2>Conclusion</h2><p>First, to the Vulkan proponents who wonder why more game studios don&#8217;t make video games based on Vulkan:</p><p>It&#8217;s simply because Vulkan sucks. If Vulkan were at least at DirectX&#8217;s or Metal&#8217;s level, I think the majority of video games would run on Vulkan. Before criticizing the game studios that use DirectX only, ask yourself whether Vulkan is actually superior to, or at least on par with, other modern graphics APIs.</p><p>Next, to the Khronos Group:</p><p>Stop adding more extensions to the API specification and focus on the actual product. Improve the tools and spend more time testing them (the aforementioned Slang config incident should not happen again). Make an API that does one thing great before moving on. We want a graphics API, not a weird mix of graphics and GPGPU APIs that isn&#8217;t good at either.</p><p>I&#8217;m currently working on the Metal backend of the project and it seems better than Vulkan, so I guess my choice of graphics API for the future will be Metal. I&#8217;ll lose the cross-platform advantage for sure, but it&#8217;s better than getting headaches from Vulkan&#8217;s downsides. Metal has issues too, specifically with the C++ implementation. I will discuss this in a following post.</p><h2>Bonus: Claude sucks</h2><p>I noticed this while using Claude Code for this project: Claude (or Claude Code) has become worse in the last couple of weeks. Claude Code seems to find and fetch many resources from the internet but fails to make use of them. One example of this is writing CMakeLists.txt for me. Even when I gave it a link to a reference configuration, and the only thing Claude Code needed to do was copy that and make some small modifications, it spent three minutes thinking and came up with something I didn&#8217;t ask for.</p><p>It writes many comments in the code, but the actual code is garbage. Even a novice graphics programmer like me can notice it. It seems to optimize the code prematurely, but does not accomplish what I asked for. It even does things like multiplying view and projection matrices on the CPU instead of on the GPU, which is clearly wrong, and I had to manually revamp that part by hand in the end.</p><p>At this point Claude Code is degrading my productivity, so I decided not to renew my Claude subscription and to move to ChatGPT and Codex. It probably plagued me more than Vulkan did during this project.</p><p><em><span>Off-topic: I watched </span>The Odyssey<span> with my friends yesterday and it was pretty good. All six of us gave the movie 10/10 (some 20/10). Definitely a recommended watch. I watched it in normal IMAX, and I think the experience could've been much better if I'd watched the 15/70 version, so if you haven't watched the movie I suggest going for IMAX 70mm.</span></em></p>]]></content:encoded></item><item><title><![CDATA[I'm Transferring to Mathematical Physics]]></title><description><![CDATA[Why I'm leaving Computer Engineering]]></description><link>https://minsoo.io/p/im-transferring-to-mathematical-physics</link><guid isPermaLink="false">https://minsoo.io/p/im-transferring-to-mathematical-physics</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 12 Jul 2026 01:04:50 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/23a6cef4-10f8-4cd6-ba0b-cba1fb86fab0_1200x675.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Today I submitted a transfer form for Mathematical Physics. In this article, I'll talk about why I joined Computer Engineering in the first place and what made me decide to transfer to Mathematical Physics.</em></p><h2>Why I chose Computer Engineering in the first place?</h2><p>It has been clear that I was going to be a programmer since I entered high school. I've contributed to FreeBSD since then, and although I paused contributions from time to time due to coursework, I'm at the point now where I can call myself a FreeBSD developer.</p><p>So back in the fall of Grade 12, it was obvious that I was going to apply to computer-related programs for university. I got an acceptance letter in March 2025 from uWaterloo Computer Engineering and I gladly accepted the offer.</p><h2>What's wrong with the Computer Engineering program?</h2><p>The first term (1A) was fine and I didn't have any complaints back then. I found myself enjoying maths and physics courses more than engineering ones, but it wasn't a big deal. I genuinely believed that the second term (1B) would be fine as well and the Computer Engineering program was my way.</p><p>But I was wrong.</p><h3>Engineering courses are boring</h3><p>I mean&#8230; you can&#8217;t enjoy the program if you don&#8217;t like the courses, right?</p><p>A few weeks after the start of 1B, I was confident that I was enjoying maths and physics courses more than engineering ones. Don&#8217;t get me wrong: the professors are fine, it&#8217;s just the courses. <em>Calculus 2</em>, <em>Discrete Mathematics</em>, and <em>Electricity and Magnetism</em> were fine, but <em>Electric Circuits</em> and <em>Digital Circuits and Systems</em> were not. However, I like writing digital circuits in Verilog at the same time, so what&#8217;s wrong with me for disliking the digital circuits course?</p><p>The answer is that learning engineering through courses isn&#8217;t my preference. I&#8217;ve taught myself programming since Grade 6 and I am luckily at the level where I can have technical discussions with experts in this area. Because I taught myself programming through books and projects, not school or online courses, engineering has become something I learn through hands-on experience, not through academic evaluations like exams or quizzes.</p><p>Also, the Computer Engineering program covers a broad field and it involves things like electric circuit courses that I&#8217;m not interested in. I love electrodynamics but not circuits. Finding the electric field at a certain point apart from a uniform charge distribution was fun, but calculating voltage, resistance, and current was the most boring math work I&#8217;ve ever done in my life.</p><p>And when upper years told me that we don&#8217;t have &#8220;fun&#8221; courses (e.g. OS, compiler, uarch) until the third year in CS and CE, I decided not to waste two years on courses that I don&#8217;t enjoy.</p><h3>The Faculty of Engineering (or the ECE department) doesn&#8217;t align with my expectation</h3><p>This year I was going to be an undergraduate research assistant (URA) under a CS professor but got rejected by the ECE administration. It turns out that the Faculty of Engineering doesn&#8217;t allow first-year students to become URAs. NO EXCEPTIONS. This is funny because the CS department grants exceptions for URAs when there is an explicit agreement from the supervisors (i.e. professors). Isn&#8217;t university a place for research? Why do they gate-keep the first years from doing research? This is totally absurd.</p><p>Meanwhile, the Faculty of Engineering is very into the idea of co-op and most engineering programs here are co-op only (i.e. no regular program offered). It&#8217;s okay because students can have experience before they graduate. However, if they are aware that the current job market is bad, they should give more time to students for job hunting instead of plaguing us with a huge amount of coursework. Like other programs, full-time engineering programs have five courses per term, but they seem to forget that 1) we have to learn way more stuff (no first-year calculus course covers more than MATH 119, which is basically a crammed version of Calculus 2 and 3) and 2) our schedule is full of tutorials and labs. Many students are skipping tutorials because they need to prepare for job interviews, and no wonder they get low academic grades in quizzes and exams. Do the people who architected this program know how it feels to have an 8:30 to 16:30 class schedule every day and need to do problem sets and lab work after that? Do they even validate the feasibility of the course schedule before making it effective?</p><p>As a result, Computer Engineering has become a contradictory program that&#8217;s operated by a university but does not aim for research, and promotes co-op but does not give enough time for job search. A similar metaphor here is <a href="https://en.wikipedia.org/wiki/Holy_Roman_Empire">&#8220;le saint empire romain n&#8217;&#233;tait en aucune mani&#232;re ni saint, ni romain, ni empire.&#8221;</a></p><h3>Engineering programs are expensive</h3><p>Look at the <a href="https://uwaterloo.ca/future-students/financing/tuition">uWaterloo tuition page</a>. Engineering programs have the highest tuition, which is $19,000 per year. Computer science is at $16,000 and mathematics and science programs are at $9,000.</p><p>I would be fine if it is truly worth the cost. However, the ECE 455 lab sessions were cancelled this term because there wasn't enough budget. For your information, it is an embedded software course. An embedded software course without a lab? This doesn't make sense. Each student pays $19,000 a year for an engineering program. The faculty sold the name of E7 and changed it to PSE because they got <a href="https://uwaterloo.ca/engineering/news/alumni-foundation-gifts-20m-waterloo-engineering">$20M from some organization</a>. And what? They don't have enough money for one-term lab sessions? That doesn't sound right. Even after OSAP, students spend a lot on tuition every year, and labs are still getting cancelled. Also don't forget that engineering programs are the most popular ones at uWaterloo.</p><h2>So why Mathematical Physics?</h2><p>I have loved watching stars since I was young, as my mum took me to observatories quite often. I liked the numbers related to stars (e.g. <a href="https://youtu.be/GoW8Tf7hTGA?si=lE6WyVtQ5ksWmm6H">size comparison of famous stars</a>) and astrophysics videos that explained things like why light bends in gravity. When I did my first high school physics course in Grade 11, I really liked it. My teacher was great at teaching it, so no way I disliked his course.</p><p>At the time I made university applications, I was in the Waterloo dream: making a huge amount of money through co-ops and continuing that after graduation. But GenAI and layoffs happened, so the dream is now hard to achieve. I made lots of connections here at Waterloo, but that wasn&#8217;t enough to justify staying in Computer Engineering. This is when I realized that I came to university for the wrong reasons. In my humble opinion, university is for learning knowledge, not for money or networking. Before, I was treating university just as a graduation certificate giver, which is completely false. It makes no sense to burn five years of tuition and living costs of around one million dollars just for a piece of paper.</p><p>On the other hand, learning physics in university makes sense to me. I&#8217;m interested in it but don&#8217;t know it quite well, so I have the passion to pursue it. Every single course that I read from the curriculum seemed to be interesting, so I can justify staying in the program for four years. Lastly, physics teaches you how to think. What&#8217;s behind the formula, why it happens, and how to play with those formulas. It&#8217;s not just plug-n-play.</p><h2>What next?</h2><p>First of all, it&#8217;s highly unlikely that I will work in a physics-related field after graduation. I will not pursue graduate degrees in physics either, as I believe undergraduate topics are enough to appease my curiosity for now. Yet, I might write an undergraduate thesis in graphics shaders like <a href="https://blog.maximeheckel.com/posts/on-rendering-the-sky-sunsets-and-planets/">this</a>.</p><p>Mathematical Physics gives nine electives, and I can always overload or take more courses in spring breaks. For ECE courses, I&#8217;m planning to take <em>Embedded Microprocessor Systems</em>, <em>Computer Architecture</em>, and <em>Digital Hardware Systems</em>. The rest will be pure mathematics and thesis courses for my graphics shaders idea. After I graduate, I might work in the industry or do a PhD in operating systems or microarchitecture.</p>]]></content:encoded></item><item><title><![CDATA[1 Year of Shaving with Safety Razors]]></title><description><![CDATA[Why I'm happy with switching to safety razors]]></description><link>https://minsoo.io/p/1-year-of-shaving-with-safety-razors</link><guid isPermaLink="false">https://minsoo.io/p/1-year-of-shaving-with-safety-razors</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 26 Jun 2026 01:40:08 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/69c777c0-223c-4ec8-be83-4540e6a40eb5_1200x684.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>This isn&#8217;t like other posts I&#8217;ve written so far. It&#8217;s not about software, university, or a job. This time I&#8217;m writing about shaving, something that most men in the world do for their entire lives.</p><p>So you might wonder: what are safety razors? Most people use electric razors (shavers) or cartridge razors. When I just started shaving, I used disposable razors but realized that it created too much waste while the shaving experience wasn&#8217;t good. I could go for shavers or cartridge razors, but they seemed to be too expensive.</p><p>Then I found safety razors on the internet. In brief, safety razors are similar to cartridge razors, but it only has one blade which is not enclosed in a plastic case. It&#8217;s also less protective and it takes more time to shave than shavers and cartridge razors, which is why it was replaced by those two in modern days. Thus, when people use safety razors, they have specific reasons to do so.</p><h2>Why do people use safety razors?</h2><p>Modern shavers or cartridge razors come with technologies that cut your hair as much as possible. The issue is that they sometimes cut too much. When razors pull hair and cut it, they actually cut part of the hair that was below the skin. Sometimes the hair fails to grow out of the hair follicle and gets stuck in it. This is what we call ingrown hair, which causes inflammation and severe itching. Safety razors are free from this problem because they don&#8217;t pull the hair when they cut it. However, this also means that it will leave some hair visible after you shave, which is a trade-off. I&#8217;ve had skin troubles since I was very young, and ingrown hair was too annoying to deal with especially when it came with pimples on my face. After switching to safety razors, I&#8217;ve had fewer issues with skin troubles on face.</p><p>On the UX side, shaving with safety razors is more fun compared to other types of razors. It&#8217;s like Vim: it&#8217;s not beginner-friendly but once you get used to it, it gives a better experience compared to other types of razors. Because it&#8217;s easy to cut your skin with safety razors, everyone accidentally cut their skin in the beginning and even experienced people make that mistake sometimes. But once you get experienced, shaving with safety razors is quite fun because you have complete control over shaving. It&#8217;s also more convenient when you need fine control over the hair. For example, removing hairs around the lips is much easier with safety razors over cartridge and disposable razors because you only need to care about one blade, not layers of blades.</p><p>The cost-effectiveness of safety razors is controversial. Of course, the minimum initial setup requires a safety razor, blades, aftershave (or an alum block), a shaving brush, shaving soap, and a shaving mug. My initial setup costed over $400. However, razor blades for safety razors are extremely cheap compared to the ones for cartridge razors or disposable razors. You can buy ten of them at $6 in Canada and each blade can be used several times. In the last one year, I only spent $25 on razor blades.</p><p>Safety razors and shaving brushes are expensive, but you can use them forever if they are kept in good maintenance. I started with Merkur Progress 500 because it has configurable aggressiveness and I didn&#8217;t know the proper aggressiveness for my skin. I settled with aggressiveness between 2 and 3 (5 is the maximum) and have enjoyed it for the past one year. Unfortunately, I didn&#8217;t know how to maintain it properly, so the threading got rusty and loose and it ended up being unusable. As my second safety razor, I was considering between Merkur 37C and Muhle R41 but chose Merkur 37C because people said R41 is too aggressive while my blades from Feather is already one the most aggressive blades in the world. So I ordered 37C a few days ago and it arrived today. It gave me a better shaving experience over the Progress 500. Unlike Progress 500, 37C is a slanted razor, so it requires less force to shave. In other words, it requires fine control so usually it&#8217;s not recommended for beginners. Moreover, 37C is an open-comb razor, so cleaning up the remaining shaving soap and hair on the razor is much easier compared to closed-comb razors like Progress 500.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kk_U!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kk_U!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kk_U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp" width="300" height="300" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/a33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:300,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;MERKUR PROGRESS 500 Classic Razor - Cuchiller&#237;a Moreno&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="MERKUR PROGRESS 500 Classic Razor - Cuchiller&#237;a Moreno" title="MERKUR PROGRESS 500 Classic Razor - Cuchiller&#237;a Moreno" srcset="https://substackcdn.com/image/fetch/$s_!Kk_U!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 424w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 848w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 1272w, https://substackcdn.com/image/fetch/$s_!Kk_U!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fa33a3083-e4aa-43f4-b41d-9576b2d88ee6_1024x1024.webp 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Merkur Progress 500. Victim of my immature maintenance skills.</figcaption></figure></div><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!35pQ!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!35pQ!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 424w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 848w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!35pQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg" width="334" height="268.9437751004016" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:401,&quot;width&quot;:498,&quot;resizeWidth&quot;:334,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Merkur 37C Slant Bar Safety Razor&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Merkur 37C Slant Bar Safety Razor" title="Merkur 37C Slant Bar Safety Razor" srcset="https://substackcdn.com/image/fetch/$s_!35pQ!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 424w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 848w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!35pQ!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fef9cfcfe-33f4-4fc0-8833-6071da1d25e3_498x401.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Merkur 37C. My new razor. Open-comb and slanted.</figcaption></figure></div><p>Safety razors are also good for the environment compared to others because they don&#8217;t have any plastic components. Also the only thing that you need to dispose of regularly are razor blades which are just a piece of metal.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!xlcD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!xlcD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!xlcD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg" width="288" height="288" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1024,&quot;width&quot;:1024,&quot;resizeWidth&quot;:288,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;Feather 81s Extra Sharp Double Edge Razor Blades (10 pcs) - Feather -  Cosmetics - Razor Blades, For Shaving, Shaving - Gentleman Store&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="Feather 81s Extra Sharp Double Edge Razor Blades (10 pcs) - Feather -  Cosmetics - Razor Blades, For Shaving, Shaving - Gentleman Store" title="Feather 81s Extra Sharp Double Edge Razor Blades (10 pcs) - Feather -  Cosmetics - Razor Blades, For Shaving, Shaving - Gentleman Store" srcset="https://substackcdn.com/image/fetch/$s_!xlcD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 424w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 848w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!xlcD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F56b31040-d0e5-408a-969a-1c84ce82d942_1024x1024.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Feather razor blades. Ranked as the most aggressive one. I&#8217;ve been using this since the beginning of my safety razor journey.</figcaption></figure></div><h2>Roadmap for shaving</h2><p>I&#8217;ll keep using Merkur 37C for a few more years as I&#8217;m very satisfied with it. When it breaks, I&#8217;ll switch to Muhle R41 or a straight razor if I feel I need more aggressiveness for shaving.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!r7PD!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!r7PD!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!r7PD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg" width="310" height="310" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/ce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1456,&quot;width&quot;:1456,&quot;resizeWidth&quot;:310,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;M M&#220;HLE Muhle R41 Open Comb Safety Razor - No Blades Included : Amazon.ca:  Beauty &amp; Personal Care&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="M M&#220;HLE Muhle R41 Open Comb Safety Razor - No Blades Included : Amazon.ca:  Beauty &amp; Personal Care" title="M M&#220;HLE Muhle R41 Open Comb Safety Razor - No Blades Included : Amazon.ca:  Beauty &amp; Personal Care" srcset="https://substackcdn.com/image/fetch/$s_!r7PD!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 424w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 848w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!r7PD!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fce69ccf1-cc19-4b17-9d30-a21a681e6098_2000x2000.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Muhle R41. Ranked as the most aggressive razor. Candidate as my next razor.</figcaption></figure></div><p>In other words, you won&#8217;t see this type of article for a while.</p>]]></content:encoded></item><item><title><![CDATA[Why I moved from LaTeX to Typst]]></title><description><![CDATA[and where LaTeX is still relevant]]></description><link>https://minsoo.io/p/why-i-moved-from-latex-to-typst</link><guid isPermaLink="false">https://minsoo.io/p/why-i-moved-from-latex-to-typst</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Tue, 16 Jun 2026 02:04:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/22c70c66-e6ea-4d99-a9d9-6ac11300fbc8_1200x901.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>Trivia: Typst 0.15 was <a href="https://typst.app/blog/2026/typst-0.15">released</a> while writing this blog post!</em></p><p>There are myriads of documentation formats. At least I have encountered plain text (<code>.txt</code>), reStructuredText, Markdown, AsciiDoctor, mandoc, DOCX, Apple Pages, Google Docs, and LaTeX over the last year for different purposes. The first five are usually used for technical documentation related to programming like the FreeBSD handbook or source code documentation. The next three are for school stuff such as collaborating on a project report or writing English essays. I find that different formats and software have their own strengths, so it&#8217;s obvious why I use so many formats for writing: there is no such thing as the best format in writing.</p><p>But LaTeX is different. So far, there hasn&#8217;t been any competitor that is appealing enough to replace LaTeX. Although LaTeX is very inconvenient, no alternatives could overcome its ecosystem. But finally I discovered something that can be its replacement: Typst.</p><h2>Pain Points of LaTeX</h2><p>So what&#8217;s wrong with LaTeX, a de-facto standard format for writing technical reports, papers, and dissertations? Here are the issues:</p><ul><li><p>Slow compilation, no incremental build</p></li><li><p>Intermediate files like <code>.aux</code> during compilation that make my workspace dirty</p></li><li><p>Difficult to learn</p></li><li><p>Compilation log issues (hard to interpret, notorious &#8220;Underfull \hbox&#8221;)</p></li><li><p>Needs too many delimiters, thus worsening readability</p></li></ul><p>The first two are obvious; I don&#8217;t think I need to explain them. For the third point: LaTeX is definitely harder than simple languages like Markdown or reStructuredText and WYSIWYG editors like Microsoft Word. But still, it&#8217;s unnecessarily complicated, and Typst solves the problem. We&#8217;ll visit that point again later.</p><p>Now let&#8217;s take a look at the last two points.</p><h3>Abstruse compilation log</h3><p>While working on my BSDCan paper, I got the following error message:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">Underfull \hbox (badness 10000) in paragraph at lines 308--314
\OT1/pcr/m/n/10 hmp_state.total_capacity \OT1/ptm/m/n/10 dur-ing ini-tial-iza-tion
/Users/minsoochoo/Documents/BSDCan 2026 - HMP/hmp.tex:318: Missing $ inserted.
&lt;inserted text&gt; 
                $</code></pre></div><p>What was the issue? Here&#8217;s what I had in line 318:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">Each score is a single scalar value: each CPU exposes exactly two
scores, indexed by \texttt{enum score_type}:</code></pre></div><p>Yes, I forgot a delimiter <code>\</code> between &#8220;score&#8221; and the following underscore. If you were experienced in LaTeX, you would&#8217;ve noticed it easily. If not, you might have wondered why it triggered that error message. The point is that the error message was kinda useless here to see what triggered it.</p><p>But that&#8217;s just part of the problem. The whole log I got from the compiler was 497 lines long, and most of them were &#8220;Underfull \hbox&#8221; warnings. That warning is very annoying because it&#8217;s not an issue most of the time but takes up a huge part of the log, making identifying issues way harder.</p><h3>Needs too many delimiters</h3><p>This is part of my BSDCan paper in LaTeX:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">Providers register themselves at \texttt{SI\_SUB\_SMP} via two parallel
macros: \texttt{HMP\_CAPACITY\_PROVIDER\_DECLARE} and
\texttt{HMP\_SCORE\_PROVIDER\_DECLARE}.  Each hooks a \texttt{SYSINIT}
handler that calls the corresponding registration routine
(\texttt{hmp\_capacity\_provider\_register()} or
\texttt{hmp\_score\_provider\_register()}) and ...</code></pre></div><p>In programming, underscores are used frequently, mainly due to namespacing. Whenever I introduce new functions or variables in my papers, I need to use delimiters so the compiler doesn&#8217;t spit out incomprehensible error messages. Now you would ask, &#8220;Why not just live with it?&#8221; The fact is that my eyes hurt even with a paper of seven pages in length. One day, I&#8217;ll need to write a thesis or longer papers. These delimiters make my eyes tired during proofreading, and as you may know, writers do proofreading multiple times (I repeated proofreading and revising more than seven times for that BSDCan paper).</p><p>I don&#8217;t have that issue with Typst. In Typst, I simply write:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">Providers register themselves at `SI_SUB_SMP` via two parallel
macros: `HMP_CAPACITY_PROVIDER_DECLARE` and
`HMP_SCORE_PROVIDER_DECLARE`. Each hooks a `SYSINIT`
handler that calls the corresponding registration routine
(`hmp_capacity_provider_register()` or
`hmp_score_provider_register()`) and</code></pre></div><p>How simple is that, right?</p><p>Another advantage of not having delimiters for underscores is that copy-pasting from source code requires less work. And again, if I miss one delimiter, the compiler will complain in a way I can&#8217;t understand.</p><h2>So why Typst?</h2><p>Remember I said LaTeX is hard to learn? It&#8217;s because many developers these days learn Markdown as their first documentation language since it&#8217;s widespread in the OSS world. And when they encounter LaTeX, it feels like learning a new language without any connection to the ones you already know. Analogy here: an Anglophone is likely to learn French more easily than CJK languages.</p><p>Typst doesn&#8217;t share the same grammar as Markdown, but at least it&#8217;s similar. Let&#8217;s see some examples:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;plaintext&quot;,&quot;nodeId&quot;:null}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-plaintext">// Typst
# Heading 1
## Heading 2
### Heading 3
*Bold*
_Italic_
`Monospace`

// ... while in LaTeX,
\section{Heading 1}
\subsection{Heading 2}
\paragraph{Heading 3}
\textbf{Bold}
\textit{Italic}
\texttt{Monospace}</code></pre></div><p>I admit that LaTeX is more consistent: every command starts with a backslash. But if you are coming from Markdown, you would admit that Typst is easier to start with. As a university student who does OS development as a hobby, I don't have time to learn a documentation language that completely differs from the ones that I already know. As a student in a STEM field and as a developer attending many conferences, I would definitely need to learn one of them. And considering my time constraints, it's obvious why I chose it over mastering LaTeX.</p><p>Another minor thing: I found that <a href="https://marketplace.visualstudio.com/items?itemName=myriad-dreamin.tinymist">Typst&#8217;s VSCode extension</a> is better than the <a href="https://marketplace.visualstudio.com/items?itemName=James-Yu.latex-workshop">VSCode LaTeX Workshop extension</a>. Unlike the LaTeX extension, the Typst extension doesn't compile the source into a PDF until I trigger it manually, but it shows a PDF preview instead. Thanks to Typst's superior compilation speed, the latency between save and update on the preview tab is better, too. And finally, the Typst extension automatically scrolls the PDF preview when I put my cursor on different parts of the document, and when I click a part in the preview, the cursor in the editor window automatically moves to the equivalent point (although this doesn't work well when macros are involved).</p><h2>Where would I still use LaTeX?</h2><p>But Typst cannot replace LaTeX completely. LaTeX already has a rich ecosystem, and many journals provide templates in LaTeX and only accept papers in LaTeX. Even arXiv only accepts LaTeX, although there is an ongoing effort to accept Typst as well (PDF is also accepted, but it has too many downsides compared to LaTeX).</p><p>Take my BSDCan paper as an example. Because it&#8217;s a conference paper, I&#8217;m going to submit a PDF generated from the LaTeX version. Typst&#8217;s <a href="https://typst.app/universe/package/charged-ieee">charged-ieee</a> template still has some minor style issues. They don&#8217;t stand out, but when I put it side by side with other articles from the original IEEE template, it stands out too much. Also, the lack of a <code>\thanks{}</code> command made me hesitate to make a switch.</p><p>So I&#8217;ll use LaTeX when I have to, like I&#8217;m forced to use Google Docs when collaborating with my friends for university projects.</p><h2>What I&#8217;ll use Typst for</h2><p>I'll use Typst for anything else. I already converted my r&#233;sum&#233; to Typst. Originally it was in the famous <a href="https://www.overleaf.com/latex/templates/jakes-resume/syzfjbzwjncs">Jake&#8217;s Resume</a> LaTeX template, but I converted it to a similar Typst template called <a href="https://typst.app/universe/package/basic-resume/">basic-resume</a>. It's not a 1:1 equivalent, and I still like the original styling, but the convenience of Typst surpasses that minor styling issue. So I'll stick with that template until a 1:1 equivalent comes out.</p><p>Lastly, I thank the Typst developers for creating such a wonderful language.</p>]]></content:encoded></item><item><title><![CDATA[First Co-op Term Recap]]></title><description><![CDATA[Long Live FreeBSD!]]></description><link>https://minsoo.io/p/first-co-op-term-recap</link><guid isPermaLink="false">https://minsoo.io/p/first-co-op-term-recap</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 26 Apr 2026 15:52:54 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/0abace27-c45b-4003-a1a6-ad4154ca6a48_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Most undergraduate students at the University of Waterloo are drawn to the school by its co-op program. Beyond helping cover tuition and living expenses for the following term, co-op provides r&#233;sum&#233;-worthy experience that pays dividends in future placements and post-graduation job searches. The program isn't without its drawbacks as there are no real breaks between terms and the competition can be intense, but it has given countless students hands-on experience that simply can't be replicated in a classroom.</p><p>For my first co-op term (one of six), I joined the FreeBSD Foundation as a Junior Software Developer Intern. I had been contributing to FreeBSD since May 2021, so I came in with an existing project backlog and a list of ideas I wanted to pursue. My supervisor, Ed Maste (emaste@), gave me the freedom to drive my own roadmap, which made the term especially productive.</p><h2>Main Projects</h2><p>I focused on two primary areas this term: HMP (heterogeneous multi-processing) scheduling, and improvements to LLDB kernel debugging.</p><h3>HMP Scheduling</h3><p>I wrote the initial patch for the&nbsp;<code>hmp(4)</code>&nbsp;framework, which serves as an interface between the provider (which reports CPU state) and the scheduler. This work will be presented at BSDCan 2026, and I've also been drafting an accompanying paper in LaTeX.</p><h3>LLDB Kernel Debugging</h3><p>The goal here was to bring LLDB to feature parity with KGDB for FreeBSD kernel debugging. This had originally been proposed as a Google Summer of Code project, but since no suitable candidate was found, I picked it up as part of my co-op work.</p><p>The work included fixing significant bugs such as kernel debugging on FreeBSD 14+ on arm64 being completely broken. I also extended support to less common architectures like riscv and ppc64le. By the end of the term, every supported platform on FreeBSD 14+ works, with the exception of i386 and armv7, which have limited support. These changes will ship in LLVM 23, and I plan to backport them to FreeBSD's in-tree LLVM as well.</p><h2>Exploratory Work</h2><p>I also spent time on two exploratory projects that didn't reach a meaningful outcome before my last day:</p><p><strong>Forgejo CI scripts.</strong>&nbsp;FreeBSD developers are currently evaluating Forgejo as a potential successor to Phorge for our source forge. Due to limited hardware resources on my end, I wasn't able to run as many script experiments as I'd hoped.</p><p><strong>EEVDF scheduler.</strong>&nbsp;This was a side project I used as a testbed to evaluate how far LLM-assisted development ("vibe coding") could take me. I'll go into more detail in a separate post, but the short version is that even Claude Code with Opus 4.6 got me only about 70% of the way to what I wanted.</p><h2>Acknowledgements</h2><p>First and foremost, thank you to&nbsp;<strong>Ed Maste (emaste@)</strong>, Senior Director of Technology at the Foundation and my co-op supervisor. Despite a heavy workload, Ed consistently looked out for me and the other co-op students, pointed me to useful resources, and tagged the right reviewers on my Phabricator revisions. I wouldn't have been able to land nearly as many changes on the FreeBSD and LLVM sides without his support.</p><p>Thank you to&nbsp;<strong>Li-wen Hsu (lwhsu@)</strong>&nbsp;for rebuilding the network setup at the Kitchener office, maintaining and upgrading the FreeBSD clusters, and organizing AsiaBSDCon 2026.</p><p>Thanks to&nbsp;<strong>Siva Mahadevan (siva@)</strong>&nbsp;for troubleshooting network issues at the Foundation, recovering my desktop after a panic from a -CURRENT update, and supervising the three of us co-op students.</p><p>On the FreeBSD project side, thanks to&nbsp;<strong>Olivier Certner (olce@)</strong>,&nbsp;<strong>Konstantin Belousov (kib@)</strong>,&nbsp;<strong>Warner Losh (imp@)</strong>, and&nbsp;<strong>John Baldwin (jhb@)</strong>&nbsp;for reviewing my patches and offering constructive feedback.</p><p>On the LLDB side, thanks to&nbsp;<strong>Jessica Clarke (jrtc27@)</strong>,&nbsp;<strong>Sheng-yi Hung (aokblast@)</strong>, and&nbsp;<strong>David Spickett (@DavidSpickett)</strong>&nbsp;from Arm for reviewing my FreeBSD kernel debugging patches.</p><p>Finally, thank you to the HR team at the Foundation for supporting the co-op students and helping arrange my travel grant for AsiaBSDCon 2026.</p>]]></content:encoded></item><item><title><![CDATA[AsiaBSDCon 2026 Recap]]></title><description><![CDATA[First time in Taiwan!]]></description><link>https://minsoo.io/p/asiabsdcon-2026-recap</link><guid isPermaLink="false">https://minsoo.io/p/asiabsdcon-2026-recap</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 27 Mar 2026 15:31:20 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/6e399be7-02fe-4b11-8dd1-6ce8029f692f_2000x1334.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Last week I was in Taipei, Taiwan, for the FreeBSD Developer Summit and AsiaBSDCon 2026. Here's how it went.</p><h2>Devsummit</h2><p>The Developer Summit ran for two days, 10 AM to 5 PM each day. Most sessions were short presentations covering topics like FreeBSD on WSL 2 and Ansible on FreeBSD. Between talks, developers worked on patches, followed up on mailing-list threads, and reviewed one another's work &#8212; I got some useful feedback on my LLVM pull requests during these gaps.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!devy!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!devy!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 424w, https://substackcdn.com/image/fetch/$s_!devy!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 848w, https://substackcdn.com/image/fetch/$s_!devy!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 1272w, https://substackcdn.com/image/fetch/$s_!devy!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!devy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png" width="194" height="259" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:259,&quot;width&quot;:194,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;AsiaBSDCon 2026 Recap&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:true,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="AsiaBSDCon 2026 Recap" title="AsiaBSDCon 2026 Recap" srcset="https://substackcdn.com/image/fetch/$s_!devy!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 424w, https://substackcdn.com/image/fetch/$s_!devy!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 848w, https://substackcdn.com/image/fetch/$s_!devy!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 1272w, https://substackcdn.com/image/fetch/$s_!devy!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F46491ae1-7ad6-4c33-a49c-eecbc3e43ea3_194x259.png 1456w" sizes="100vw" fetchpriority="high"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Kuai Kuai, Source: <a href="https://commons.wikimedia.org/wiki/File:Kuai_Kuai_green.jpg#/media/File:Kuai_Kuai_green.jpg">Wikipedia</a></figcaption></figure></div><p>The AsiaBSDCon organizer handed out&nbsp;<em>Kuai Kuai</em>, a popular Taiwanese snack that comes in a bright green package. The tradition is to place it on top of your computer as a good-luck charm &#8212; the idea being that your code won't break as long as the snack hasn't expired. Think of it as the Taiwanese equivalent of holding a blessing ceremony in a server room before it goes live.</p><p>So I guess it's something similar to having religious ceremony in a server room before it opens to public.</p><div class="captioned-image-container"><figure><a class="image-link image2" target="_blank" href="https://substackcdn.com/image/fetch/$s_!GJEo!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!GJEo!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 424w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 848w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 1272w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!GJEo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png" width="276" height="182" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:182,&quot;width&quot;:276,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;AsiaBSDCon 2026 Recap&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:false,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="AsiaBSDCon 2026 Recap" title="AsiaBSDCon 2026 Recap" srcset="https://substackcdn.com/image/fetch/$s_!GJEo!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 424w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 848w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 1272w, https://substackcdn.com/image/fetch/$s_!GJEo!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd9b78f9b-01e2-40e3-b0cc-7f894afae67e_276x182.png 1456w" sizes="100vw"></picture><div></div></div></a><figcaption class="image-caption">Something like this...</figcaption></figure></div><h2>AsiaBSDCon 2026</h2><p>The main conference began right after the summit and drew roughly three to four times as many attendees. Each participant received a copy of the <em>AsiaBSDCon 2026 Proceedings</em> as part of the welcome package. The book itself was well produced, though the formatting across papers was inconsistent &#8212; most followed the IEEE Conference template, but font weight, size, margins, and layout varied noticeably, and a few papers used entirely different templates. It would be great if future committees provided a strict template and enforced compliance. A PDF or EPUB edition would also be a welcome addition.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Kzt5!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Kzt5!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Kzt5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg" width="2000" height="2361" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/d03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:2361,&quot;width&quot;:2000,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;AsiaBSDCon 2026 Recap&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="AsiaBSDCon 2026 Recap" title="AsiaBSDCon 2026 Recap" srcset="https://substackcdn.com/image/fetch/$s_!Kzt5!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Kzt5!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2Fd03bc54a-c97c-4a9b-8dee-1f474fcecab5_2000x2361.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">Photo of AsiaBSDCon2026 Proceedings</figcaption></figure></div><h3>Talks That Stood Out</h3><h4>Rethinking the forms of OS functionality development</h4><p>Kenichi Yasukata presented his work on a portable userland TCP/IP stack. He outlined the performance advantages of running the network stack in userspace but highlighted a persistent challenge: portability across operating systems due to divergent APIs.</p><p>His solution is a userland TCP/IP stack that deliberately omits OS-specific code. That sounds paradoxical &#8212; how can a TCP/IP stack function without OS bindings? The answer is that developers supply the OS-specific low-level glue themselves. This separation lets the core stack remain portable while still achieving strong performance.</p><p>Kenichi also discussed techniques for intercepting system calls without relying on&nbsp;<code>LD_PRELOAD</code>. His approach uses binary overwriting, which requires architecture-specific hooks:&nbsp;<em>svc-hook</em>&nbsp;on arm64, and&nbsp;<em>zpoline</em>&nbsp;(a trampoline through an alternative syscall entry point) on x86-64.</p><h4>Faster, smolBSD! Boot! Boot!</h4><p>Pierre Pronchery showcased smolBSD, a container-oriented NetBSD variant. By stripping the kernel down to only the necessary drivers and bypassing the traditional UEFI boot path, smolBSD achieves bare-metal boot times under one second.</p><p>Pierre demonstrated PicoClaw and SSH server images that can be instantiated much like Docker images &#8212; an impressive feat for anyone who has waited several seconds for a standard container to come up. He also showed ZFS-on-root running on NetBSD, though this still appears to lag behind FreeBSD's mature ZFS support.</p><h4>Run Time Reoptimization for Modern Heterogenous Systems</h4><p>George Neville-Neil argued that modern hardware &#8212; CPUs, GPUs, NPUs &#8212; has evolved far beyond the PDP-11 model, yet Unix-like operating systems still carry assumptions rooted in that era.</p><p>He dove deep into CPU microarchitecture: cycle-level penalties, cache misses, branch mispredictions, and the like. The core idea is to capture these runtime penalties and feed them back into LLVM, which he highlighted as a strong abstraction layer across diverse hardware targets. This feedback from live profilers is passed through optimization pipelines that produce architecture-specific binaries, which are reloaded without exiting the program.</p><p>I'll admit this talk was hard to follow in real time &#8212; partly because I was multitasking &#8212; and I plan to revisit the recording to better understand the benchmarking results.</p><h4>Bringing memory safety to BSD with CHERI</h4><p>Brooks Davis presented the CheriBSD upstreaming effort, with a strong emphasis on CHERI's security benefits. Two examples stood out. First, the team asked an LLM to inject 13 memory bugs into NGINX; CHERI caught all 13 plus two additional bugs the LLM introduced unintentionally. Second, while porting Chromium to CheriBSD, the two-person team uncovered numerous memory vulnerabilities that were later assigned CVEs &#8212; matching or exceeding the output of over 100 security researchers on the Chrome team, thanks to CHERI's memory-safety guarantees.</p><p>The upstreaming roadmap targets completion by FreeBSD 16, expected in December 2027. CheriBSD will be the first time-sharing operating system with full CHERI support, covering both Arm Morello and RISC-V CHERI (RV64Y). On the Linux side, a CHERI port is in progress, but organizational challenges &#8212; what I'd describe as significant process and priority shifts &#8212; appear to be slowing adoption.</p><div class="captioned-image-container"><figure><a class="image-link image2 is-viewable-img" target="_blank" href="https://substackcdn.com/image/fetch/$s_!Rjzk!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg" data-component-name="Image2ToDOM"><div class="image2-inset"><picture><source type="image/webp" srcset="https://substackcdn.com/image/fetch/$s_!Rjzk!,w_424,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_848,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_1272,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_1456,c_limit,f_webp,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 1456w" sizes="100vw"><img src="https://substackcdn.com/image/fetch/$s_!Rjzk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg" width="1754" height="1124" data-attrs="{&quot;src&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg&quot;,&quot;srcNoWatermark&quot;:null,&quot;fullscreen&quot;:null,&quot;imageSize&quot;:null,&quot;height&quot;:1124,&quot;width&quot;:1754,&quot;resizeWidth&quot;:null,&quot;bytes&quot;:null,&quot;alt&quot;:&quot;AsiaBSDCon 2026 Recap&quot;,&quot;title&quot;:null,&quot;type&quot;:null,&quot;href&quot;:null,&quot;belowTheFold&quot;:true,&quot;topImage&quot;:false,&quot;internalRedirect&quot;:null,&quot;isProcessing&quot;:false,&quot;align&quot;:null,&quot;offset&quot;:false}" class="sizing-normal" alt="AsiaBSDCon 2026 Recap" title="AsiaBSDCon 2026 Recap" srcset="https://substackcdn.com/image/fetch/$s_!Rjzk!,w_424,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 424w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_848,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 848w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_1272,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 1272w, https://substackcdn.com/image/fetch/$s_!Rjzk!,w_1456,c_limit,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F45f308a0-943f-4267-8f34-96f7a54a83e3_1754x1124.jpeg 1456w" sizes="100vw" loading="lazy"></picture><div class="image-link-expand"><div class="pencraft pc-display-flex pc-gap-8 pc-reset"><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container restack-image"><svg aria-hidden="true" width="20" height="20" viewBox="0 0 20 20" fill="none" stroke-width="1.5" stroke="var(--color-fg-primary)" stroke-linecap="round" stroke-linejoin="round" xmlns="http://www.w3.org/2000/svg"><g><path d="M2.53001 7.81595C3.49179 4.73911 6.43281 2.5 9.91173 2.5C13.1684 2.5 15.9537 4.46214 17.0852 7.23684L17.6179 8.67647M17.6179 8.67647L18.5002 4.26471M17.6179 8.67647L13.6473 6.91176M17.4995 12.1841C16.5378 15.2609 13.5967 17.5 10.1178 17.5C6.86118 17.5 4.07589 15.5379 2.94432 12.7632L2.41165 11.3235M2.41165 11.3235L1.5293 15.7353M2.41165 11.3235L6.38224 13.0882"></path></g></svg></button><button tabindex="0" type="button" class="pencraft pc-reset pencraft icon-container view-image"><svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-maximize2 lucide-maximize-2"><polyline points="15 3 21 3 21 9"></polyline><polyline points="9 21 3 21 3 15"></polyline><line x1="21" x2="14" y1="3" y2="10"></line><line x1="3" x2="10" y1="21" y2="14"></line></svg></button></div></div></div></a><figcaption class="image-caption">CHERI upstreaming timeline. Copyrighted by Brooks Davis.</figcaption></figure></div><h2>What's Next?</h2><p><strong>BSDCan 2026</strong>&nbsp;&#8212; I'll be presenting a talk on hybrid scheduling. Unfortunately, a midterm exam will keep me from the hackathon.</p><p><strong>EuroBSDCon 2026</strong>&nbsp;&#8212; I'm eager to attend, pending travel approval from my second co-op employer.</p><p><strong>AsiaBSDCon 2027</strong>&nbsp;&#8212; During the closing session, Li-wen Hsu announced that next year's conference will be held in Singapore. As George put it, making it happen requires "volunteers, volunteers, volunteers &#8212; and sponsors, sponsors, sponsors." If you're based in Singapore and can spare four days, please consider volunteering. If your company is in a position to help financially, sponsorship goes a long way.</p><h2>Acknowledgments</h2><p>As George Neville-Neil noted in the closing session, enormous thanks are owed to Li-wen Hsu (lwhsu@) for making AsiaBSDCon possible. Everyone who worked alongside him knows the effort he poured into the event, day and night. Thank you, Li-wen.</p><p>I also want to thank the FreeBSD Foundation for approving and sponsoring my trip to Taiwan.</p>]]></content:encoded></item><item><title><![CDATA[My Experience with Jujutsu]]></title><description><![CDATA[A pragmatic review as FreeBSD and LLDB developer]]></description><link>https://minsoo.io/p/my-experience-with-jujutsu-a-pragmatic-review</link><guid isPermaLink="false">https://minsoo.io/p/my-experience-with-jujutsu-a-pragmatic-review</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Thu, 26 Mar 2026 07:39:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/f33f3fd9-723c-4174-a02d-13d8e69e6522_2000x2666.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><a href="https://github.com/jj-vcs/jj">Jujutsu</a>&nbsp;is a version control system that pairs Git's proven storage backend with a rethought approach to code management workflows. I currently use it across all of my repositories&#8212;with the sole exception of&nbsp;<code>freebsd-src</code>, which relies on a <code>prepare-commit-msg</code> hook that Jujutsu does not yet support. There is no shortage of introductory material on Jujutsu elsewhere, so rather than rehashing the basics, I want to share what I have found to be its strengths, its rough edges, and how it holds up in real-world, day-to-day use.</p><h2>The Good</h2><p>Jujutsu's workflow is meaningfully more efficient than Git's. Operations that tend to be friction-heavy in Git&#8212;moving commits between branches, rewriting commit messages, and resolving merge conflicts&#8212;are noticeably smoother in Jujutsu. Compatibility with existing Git repositories is solid; in most cases I disable Git colocation entirely and work with a fully native Jujutsu repository.</p><p>For production use, I rely on Jujutsu for both LLVM development and my weekly reports at the FreeBSD Foundation. Across both of these workflows, it has been completely reliable.</p><h2>The Bad</h2><p>Jujutsu is in good shape overall, but a few pain points remain.</p><p><strong>No hook support.</strong>&nbsp;While it is true that most Git hooks are unnecessary in Jujutsu's model,&nbsp;<code>prepare-commit-msg</code>&nbsp;is the exception I miss daily. The FreeBSD Project uses this hook to inject metadata into commit messages, and its absence is the sole reason&nbsp;<code>freebsd-src</code>&nbsp;is the one repository where I still fall back to Git. I am hopeful that hook support will land soon.</p><p><strong>No&nbsp;<code>--fixup</code>&nbsp;equivalent.</strong>&nbsp;Git's&nbsp;<code>git commit --fixup</code>&nbsp;has no direct counterpart in Jujutsu. My current workaround is to manually prepend&nbsp;<code>fixup!&nbsp;</code>to the change description, but this means re-typing the target commit message each time. When working on a series of LLVM patches, this gets tedious quickly.</p><p><strong>Manual bookmark management.</strong>&nbsp;Jujutsu does not advance bookmarks automatically, which makes pushing changes more verbose than it needs to be. Where Git requires a single&nbsp;<code>git push</code>, Jujutsu requires two commands:&nbsp;<code>jj bookmark set -r &lt;revset&gt; foo</code>&nbsp;followed by&nbsp;<code>jj git push --bookmark foo</code>. It is a small friction, but it adds up.</p><p><strong>Immature ecosystem.</strong>&nbsp;Third-party tooling is still catching up. As a concrete example,&nbsp;<a href="https://spaceship-prompt.sh/">Spaceship</a>&nbsp;only gained Jujutsu prompt support last week, and only through a community-maintained plugin. There are other integration gaps as well, though the Jujutsu team is actively working toward full Git compatibility, and progress has been rapid.</p><h2>Final Thoughts</h2><p>Despite its rough edges, Jujutsu has become my default version control tool. The workflow improvements over Git are substantial enough that the remaining gaps feel like temporary inconveniences rather than fundamental limitations. If you spend any meaningful amount of time in Git, it is worth giving Jujutsu a serious look.</p>]]></content:encoded></item><item><title><![CDATA[Future of the FreeBSD Kernel LLDB Plugin]]></title><description><![CDATA[Kernel debugging shouldn't be GPL]]></description><link>https://minsoo.io/p/future-of-the-freebsd-kernel-lldb-plugin</link><guid isPermaLink="false">https://minsoo.io/p/future-of-the-freebsd-kernel-lldb-plugin</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Wed, 18 Feb 2026 20:28:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/76cee643-9f91-468a-ab16-cbc4efa4236d_2000x1325.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>FreeBSD offers several approaches to kernel debugging: DDB, live kernel debugging, and core dump analysis. <a href="https://man.freebsd.org/cgi/man.cgi?query=ddb&amp;sektion=4&amp;apropos=0&amp;manpath=FreeBSD+15.0-RELEASE+and+Ports">DDB</a> is an interactive debugger built directly into the FreeBSD kernel, with syntax inspired by GDB &#8212; making it immediately familiar to most developers. Live debugging leverages FreeBSD's GDB stub (defined under&nbsp;<a href="https://github.com/freebsd/freebsd-src/tree/main/sys/gdb"><code>sys/gdb</code></a>); on the LLDB side, the&nbsp;<code>gdb-remote</code>&nbsp;plugin connects an LLDB client to a FreeBSD host via the GDB protocol, keeping the client platform-independent. Core dump debugging, meanwhile, can be performed with either <a href="https://man.freebsd.org/cgi/man.cgi?query=kgdb&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+15.0-RELEASE+and+Ports&amp;format=html">KGDB</a> or LLDB's&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin.</p><p>KGDB remains the preferred tool for many developers, largely because widely used debugger scripts and utilities like&nbsp;<a href="https://man.freebsd.org/cgi/man.cgi?query=crashinfo&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+15.0-RELEASE+and+Ports&amp;format=html"><code>crashinfo</code></a>&nbsp;depend on it. However, KGDB is GPL-licensed and therefore not shipped with FreeBSD. To address this, Moritz Systems ported KGDB's core functionality into LLDB several years ago under contract with the FreeBSD Foundation. One important distinction: KGDB is only available on FreeBSD because it depends on FreeBSD's&nbsp;<a href="https://man.freebsd.org/cgi/man.cgi?query=kvm&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+15.0-RELEASE+and+Ports&amp;format=html"><code>kvm</code></a>&nbsp;library &#8212; a dependency that also enables partial live kernel debugging through&nbsp;<a href="https://man.freebsd.org/cgi/man.cgi?query=mem&amp;apropos=0&amp;sektion=0&amp;manpath=FreeBSD+15.0-RELEASE+and+Ports&amp;format=html"><code>/dev/mem</code></a>. LLDB's&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin, by contrast, supports two backends:&nbsp;<code>kvm</code>&nbsp;and&nbsp;<code>libfbsdvmcore</code>.</p><h2>The Problem with the Dual-Provider Model</h2><p>Why does the&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin offer two separate interfaces? The choice between them isn't made at runtime &#8212; it's determined at compile time. The root issue is that&nbsp;<code>kvm</code>&nbsp;is only available on FreeBSD. To enable cross-platform support, LLDB needed an alternative, which led to the creation of&nbsp;<code>libfbsdvmcore</code>&nbsp;(commonly referred to as&nbsp;<code>fvc</code>).</p><p>This dual-provider approach introduces several problems.</p><p>First,&nbsp;<code>fvc</code>&nbsp;is effectively a clone of&nbsp;<code>kvm</code>&nbsp;with FreeBSD-specific code stripped out and cross-platform scaffolding added in. As a result, it inherits&nbsp;<code>kvm</code>'s bugs and limitations. Patches applied to&nbsp;<code>kvm</code>&nbsp;on the FreeBSD side need to be backported to&nbsp;<code>fvc</code>&nbsp;&#8212; and when they aren't, things break. For example, if a new minidump format version lands in FreeBSD but isn't reflected in&nbsp;<code>fvc</code>, cross-platform users will be unable to process core dumps generated under the new format.</p><p>Second,&nbsp;<code>fvc</code>&nbsp;is a third-party library that isn't bundled with LLDB. The original goal of making&nbsp;<code>FreeBSDKernel</code>&nbsp;cross-platform was to allow developers on macOS or Linux to debug FreeBSD core dumps. In practice, however, distribution-supplied LLDB packages don't include libraries like&nbsp;<code>fvc</code>, meaning those developers would need to build LLDB from source &#8212; a barrier high enough that virtually no one does it. This has left&nbsp;<code>fvc</code>&nbsp;largely unmaintained and undertested. I recently discovered, for instance, that it was missing minidump version 3 support on arm64. My ongoing work to bring the&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin to feature parity with KGDB is made considerably harder by having to validate against two separate providers.</p><h2>Solving the Dual-Provider Problem</h2><p>The solution, originally proposed by the developer of the&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin, is to integrate&nbsp;<code>kvm</code>'s functionality directly into LLDB. I agree with this approach: it enables cross-platform debugging without relying on external libraries, and it allows us to retire both the&nbsp;<code>kvm</code>&nbsp;and&nbsp;<code>fvc</code>&nbsp;interfaces in favor of a single, unified backend &#8212; significantly reducing the maintenance burden.</p><p>The one trade-off is that changes to the internalized implementation will need to be backported to FreeBSD's in-tree LLDB and upstreamed accordingly. In practice, though, this is far more manageable than maintaining two parallel interfaces.</p><p>That said, this is a substantial undertaking involving significant research, implementation, and testing. Since I already have ongoing LLDB improvement work in progress, it isn't the immediate priority. My current target is to complete the in-flight work by LLVM 23, with the unified interface aimed for LLVM 24. In the interim, the most practical step is to remove&nbsp;<code>fvc</code>&nbsp;from the&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin and make it&nbsp;<code>kvm</code>-only. A <a href="https://github.com/llvm/llvm-project/pull/181283">pull request</a> for that change is currently under review.</p><h2>Other Improvements to FreeBSDKernel</h2><p>My broader work on the&nbsp;<code>FreeBSDKernel</code>&nbsp;plugin focuses on improving LLDB's overall FreeBSD kernel debugging support. This was originally conceived as a GSoC project idea, but I took it on as a work item during my co-op with the FreeBSD Foundation. The scope includes adding support for additional architectures, implementing commands and features where&nbsp;<code>FreeBSDKernel</code>&nbsp;currently falls short of KGDB, and other enhancements. Progress is being tracked publicly on <a href="https://github.com/llvm/llvm-project/issues/180061">LLVM's GitHub issue</a>.</p>]]></content:encoded></item><item><title><![CDATA[Problems with the ULE Scheduler]]></title><description><![CDATA[Just a bug or design flaw?]]></description><link>https://minsoo.io/p/problems-with-the-ule-scheduler</link><guid isPermaLink="false">https://minsoo.io/p/problems-with-the-ule-scheduler</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Tue, 10 Feb 2026 22:44:19 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b559f311-97d1-42e4-9f38-09204f22514a_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>There are many CPU schedulers out there &#8212; ULE, 4BSD, CFS, and EEVDF, to name a few &#8212; but none of them are perfect. Every scheduler has areas where it excels and areas where it falls short. That's acceptable when the shortcomings stem from fundamental design trade-offs (e.g., the inherent limitations of a fair scheduler), but not when they stem from bugs or implementation oversights.</p><p>ULE, the default scheduler in FreeBSD, was introduced in FreeBSD 5.1 and became the default in FreeBSD 7.1. You might wonder why FreeBSD still ships its predecessor, 4BSD, even now at FreeBSD 15. The reason is that despite ULE being designed as a replacement for 4BSD, there are implementation issues in ULE that cause it to perform worse than 4BSD in certain scenarios. These should, of course, be fixed &#8212; and a developer has announced plans to work on this in the near future. In this post, I'll describe what those issues are and outline possible fixes.</p><h2>Nice is not well-respected</h2><p>In the ULE scheduler, nice values are not well-respected. The <a href="https://www.usenix.org/legacy/event/bsdcon03/tech/full_papers/roberson/roberson.pdf">original ULE paper</a> describes the design as follows:</p><blockquote><p>A fixed part of the priority range in FreeBSD is used for time sharing threads. ULE uses the interactivity score to derive the priority. After this the nice value is added to the priority, which may actually lower the priority in the case of negative nice values.</p></blockquote><p>For context, here is how FreeBSD defines its priority bands and how ULE calculates scheduling priority:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;c&quot;,&quot;nodeId&quot;:&quot;8226a2b3-1c37-4808-b2b7-7e2a01da34af&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-c">/* from sys/sys/priority.h */
/*
 * Priorities range from 0 to 255.  Ranges are as follows:
 *
 * Interrupt threads:&#9;&#9;0 - 7
 * Realtime user threads:&#9;8 - 39
 * Top half kernel threads:&#9;40 - 55
 * Time sharing user threads:&#9;56 - 223
 * Idle user threads:&#9;&#9;224 - 255
 *
 * ...
 */</code></pre></div><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;c&quot;,&quot;nodeId&quot;:&quot;1e99d68d-16cd-4530-8949-99ccebe58cae&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-c">/* from sys/kern/sched_ule.c:sched_priority(), simplified */
/*
 * If the score is interactive we place the thread in the realtime
 * queue with a priority that is less than kernel and interrupt
 * priorities.  These threads are not subject to nice restrictions.
 *
 * Scores greater than this are placed on the normal timeshare queue
 * where the priority is partially decided by the most recent cpu
 * utilization and the rest is decided by nice value.
 *
 * The nice value of the process has a linear effect on the calculated
 * score.  Negative nice values make it easier for a thread to be
 * considered interactive.
 */
score = imax(0, sched_interact_score(td) + nice);
if (score &lt; sched_interact) {
    pri = PRI_MIN_INTERACT;
    pri += (PRI_MAX_INTERACT - PRI_MIN_INTERACT + 1) * score /
        sched_interact;
} else {
    const struct td_sched *const ts = td_get_sched(td);
    const u_int run = SCHED_TICK_RUN_SHIFTED(ts);
    const u_int run_unshifted __unused = (run +
        (1 &lt;&lt; SCHED_TICK_SHIFT) / 2) &gt;&gt; SCHED_TICK_SHIFT;
    const u_int len = SCHED_TICK_LENGTH(ts);
    const u_int nice_pri_off = SCHED_PRI_NICE(nice);
    const u_int cpu_pri_off = (((SCHED_PRI_CPU_RANGE - 1) *
        run + len / 2) / len + (1 &lt;&lt; SCHED_TICK_SHIFT) / 2) &gt;&gt;
        SCHED_TICK_SHIFT;
    pri = PRI_MIN_BATCH + cpu_pri_off + nice_pri_off;
}</code></pre></div><p>In FreeBSD, nice values range from &#8722;20 to 20 (41 levels), while the timeshare priority band spans from 56 to 223 (168 levels). The nice value is added to the priority linearly without scaling. This means the impact of nice on scheduling priority is relatively small, and the interactivity score can easily dominate the priority calculation, effectively drowning out the nice value.</p><p>One straightforward fix would be to multiply the nice value by 3 or 4 before adding it to the priority. However, linear addition has a deeper problem: the perceptual difference between nice 0 and nice 1 is much greater than the difference between nice 18 and nice 19. A proportional approach using an exponential weight table solves this by expressing nice levels as ratios rather than fixed offsets &#8212; for example, each nice level corresponds to roughly a 10% change in CPU share.</p><p>Linux already takes this approach. The CFS/EEVDF scheduler maps each nice level to a weight via a precomputed table:</p><div class="highlighted_code_block" data-attrs="{&quot;language&quot;:&quot;c&quot;,&quot;nodeId&quot;:&quot;c2f61270-ede0-4e4b-b421-5bf6fc5a9af1&quot;}" data-component-name="HighlightedCodeBlockToDOM"><pre class="shiki"><code class="language-c">/* from kernel/sched/core.c */
/*
 * Nice levels are multiplicative, with a gentle 10% change for every
 * nice level changed. I.e. when a CPU-bound task goes from nice 0 to
 * nice 1, it will get ~10% less CPU time than another CPU-bound task
 * that remained on nice 0.
 *
 * The "10% effect" is relative and cumulative: from _any_ nice level,
 * if you go up 1 level, it's -10% CPU usage, if you go down 1 level
 * it's +10% CPU usage. (to achieve that we use a multiplier of 1.25.
 * If a task goes up by ~10% and another task goes down by ~10% then
 * the relative distance between them is ~25%.)
 */
const int sched_prio_to_weight[40] = {
 /* -20 */     88761,     71755,     56483,     46273,     36291,
 /* -15 */     29154,     23254,     18705,     14949,     11916,
 /* -10 */      9548,      7620,      6100,      4904,      3906,
 /*  -5 */      3121,      2501,      1991,      1586,      1277,
 /*   0 */      1024,       820,       655,       526,       423,
 /*   5 */       335,       272,       215,       172,       137,
 /*  10 */       110,        87,        70,        56,        45,
 /*  15 */        36,        29,        23,        18,        15,
};</code></pre></div><p>With this kind of weight table, nice values are meaningfully respected at every level, and the effect of each increment feels consistent across the entire range.</p><h3>Fairness Issue</h3><p>The ULE scheduler is not completely fair. To illustrate what this means: in Linux's CFS and EEVDF schedulers, total CPU usage is tracked per task via a virtual runtime (<code>vruntime</code>). When a task yields the CPU before its time quantum expires, the unused portion is preserved, and the task receives compensation the next time it is scheduled.</p><p>ULE does not do this. When a batch-class task in ULE yields the CPU early, the remainder of its time quantum is simply lost. If the task repeatedly yields early &#8212; but not frequently enough to be promoted to the interactive class &#8212; it ends up receiving less CPU time than it is entitled to, leading to a form of soft starvation. One approach to fixing this would be to track the lost quantum as a credit and apply it the next time the task is scheduled.</p><h3>Conclusion</h3><p>Recently, FreeBSD landed a <a href="https://cgit.freebsd.org/src/commit/?id=ce38acee8d0bb35223b227479b9998c77b47f41b">patch</a> that allows ULE and 4BSD to coexist in the same kernel, enabling users to select a scheduler at boot time without recompiling. Once fixes for the issues described above land, users who have been relying on 4BSD due to ULE's shortcomings will be able to properly evaluate ULE's performance. If ULE can be shown to be superior to 4BSD in all cases, 4BSD can finally be deprecated. To follow progress on this work, subscribe to the <a href="https://lists.freebsd.org/subscription/freebsd-hackers">freebsd-hackers mailing list</a>.</p>]]></content:encoded></item><item><title><![CDATA[How to Become a Good Programmer (With Open Source)]]></title><description><![CDATA[In my previous post, I explained why modern hackathons are doing more harm than good for computer science students.]]></description><link>https://minsoo.io/p/how-to-become-a-good-programmer-with</link><guid isPermaLink="false">https://minsoo.io/p/how-to-become-a-good-programmer-with</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 01 Feb 2026 04:30:39 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/21ead27b-af0a-4d02-85c0-c66aff75c247_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>In my previous post, I explained why modern hackathons are doing more harm than good for computer science students. But that piece felt incomplete&#8212;I criticized without offering a path forward. So here&#8217;s the constructive follow-up: how I learned to become a good programmer, and how you can too.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;545ef8ac-c943-4494-a876-77396c46d634&quot;,&quot;caption&quot;:&quot;Let me be clear from the start: not all hackathons are created equal. Events like FreeBSD hackathons, where developers collaborate on meaningful operating system improvements, represent the best of what these gatherings can offer. But since arriving at the University of Waterloo, I&#8217;ve witnessed a troubling transformation in hackathon culture&#8212;particularl&#8230;&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Hackathons Are Ruining Students&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:167787206,&quot;name&quot;:&quot;Minsoo Choo&quot;,&quot;bio&quot;:&quot;FreeBSD Kernel Developer &#8226; CHERI Alliance Ambassador &#8226; University of Waterloo Computer Engineering (Class of &#8217;30)&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/930ec2b0-2266-4098-a89e-76652d7b0c68_2769x2769.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-11-04T03:52:45.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/b1b7978f-1ebc-4f38-b7da-1b811881f39e_2000x1333.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://minsoo.io/p/hackathons-are-ruining-students&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199015324,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:8751651,&quot;publication_name&quot;:&quot;Minsoo Choo&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!v4hh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F251537e3-ac76-4a30-adf6-1072fe518d0d_1280x1280.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p>A note before we begin: this advice won&#8217;t apply to everyone. Web developers, for instance, may find some of this less relevant. But I believe most programmers will recognize these principles as foundational.</p><h2>The Best Way to Learn Is From Good Teachers</h2><p>This holds true across every discipline&#8212;music, mathematics, art, science. The fastest, most reliable path to expertise is learning from someone who&#8217;s already mastered the craft. Think of teenage pianists who travel across countries to study with legendary tutors. Programming is no different.</p><p>Here&#8217;s the problem: computer science is barely a century old, yet it&#8217;s become one of the most popular fields in the world. The demand for great teachers far outstrips the supply.</p><p>But that doesn&#8217;t mean you&#8217;re out of luck.</p><p>We have something better than a scarce handful of mentors: hundreds of excellent books written by legendary programmers. Yes, many students avoid them&#8212;they&#8217;re long, dense, and admittedly boring at times. But progress in <em>any </em>field has boring parts. Computer science is no exception. And I promise you, working through these books is infinitely more valuable than churning out throwaway projects at hackathons.</p><p>For fundamentals, I recommend <em>Computer Systems: A Programmer&#8217;s Perspective</em> and <em>Computer Architecture: A Quantitative Approach</em>. For the C programming language, start with <em>C Programming: A Modern Approach</em>, then move to <em>The C Programming Language</em> and <em>Modern C</em>.</p><p>Now, some of you might argue that starting with C is outdated&#8212;that Python is a better entry point. That&#8217;s a reasonable position, but here&#8217;s the truth: you&#8217;ll need to learn C eventually. No exceptions. Even if you&#8217;re a web developer, understanding what C teaches you will make you more effective&#8212;whether that&#8217;s tracking down why your app is slow, profiling performance, or occasionally digging into browser internals. Languages like C++, Rust, and Zig exist, but C remains the simplest and most direct way to understand how machines actually work.</p><p>After that, learn algorithms. <em>Introduction to Algorithms</em> is the gold standard. Once you&#8217;ve read it, you&#8217;ll find that understanding new algorithms becomes straightforward&#8212;often just a matter of reading a Wikipedia page and some example code. LeetCode has its place, but don&#8217;t grind through hard problems for the sake of it. Focus on easy and medium difficulty. Instead of memorizing solutions, learn to recognize patterns. When you face an algorithmic challenge at work or in an interview, you&#8217;ll spend less time both planning and implementing.</p><h2>Open Source Is Your Classroom</h2><p>Now you need real-world experience. But before you start writing code, study how others have done it.</p><p>Remember what I said about learning from good teachers? The open-source world is filled with them. Want to see exemplary object-oriented, modern C++? Study the <a href="https://github.com/llvm/llvm-project">LLVM project</a>. Curious about how operating systems work? Explore <a href="https://github.com/freebsd/freebsd-src">FreeBSD</a>, <a href="https://github.com/apple-oss-distributions/xnu">XNU</a> (macOS's kernel), <a href="https://github.com/torvalds/linux">Linux</a>, and <a href="https://github.com/FreeRTOS/FreeRTOS">FreeRTOS</a>.</p><p>Here&#8217;s the catch: not all open-source code is worth studying. Even the Linux kernel has its infamous staging drivers&#8212;poorly maintained code that exists in a kind of purgatory for a reason. But as you read more, you&#8217;ll develop the ability to distinguish good code from bad. You&#8217;ll start to sense when something is off.</p><p>This &#8220;smell&#8221;&#8212;the instinct that tells you code was written by a beginner, by an experienced developer new to a codebase, or by AI&#8212;is hard to articulate, but unmistakable once you&#8217;ve internalized it. After reading a few hundred thousand lines, you&#8217;ll know. If you ever want to advance to senior-level work, this skill is non-negotiable.</p><p>Whatever your area of interest&#8212;databases, web servers, quantitative finance, cryptography, blockchain, AI, GPU programming, video games&#8212;find the most respected project in that space. Ninety percent of the time, you&#8217;ll be learning from the best. (There are exceptions; GPU kernels written in CUDA, for instance, leaves much to be desired.) If you&#8217;re unsure, ask around&#8212;forums, communities, and colleagues can point you toward the gold-standard implementation of whatever you&#8217;re studying.</p><p>Unless you&#8217;re working on classified military software, you can find source code for almost anything online&#8212;including, as a fun fact, leaked Windows XP kernel code.</p><h2>Conclusion</h2><p>So yes, becoming a good programmer involves a lot of reading&#8212;books and real-world code. Sounds boring? Welcome to professional-level work in <em>any</em> field.</p><p>If you&#8217;d rather stick to hobby projects and hackathons, that&#8217;s fine&#8212;but then why pursue a computer science degree? You can do those things without one. Once you&#8217;ve committed to this field, it&#8217;s time to do what students in every other serious discipline do: learn from the best examples, written by the best teachers.</p><p>The shortcuts aren&#8217;t shortcuts. The fundamentals are the path.</p>]]></content:encoded></item><item><title><![CDATA[University of Waterloo ECE 1A Wrap-Up]]></title><description><![CDATA[Three months in&#8212;here&#8217;s what I actually learned (and what I wish I&#8217;d known)]]></description><link>https://minsoo.io/p/university-of-waterloo-ece-1a-wrap</link><guid isPermaLink="false">https://minsoo.io/p/university-of-waterloo-ece-1a-wrap</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 14 Dec 2025 17:49:14 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/bb3b98d8-0bc6-4216-8d8c-52df06ac153e_2000x1325.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Three months have passed since I started at the University of Waterloo. For prospective students curious about what first-year engineering is really like&#8212;or anyone interested in an unfiltered account of 1A in Computer Engineering&#8212;here&#8217;s my honest breakdown covering courses, co-op, health, and food.</p><h2>Courses</h2><p>If there&#8217;s one takeaway from my 1A term in Computer Engineering, it&#8217;s this: the curriculum feels designed without much consideration for whether it&#8217;s actually realistic for first-year students.</p><p><strong>ECE 105 (Classical Mechanics):</strong> Easily the hardest and, for computer engineers, least relevant course of the term. I genuinely love physics, which made this experience all the more disappointing. The teaching approach covers principles in lectures while expecting students to figure out applications independently. Tutorial problems are so difficult they never appear on actual assessments&#8212;and it seems like even the instructors aren&#8217;t sure what the quizzes and exams should look like. The kicker? ECE 105 covers more material and is harder than PHYS 111 and PHYS 121, which are designed for <em>physics majors</em>.</p><p><strong>ECE 150 (Fundamentals of Programming):</strong> Learning C++ fundamentals in three months is ambitious, to put it mildly. Unless you&#8217;ve already programmed in C++ before arriving, expecting above a 70 is optimistic. I feel for the electrical engineering students&#8212;most of them will never use this material again.</p><p><strong>ECE 190 (Engineering Profession and Practice):</strong> This course isn&#8217;t really about ethics; it&#8217;s about memorizing slides. The exams are full of gotcha questions that test trivia rather than understanding. You&#8217;ll need to remember obscure facts (how many undergraduate engineering programs exist in Canada?) and distinguish between nearly identical terms (in &#8220;E-coop,&#8221; does the &#8220;E&#8221; stand for &#8220;Enterprise&#8221; or &#8220;Entrepreneurial&#8221;?). It&#8217;s more IQ test than ethics course.</p><p><strong>ECE 198 (Project Studio):</strong> The professor allowed AI usage, which was fortunate because I had no time to do anything else. I essentially vibe-coded my way through with Claude Code&#8212;GenAI usage isn&#8217;t against Policy 71 for this course, after all. The group project was painful; I had a teammate who was equal parts arrogant and uninformed, which is the worst combination. Also, they scheduled our symposium on a Sunday. That presentation was worth around 30% of our grade. Do student labour protections not apply here?</p><p><strong>MATH 115 &amp; MATH 117 (Linear Algebra and Calculus):</strong> These were manageable. If you finished high school math with 85+ and stayed awake during lectures, you should be fine. The conventional wisdom that university grades drop 15% from high school doesn&#8217;t seem to apply here. Credit where it&#8217;s due: the Faculty of Mathematics has excellent professors and TAs.</p><p><strong>COMMST 192 (Communication in Engineering):</strong> Fun and genuinely useful, but the workload was enormous. I spent most of my after-class time on COMMST 192 assignments, which is why I never finished the problem sets for ECE 105, MATH 115, and MATH 117. For me, this course had more work than everything else combined&#8212;though for most people, ECE 150 probably takes that crown. My Grammarly Pro subscription expired after reading week, which made catching errors significantly harder without AI assistance.</p><p><strong>The Bottom Line:</strong> The schedule and workload are brutal for first-year students. It feels like the institution prioritizes tuition revenue over student well-being. If I were an MPP, I&#8217;d propose legislation requiring curriculum coordinators to complete their own programs before implementing them.</p><h2>Co-op</h2><p>This was the easiest part of my term, though I know it&#8217;s the hardest for most people. I was one of the lucky few who secured a good placement quickly. Many friends&#8212;including my roommate&#8212;are still searching. I&#8217;ve noticed tension building as some students without placements grow envious of those who have them.</p><p>The fantasy that everyone will land great co-ops for five years and walk into FAANG after graduation is starting to crumble. I knew this going in&#8212;friends with older siblings in CS and CE had warned me&#8212;but I applied anyway.</p><p>I taught myself most of this material before university and had two successful work experiences under my belt. Academically, 1A taught me almost nothing new. What I <em>did</em> discover was an unexpected passion for theoretical physics and pure mathematics. It&#8217;s too late to switch programs, though I don&#8217;t regret choosing computer engineering. I&#8217;m pragmatic enough to acknowledge that physics and math degrees don&#8217;t pay the same way.</p><h2>Health</h2><p>Now I understand why engineering and math students have certain reputations at this university.</p><p>Yes, the gym is open until midnight. But when you&#8217;re drowning in assignments, who has time to go? Before reading week, I&#8217;d see engineering students working out regularly. Now? I don&#8217;t know anyone in my cohort who still makes it to the gym. We&#8217;re all burnt out. Even the walk there feels like too much.</p><p>Mental health is worse. Friends from high school keep suggesting I date someone. But making a girlfriend&#8212;or even talking to women&#8212;isn&#8217;t realistic here. Achieving 80+ and finishing everything on time requires isolation. The gender ratio doesn&#8217;t help either. I don&#8217;t have exact numbers (and collecting them would be awkward), but it feels like somewhere between 10:1 and 15:1. We joke that finding a girl in our cohort is harder than finding a unicorn.</p><p>When you&#8217;re one week from finals, fighting a cold because the university didn&#8217;t call a snow day during an actual snowstorm, and you got sick trudging between classes&#8212;the combination of physical and mental strain is indescribable.</p><h2>Food</h2><p>The best thing about my first 18 years of life was that my mom is the best chef in the world. Food here tastes like sewage and costs a fortune. It&#8217;s borderline fraudulent.</p><p>I&#8217;m fortunate to be in a residence with the best dining hall on campus, but it doesn&#8217;t come close to what I ate at home in Ottawa. I&#8217;ve also learned that nutritional balance matters more than I thought. I got sick at least once a month because I refused to eat vegetables. The vegetables here don&#8217;t help&#8212;they&#8217;re not the fresh greens I had back home; they taste like they survived some kind of biohazard incident.</p><p>I don&#8217;t know why I was so stubborn about vegetables in Ottawa. I swear I&#8217;ll eat them happily when I go back after finals.</p><h2>Conclusion</h2><p>I wish I could have skipped first year entirely. There&#8217;s nothing here that matches what I expected back in June. A physics or mathematics degree might have been more intellectually fulfilling, but it would have left me broke after graduation. The current economy leaves little room for idealism.</p><p>On the bright side, I&#8217;ve discovered a genuine interest in physics and am now pursuing a joint honours. Hopefully this will make my tuition feel less wasted while I continue learning almost nothing new in my core engineering courses.</p><div><hr></div><p><strong>Resources</strong></p><p>If you&#8217;re navigating Waterloo, I highly recommend <a href="https://xierumeng.github.io/">Xierumeng&#8217;s &#8220;Guide to UW&#8221;</a> blog series. It offers detailed guidance for each academic term, co-op terms, and other essential skills for succeeding here.</p>]]></content:encoded></item><item><title><![CDATA[Physics Is Not a Sprint]]></title><description><![CDATA[Yet we keep training marathon runners for the 100-meter dash]]></description><link>https://minsoo.io/p/physics-is-not-a-sprint</link><guid isPermaLink="false">https://minsoo.io/p/physics-is-not-a-sprint</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 14 Nov 2025 19:08:35 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/636a16c2-9c8e-4a5f-b699-32447a91125a_2000x2000.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>As a computer engineering student at the University of Waterloo, I&#8217;m currently navigating ECE 105: Classical Mechanics. While much of the content revisits Ontario&#8217;s Grade 12 physics curriculum, the practice problems and exams present a notably steeper challenge. This course has earned a notorious reputation&#8212;it consistently posts the lowest midterm averages across all first-term ECE courses, leaving many students demoralized.</p><h2>The Rush to Nowhere</h2><p>University physics lectures move at breakneck speed. When students struggle with new concepts, they&#8217;re left with limited options: figure it out independently or seek help from teaching assistants who aren&#8217;t always available. The situation becomes particularly challenging for students arriving from educational systems where these foundational concepts weren&#8217;t covered&#8212;they find themselves simultaneously learning new material while racing against exam deadlines.</p><h2>The Memorization Trap</h2><p>Here&#8217;s what makes physics fundamentally different from most university courses: while chemistry, biology, and even engineering mathematics lean heavily on memorization, physics demands something else entirely. Every physics instructor I&#8217;ve encountered shares the same philosophy: &#8220;The only equation you need to remember is F=ma.&#8221;</p><p>Of course, this isn&#8217;t literally true&#8212;students must know formulas for energy, momentum, and wave mechanics to complete exams within time limits. But the underlying message is clear: physics should be about understanding systems, not memorizing solutions.</p><p>Consider <a href="https://en.wikipedia.org/wiki/Elastic_collision#One-dimensional_Newtonian">elastic collisions</a> between two objects. Most students instinctively memorize the velocity exchange formulas, while professors consistently discourage this approach, advocating instead for case-by-case analysis. This disconnect reveals a fundamental tension in how physics is taught versus how it&#8217;s tested.</p><h2>Why Students Choose Shortcuts</h2><p>The reality is stark: exams reward speed over understanding. When you have 50 minutes to solve five complex problems, methodical analysis becomes a luxury you can&#8217;t afford. Students who memorize formulas gain a clear advantage&#8212;not because they understand physics better, but because they can navigate the exam more efficiently.</p><p>This creates a perverse incentive structure. Physics problem-solving through genuine analysis becomes an IQ test under time pressure. Some students excel at rapid analytical thinking, but many others&#8212;who could solve these problems given adequate time&#8212;find themselves forced to choose between understanding and grades.</p><h2>A Better Way Forward</h2><p>The solution isn&#8217;t complicated, but it requires reimagining how we assess physics knowledge. Instead of rewarding formula application, we should structure evaluations to emphasize systematic thinking. Imagine a marking scheme that allocates points like this:</p><ul><li><p><strong>30% for system identification</strong>: Recognizing the relevant objects and forces</p></li><li><p><strong>20% for visual representation</strong>: Creating accurate free-body diagrams and illustrations</p></li><li><p><strong>30% for conceptual explanation</strong>: Articulating in words why and how the system behaves</p></li><li><p><strong>20% for mathematical execution</strong>: Applying formulas to reach the numerical answer</p></li></ul><p>This approach would make shortcuts through memorization insufficient. Students couldn&#8217;t achieve full marks simply by plugging numbers into equations&#8212;they&#8217;d need to demonstrate genuine understanding of the physical principles at play.</p><p>Crucially, such changes must be paired with realistic time allocations. There&#8217;s no value in testing analytical thinking if students must still race against the clock.</p><h2>The Uncomfortable Truth</h2><p>Despite these clear improvements, I&#8217;m skeptical we&#8217;ll see meaningful change. While I personally enjoy studying physics in my spare time, I recognize that most students have different interests and priorities. Without widespread demand for reform, professors have little incentive to restructure their courses.</p><p>The result? Physics remains trapped in its current form&#8212;simultaneously the most challenging and least engaging course of the term for many students. We&#8217;ve transformed a subject that should inspire curiosity about the natural world into a high-stakes memorization contest.</p><p>Until we&#8217;re willing to sacrifice some breadth of coverage for depth of understanding, and until we design assessments that reward thinking over speed, university physics will continue to feel less like an exploration of the universe&#8217;s fundamental principles and more like an academic obstacle course.</p>]]></content:encoded></item><item><title><![CDATA[Hackathons Are Ruining Students]]></title><description><![CDATA[Why we're teaching the next generation to code fast, not code well]]></description><link>https://minsoo.io/p/hackathons-are-ruining-students</link><guid isPermaLink="false">https://minsoo.io/p/hackathons-are-ruining-students</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Tue, 04 Nov 2025 03:52:45 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b1b7978f-1ebc-4f38-b7da-1b811881f39e_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>Let me be clear from the start: not all hackathons are created equal. Events like <a href="https://wiki.freebsd.org/Hackathon">FreeBSD hackathons</a>, where developers collaborate on meaningful operating system improvements, represent the best of what these gatherings can offer. But since arriving at the University of Waterloo, I&#8217;ve witnessed a troubling transformation in hackathon culture&#8212;particularly among freshmen who treat these events as golden tickets to FAANG companies rather than opportunities for genuine innovation.</p><h2><strong>The Hackathon Gold Rush</strong></h2><p>Ontario&#8217;s hackathon circuit&#8212;<a href="https://hackthenorth.com">Hack the North</a>, <a href="https://hackthevalley.io">Hack the Valley</a>, <a href="https://www.deltahacks.com">DeltaHacks</a>&#8212;follows a familiar formula: teams sprint through 24-36 hours of coding, judges crown winners, and everyone goes home exhausted. These events were designed to reward brilliant ideas and creative problem-solving. That original vision, however, has been casualties of a much larger shift in the tech landscape.</p><p>The post-pandemic job market fundamentally altered how students approach their careers. With supply dramatically outpacing demand in software engineering, stories of graduates struggling for years to find work have shattered the once-reliable narrative that a computer science degree guaranteed a pathway to Big Tech. Students who once believed GPA alone would open doors now scramble for any edge they can find.</p><p>Enter the modern hackathon: a perceived shortcut to distinction. Unlike GPA, where theoretically everyone can excel, hackathons produce a limited number of winners. Victory promises not just a line on a resume, but face time with senior developers and hiring managers from sponsoring companies. In this new reality, the original purpose&#8212;fostering innovation&#8212;has become secondary to career advancement.</p><h2><strong>When Competition Corrupts Innovation</strong></h2><p>The pressure to win has transformed hackathons into something unrecognizable. While rule-bending has always existed&#8212;teams uploading pre-written code to GitHub was once the height of cheating&#8212;the rise of LLM coding agents has fundamentally broken the playing field.</p><p>Today&#8217;s hackathon landscape rewards resources over creativity. Teams with premium AI subscriptions, multiple specialized tools, and access to various LLM models hold decisive advantages. When participants can generate entire project architectures and implementations without understanding the underlying code, we&#8217;re no longer measuring innovation or skill&#8212;we&#8217;re measuring who can afford the best digital assistants.</p><p>This pay-to-win dynamic violates the fundamental philosophy of hackathons. Instead of identifying the brightest ideas and most talented developers, we&#8217;re selecting for those with the deepest pockets and the most sophisticated AI toolchains.</p><h2><strong>The Hidden Cost: Technical Debt as Education</strong></h2><p>Perhaps most concerning is what hackathon culture teaches about software development. The sprint mentality&#8212;ship something, anything, in 36 hours&#8212;produces code that would horrify any professional developer. No version control, incomprehensible commit messages, zero documentation, and architectural decisions that would make maintenance impossible. These aren&#8217;t just bad habits; they&#8217;re anti-patterns that actively harm students&#8217; development as engineers.</p><p>I regularly review code from serial hackathon participants, and the patterns are depressingly consistent: branches merged instead of rebased, creating labyrinthine Git histories; commit messages that explain nothing; code generated by AI that neither the author nor reviewer truly understands. One memorable submission included hundreds of lines of refactoring with a single-line commit message.</p><p>This is the opposite of what industry needs. While hackathon veterans chase the next win, they&#8217;re failing to develop the fundamental skills that matter: writing maintainable code, thinking about long-term architecture, collaborating effectively through proper version control, and&#8212;critically&#8212;understanding what they&#8217;re building.</p><h2><strong>The Wrong Lesson at the Wrong Time</strong></h2><p>Computer science students should be learning to write good code, not just fast code. They need a learner&#8217;s mindset, not an entrepreneur&#8217;s hustle. Yet hackathon culture teaches them to prioritize velocity over quality, prizes over understanding, and shortcuts over craftsmanship.</p><p>The irony is stark. While students optimize for ephemeral 36-hour sprints, the industry still runs on COBOL systems in financial institutions that have operated reliably for decades. We&#8217;re creating a generation of developers who can spin up a flashy demo but can&#8217;t maintain a production system, who can prompt an AI but can&#8217;t debug its output, who can win competitions but can&#8217;t collaborate on real codebases.</p><h2><strong>A Call for Better</strong></h2><p>Hackathons could be valuable learning experiences. They could teach collaboration, innovation, and yes, even how to work under pressure. But the current model&#8212;driven by job market anxiety and enabled by AI shortcuts&#8212;is producing the opposite of what our industry needs.</p><p>We&#8217;re teaching students to play a lottery rather than develop skills, to generate code rather than understand it, to win at any cost rather than build something lasting. If we continue down this path, we risk creating a generation of developers who view software as something to be generated quickly and discarded, rather than crafted carefully and maintained.</p><p>The &#8220;move fast and break things&#8221; mentality has its place in certain contexts. But when it becomes the primary educational model for our future developers, we&#8217;re not just breaking things&#8212;we&#8217;re breaking the very foundation of software craftsmanship that our industry depends on.</p><p>It&#8217;s time to reconsider what we&#8217;re really teaching when we celebrate the hackathon winner who cobbled together an AI-generated project they don&#8217;t understand over the student who spent the same weekend learning to properly use Git, understanding design patterns, or contributing to an open-source project. Because in the long run, I know which one I&#8217;d rather have on my team.</p>]]></content:encoded></item><item><title><![CDATA[The Waterloo Paradox: How Canada's Top Tech School Lost Its Edge]]></title><description><![CDATA[The Waterloo dream isn't true anymore]]></description><link>https://minsoo.io/p/the-waterloo-paradox-how-canadas</link><guid isPermaLink="false">https://minsoo.io/p/the-waterloo-paradox-how-canadas</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Sun, 26 Oct 2025 01:42:20 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a249b150-10ee-4f64-b6a3-031252f0bb0e_1299x678.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>`A disclaimer: This piece draws from conversations with students, alumni, online discussions, and publicly available information. While I wasn&#8217;t personally present for the specific incidents mentioned, the patterns described reflect widely shared experiences within the Waterloo community.</em></p><h2>The Golden Era</h2><blockquote><p>&#8220;Microsoft&#8217;s favorite recruiting grounds were Harvard, Yale, Massachusetts Institute of Technology, Carnegie Mellon, and a little college near Toronto named the University of Waterloo.&#8221; &#8212; <em>Hard Drive: Bill Gates and the Making of the Microsoft Empire</em></p></blockquote><p>For decades, the University of Waterloo has occupied a unique position in North American tech education. While Canada boasts several excellent institutions&#8212;Toronto, UBC, McGill among them&#8212;Waterloo carved out something different: a co-op program so robust that it became the envy of engineering schools continent-wide.</p><p>The formula was simple and brilliant. Students would alternate between academic terms and work placements, graduating with two years of real-world experience. In the golden age of tech expansion through the mid-2010s, this wasn&#8217;t just an advantage&#8212;it was a golden ticket. The mythology around Waterloo computer science, software engineering, and computer engineering graduates landing FAANG positions wasn&#8217;t entirely exaggerated. Software jobs were abundant, companies were in perpetual hiring mode, and Waterloo students arrived battle-tested from their co-op experiences.</p><h2>When Supply Meets Reality</h2><p>But mythology has a way of creating its own demise.</p><p>As Waterloo&#8217;s reputation soared, two forces began reshaping the landscape. First, admissions became brutally competitive as students nationwide&#8212;and internationally&#8212;competed for spots in these &#8220;guaranteed success&#8221; programs. Second, and more critically, the tech job market underwent a seismic shift, particularly post-pandemic. The industry that once seemed to have infinite appetite for developers suddenly discovered limits.</p><p>Here&#8217;s the Economics 101 problem no one wanted to acknowledge: When supply surges while demand contracts, value plummets.</p><p>Today&#8217;s WaterlooWorks platform tells a sobering story. Software engineering positions that once attracted applications solely from computing students now see desperate bids from chemical and biomedical engineers, driven by scarcity in their own fields. The platform simply doesn&#8217;t have enough quality positions for its core computer science and engineering cohorts, let alone the overflow from other programs.</p><h2>The Quality Crisis</h2><p>But numbers tell only half the story. The more insidious problem is the deterioration in job quality itself.</p><p>Modern WaterlooWorks has become a hunting ground for startups operating on questionable foundations. Companies post positions before securing funding. &#8220;Teams&#8221; consist of two full-time employees supervising ten co-op students&#8212;a ratio that screams exploitation rather than education. The crunch culture that Silicon Valley is slowly abandoning has found new life in companies that view co-ops as disposable labor rather than future talent.</p><p>Consider this: One New York startup systematically fired half its co-op cohort for &#8220;financial reasons,&#8221; only to hire the exact same number the following term. The message was clear&#8212;conform to our crushing work culture or be replaced.</p><p>Most troubling is the persistent complaint, documented across decades of online forums, that the university itself prioritizes corporate relationships over student welfare. The institution meant to protect and educate has become, in many students&#8217; eyes, complicit in their exploitation.</p><h2>A Path Forward</h2><p>The solutions aren&#8217;t complex&#8212;they require institutional courage.</p><p><strong>First, implement supply-side discipline.</strong> If only 1,000 of 2,000 students secure meaningful co-ops (excluding programs like WE Accelerate), next year&#8217;s admission should reflect that reality. Yes, this intensifies admission competition, but it creates a more sustainable ecosystem where admitted students can focus on learning rather than surviving a hunger games-style job hunt.</p><p><strong>Second, establish real oversight.</strong> The co-op office must evolve from placement facilitator to quality guardian. This means verifying companies&#8217; financial stability, examining their employee composition, and ensuring they offer genuine learning environments. Startups using co-ops as venture-subsidized labor should find no place on WaterlooWorks.</p><h2>The Waterloo Moment</h2><p>The University of Waterloo&#8217;s co-op program revolutionized Canadian technical education and served as a model for universities nationwide. But models built for one era don&#8217;t automatically translate to another.</p><p>The question isn&#8217;t whether Waterloo can maintain its historical dominance&#8212;that ship has likely sailed. The question is whether it can evolve to protect what made it special in the first place: giving talented students real experience in supportive environments that foster both learning and career development.</p><p>The current system burns out students before they graduate, exploits their labor while they&#8217;re learning, and leaves many questioning whether the &#8220;Waterloo advantage&#8221; still exists. Without substantive reform, the institution risks becoming a cautionary tale about what happens when reputation outlives reality.</p><p>The co-op program doesn&#8217;t need to be perfect. But it does need to remember its purpose: education, not exploitation. The students flooding into Waterloo&#8217;s programs deserve the opportunity their predecessors enjoyed&#8212;to learn, grow, and launch careers, not merely survive.</p><p><em>That&#8217;s the promise worth fighting for.</em></p>]]></content:encoded></item><item><title><![CDATA[Road to Kernel Developer]]></title><description><![CDATA[Endless learning, experimenting, and thinking]]></description><link>https://minsoo.io/p/road-to-kernel-developer</link><guid isPermaLink="false">https://minsoo.io/p/road-to-kernel-developer</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Fri, 24 Oct 2025 00:01:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/45fe1aac-2f30-4e1e-8938-5df8cf1365e5_2000x1197.png" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p><em>If you&#8217;re just here for the roadmap to becoming a kernel developer, feel free to skip my personal story and jump straight to the comprehensive reading list at the end.</em></p><h2>How It All Started</h2><p>My programming journey began when I was twelve, captivated by the portrayal of hackers in popular media. My first programming book (<em><strong>&#54868;&#51060;&#53944; &#54644;&#52964;&#47484; &#50948;&#54620; &#50516;&#54840;&#50752; &#54644;&#53433;</strong></em> (1st Edition)<em> </em>by<em> </em>&#51109;&#49340;&#50857;)&#8212;a Korean text on cryptography and network security in Python&#8212;was far beyond my comprehension at the time. While I can parse it effortlessly now, back then I grasped maybe 60% of the concepts, if I&#8217;m being generous.</p><p>Some of my earliest engineering experiences still baffle me today. At age ten, I successfully upgraded the network card in my mother&#8217;s aging laptop&#8212;a feat I still can&#8217;t quite explain. The machine shipped with Windows 7, but I was desperate to experience Windows 10&#8217;s sleek, modern interface. After multiple failed upgrade attempts, I dove into online forums, searching for others with similar symptoms.</p><p>I stumbled upon a blog post describing my exact issue with a nearly identical laptop model. The solution? A network card upgrade&#8212;Windows 10 apparently lacked drivers for the older hardware. Armed with nothing but this single blog post and unwavering determination, I ordered the recommended card, completely disassembled the laptop, swapped the hardware, and reassembled everything. The upgrade to Windows 10 went through without a hitch.</p><p>Looking back, I&#8217;m amazed that my mother trusted her ten-year-old with such a task. That trust would soon be tested.</p><h2>The Incident That Changed Everything</h2><p>My next experiment&#8212;attempting to dual-boot Ubuntu&#8212;ended in disaster. I accidentally formatted the entire drive, obliterating years of irreplaceable family photos and documents. Despite spending hundreds of dollars on professional data recovery, we salvaged only fragments.</p><p>This catastrophe convinced my parents that perhaps I needed my own machine for these experiments. When I was twelve, my mother made a unilateral decision to purchase me a $6,000 iMac&#8212;a purchase she hadn&#8217;t cleared with my father, who was our family&#8217;s sole income earner. The tension was palpable, but the deed was done, and my mother&#8217;s unofficial veto power prevailed.</p><p>I&#8217;d justified the iMac request by claiming macOS&#8217;s gaming limitations would keep me focused on programming. Naturally, I immediately installed Windows via Bootcamp and played games. But I also kept my promise&#8212;I discovered FreeBSD and became obsessed with contributing to its base system.</p><h2>The Challenge of Finding Direction</h2><p>Unlike web development, with its abundance of detailed roadmaps and tutorials, kernel development resources are scarce and scattered. This knowledge is typically reserved for third-year university courses, leaving self-taught programmers to piece together their own curriculum.</p><p>After years of trial and error, I&#8217;ve assembled the roadmap I wish I&#8217;d had when starting. While there may be more efficient paths, this one worked for me.</p><h2>Roadmap to Kernel Developer</h2><p>This is subjective path that I found and followed. There could be better roadmaps that are more efficient and in higher quality. I only listed books below because I believe that books are the most efficient, high quality, and accurate resources for programming. If you want to be a kernel developer, you&#8217;ll need to read a lot of standard documents, papers, and man pages. Learning through books can help you prepare for those situations.</p><h3>1. Master the C Language</h3><p>C is non-negotiable for kernel development. You need to read C code as naturally as you read English. The language itself is deceptively small, but its evolution means you&#8217;ll need multiple perspectives:</p><p><strong>Start here:</strong></p><ul><li><p><strong>C Programming: A Modern Approach</strong> (2nd Edition) by K. N. King &#8212; An excellent introduction, though it doesn&#8217;t cover the latest standards</p></li></ul><p><strong>Then understand the philosophy:</strong></p><ul><li><p><strong>The C Programming Language</strong> (2nd Edition) by Kernighan &amp; Ritchie &#8212; Not for beginners, but essential for understanding C&#8217;s design philosophy and machine-oriented thinking</p></li></ul><p><strong>Finally, modernize your approach:</strong></p><ul><li><p><strong>Modern C</strong> (3rd Edition) by Jens Gustedt &#8212; Learn how C is written today, which differs significantly from traditional approaches</p></li></ul><h3>2. Algorithms and Data Structures</h3><p>Programming languages are merely tools&#8212;algorithms and data structures are what make programs actually do something meaningful.</p><p><strong>Essential reading:</strong></p><ul><li><p><strong>Guide to Competitive Programming</strong> (3rd Edition) by Antti Laaksonen &#8212; A solid introduction to fundamental concepts</p></li><li><p><strong>Competitive Programming 4</strong> by Halim, Halim &amp; Effendy &#8212; Advanced material for serious practitioners</p></li></ul><p><em>For Korean readers:</em> <strong>&#50508;&#44256;&#47532;&#51608; &#47928;&#51228; &#54644;&#44208; &#51204;&#47029;</strong> by &#44396;&#51333;&#47564; remains my favorite comprehensive introduction to the field.</p><h3>3. Computer Architecture</h3><p>Understanding the machine beneath the code is crucial for kernel developers. You need to know how software and hardware dance together.</p><p><strong>The heavyweight champion:</strong></p><ul><li><p><strong>Computer Systems: A Programmer&#8217;s Perspective</strong> (3rd Edition) by Bryant &amp; O&#8217;Hallaron &#8212; Dense, comprehensive, and absolutely essential. This textbook assumes self-directed learning, so prepare for extensive research and problem-solving.</p></li></ul><p><strong>Alternative perspective:</strong></p><ul><li><p><strong>Computer Architecture: A Quantitative Approach</strong> (7th Edition) by Patterson &amp; Hennessy &#8212; Highly recommended by the community</p></li></ul><h3>4. Operating Systems</h3><p>After 1-2 years of foundation building, you&#8217;re ready for the main event.</p><p><strong>Modern and accessible:</strong></p><ul><li><p><strong>Operating Systems: Three Easy Pieces</strong> by the Arpaci-Dusseaus &#8212; More current and approachable than traditional texts, available free online (though I recommend print for your eyes)</p></li></ul><p><strong>For Linux enthusiasts:</strong></p><ul><li><p><strong>&#46356;&#48260;&#44613;&#51012; &#53685;&#54644; &#48176;&#50864;&#45716; &#47532;&#45573;&#49828; &#52964;&#45328;&#51032; &#44396;&#51312;&#50752; &#50896;&#47532;</strong> by &#44608;&#46041;&#54788; &#8212; Hands-on kernel hacking (Korean only, unfortunately)</p></li></ul><p><strong>For FreeBSD developers:</strong></p><ul><li><p><strong>The Design and Implementation of the FreeBSD Operating System</strong> (2nd Edition) by Neville-Neil &amp; McKusick &#8212; Comprehensive but theoretical; essential for FreeBSD contributors</p></li></ul><h2>The Reality Check</h2><p>This roadmap represents a minimum three-year commitment. Unlike web development&#8217;s relatively quick onramp, kernel development demands deep understanding of both software and hardware layers. And this is just the beginning&#8212;kernel developers never stop learning, constantly adapting to new architectures, technologies, and paradigms.</p><p>I&#8217;ve completed most of this curriculum and still consider myself a novice. If you&#8217;re serious about kernel development, you need two things above all: genuine passion for systems programming and the humility to embrace lifelong learning.</p><p>The path is long, the learning curve is steep, but for those who persist, you&#8217;ll gain the ability to work at the very foundation of modern computing. Is it worth it? For me, absolutely.</p>]]></content:encoded></item><item><title><![CDATA[Finding My Path: From FreeBSD Contributor to Foundation Co-op]]></title><description><![CDATA[I will have my first co-op (winter 2026) at the FreeBSD Foundation as a kernel developer]]></description><link>https://minsoo.io/p/finding-my-path-from-freebsd-contributor</link><guid isPermaLink="false">https://minsoo.io/p/finding-my-path-from-freebsd-contributor</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Tue, 21 Oct 2025 22:32:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/b98fed85-bd7a-4e4d-a110-87c3e95c0a98_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2>The Waterloo Paradox</h2><p>The University of Waterloo&#8217;s co-op program is both its greatest strength and its students&#8217; most daunting challenge. As a Stream 4 Computer Engineering student, I barely had time to settle into my 1A term before the job hunt began. September rolled around, and suddenly everyone was polishing r&#233;sum&#233;s and practicing for interviews. The university requires five co-op credits to graduate&#8212;a requirement that feels overwhelming when companies barely glance at first-year applications.</p><p>My WaterlooWorks experience was typical: three interview offers, all for web development roles. A California startup reached out directly through my r&#233;sum&#233;, only to ghost me after I replied. The other two&#8212;a company in Oakville and a startup in North York&#8212;interviewed me, but my heart wasn&#8217;t in it. I&#8217;d done enough web development to know it wasn&#8217;t my calling.</p><div class="digest-post-embed" data-attrs="{&quot;nodeId&quot;:&quot;96b30601-d6ac-4dfc-a53b-a7c4c017b471&quot;,&quot;caption&quot;:&quot;The Beginning&quot;,&quot;cta&quot;:null,&quot;showBylines&quot;:true,&quot;showDescription&quot;:true,&quot;showImage&quot;:true,&quot;size&quot;:&quot;sm&quot;,&quot;isEditorNode&quot;:true,&quot;title&quot;:&quot;Why I'm Leaving Web Development&quot;,&quot;publishedBylines&quot;:[{&quot;id&quot;:167787206,&quot;name&quot;:&quot;Minsoo Choo&quot;,&quot;bio&quot;:&quot;FreeBSD Kernel Developer &#8226; CHERI Alliance Ambassador &#8226; University of Waterloo Computer Engineering (Class of &#8217;30)&quot;,&quot;photo_url&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/930ec2b0-2266-4098-a89e-76652d7b0c68_2769x2769.jpeg&quot;,&quot;is_guest&quot;:false,&quot;bestseller_tier&quot;:null}],&quot;post_date&quot;:&quot;2025-07-30T20:49:00.000Z&quot;,&quot;cover_image&quot;:&quot;https://substack-post-media.s3.amazonaws.com/public/images/9c3ce48a-5bd6-48bc-b2c8-4c897d8a953f_2000x1423.jpeg&quot;,&quot;cover_image_alt&quot;:null,&quot;canonical_url&quot;:&quot;https://minsoo.io/p/why-im-leaving-web-development&quot;,&quot;section_name&quot;:null,&quot;video_upload_id&quot;:null,&quot;id&quot;:199019648,&quot;type&quot;:&quot;newsletter&quot;,&quot;reaction_count&quot;:0,&quot;comment_count&quot;:0,&quot;publication_id&quot;:8751651,&quot;publication_name&quot;:&quot;Minsoo Choo&quot;,&quot;publication_logo_url&quot;:&quot;https://substackcdn.com/image/fetch/$s_!v4hh!,f_auto,q_auto:good,fl_progressive:steep/https%3A%2F%2Fsubstack-post-media.s3.amazonaws.com%2Fpublic%2Fimages%2F251537e3-ac76-4a30-adf6-1072fe518d0d_1280x1280.png&quot;,&quot;belowTheFold&quot;:false,&quot;youtube_url&quot;:null,&quot;show_links&quot;:null,&quot;feed_url&quot;:null}"></div><p> it wasn&#8217;t my calling.</p><p>That&#8217;s when I remembered where I truly belonged: the world of operating systems.</p><h2>A Five-Year Journey to My First Co-op</h2><p>My journey with kernels and CPU architectures began long before university. At thirteen, I submitted my first patch to <a href="https://www.freebsd.org">the FreeBSD Project</a>. That first <a href="https://cgit.freebsd.org/doc/commit/?id=23b3362cfb3ce5c5cbf6fae8c41db9bc983940d4">commit</a> on May 5th, 2021, marked the beginning of a consistent contribution habit that carried me through high school. I spent my free time diving into man pages, updating C17 implementations in the base system, and helping import jemalloc 5.3.0&#8212;unconventional hobbies for a teenager, but they were what fascinated me.</p><p>I never expected rewards&#8212;seeing my name in git logs was reward enough. But those five years of contributions (always balanced with schoolwork as my priority) became my unconventional path to my dream co-op.</p><p>Operating systems are typically third-year material at university. Most students don&#8217;t touch kernel code until they&#8217;ve built a solid foundation in computer science fundamentals. Yet here I was, a first-year student with half a decade of practical experience in the field. After realizing this unique position, I reached out to a developer at the FreeBSD Foundation&#8212;someone I&#8217;d met during my two BSDCan attendances, sponsored by the foundation.</p><p>Against all odds, they offered me my first co-op position.</p><h2>An Ambitious Roadmap</h2><p>My plans for these four months at the FreeBSD Foundation are ambitious, perhaps overly so. The review process is strict, and time is limited, but I&#8217;m determined to contribute as much as possible:</p><ul><li><p><strong>Infrastructure modernization</strong>: Migrating our code forge to <a href="https://forgejo.org">Forgejo</a></p></li><li><p><strong>Documentation enhancement</strong>: Creating comprehensive kernel documentation (Doxygen + Sphinx + Breathe + Exhale) inspired by <a href="https://docs.kernel.org">the Linux Kernel documentation</a></p></li><li><p><strong>Performance optimization</strong>: Adopting AVX/AVX2/AVX10 SIMD instructions in libc based on <a href="https://man.freebsd.org/cgi/man.cgi?query=simd&amp;manpath=FreeBSD+15.0-CURRENT">simd(7)</a></p></li><li><p><strong>Standards compliance</strong>: Implementing C23 and Single Unix Specification requirements</p></li><li><p><strong>Compatibility improvements</strong>: Matching Linuxulator and Linux KPI functionalities to the latest kernel</p></li><li><p><strong>Scheduler optimization</strong>: Enhancing <a href="https://man.freebsd.org/cgi/man.cgi?query=sched_ule">sched_ule(4)</a> for hybrid processors (Intel P/E-core, ARM big.LITTLE)</p></li><li><p><strong>Continuous bug fixes</strong>: Contributing to overall system stability</p></li></ul><p>This first co-op is about mastering operating system fundamentals. Looking ahead, I&#8217;m already mapping out my trajectory: exploring <a href="https://en.wikipedia.org/wiki/Capability_Hardware_Enhanced_RISC_Instructions">CHERI</a> and <a href="https://en.wikipedia.org/wiki/RISC-V">RISC-V</a> ports for my second and third terms, with companies like <a href="https://www.capabilitieslimited.co.uk">Capabilities Limited</a> and <a href="https://codasip.com">Codasip</a> on my radar. Eventually, I want to delve into processor design with HDL and compiler development.</p><h2>Swimming Against the Current</h2><p>While my peers chase positions in web development or applied AI&#8212;fields increasingly dominated by LLM coding assistants&#8212;I&#8217;m deliberately choosing a different path. Too many startups treat co-op students as cheap labor, burning them out with repetitive tasks that teach little of value. Big tech companies, despite their prestige, often mean following a manager&#8217;s roadmap rather than exploring the technology that fascinates you.</p><p>I&#8217;m not chasing the highest salary or the most recognizable company name. I&#8217;m chasing knowledge in the field that has captivated me since I was thirteen. The FreeBSD Foundation saw something in me&#8212;perhaps the same passion for operating systems and CPU architectures that has driven me all these years.</p><h2>The Value of Hard-Won Experience</h2><p>Waterloo&#8217;s six co-op terms might seem grueling to some, but I see them differently: 24 months of deep, hands-on experience in a field that typically requires years of study to enter. While balancing operating systems work with undergraduate studies is challenging, these co-op terms offer something invaluable&#8212;the opportunity to learn by doing, to contribute to systems that power the internet&#8217;s infrastructure, and to work alongside developers who&#8217;ve shaped the technology we rely on daily.</p><p>The FreeBSD Foundation took a chance on a first-year student with an unconventional background. Now it&#8217;s my turn to prove that passion, combined with years of consistent contribution, can be just as valuable as a traditional academic path.</p>]]></content:encoded></item><item><title><![CDATA[Announcing My Role as CHERI Alliance Ambassador]]></title><description><![CDATA[Starting from October 2025, I'm part of the CHERI Alliance as an ambassador]]></description><link>https://minsoo.io/p/announcing-my-role-as-cheri-alliance</link><guid isPermaLink="false">https://minsoo.io/p/announcing-my-role-as-cheri-alliance</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Mon, 20 Oct 2025 20:08:04 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/a4a7d72e-5541-42d1-8e03-97ae6f46bfa8_2000x1333.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<p>I&#8217;m joining CHERI Alliance as an ambassador, working to transform cybersecurity at its foundation.</p><p>Memory safety bugs cause 70% of cyber vulnerabilities, leading to disasters like OpenSSL <a href="https://en.wikipedia.org/wiki/Heartbleed">Heartbleed</a> and the <a href="https://en.wikipedia.org/wiki/2024_CrowdStrike-related_IT_outages">2024 CrowdStrike outage</a> ($5.4 billion in losses). <a href="https://en.wikipedia.org/wiki/Capability_Hardware_Enhanced_RISC_Instructions">The CHERI technology</a>, developed over 15 years by Cambridge University and SRI International, prevents these attacks through hardware-enforced memory protection rather than endless software patches.</p><p>The momentum is extraordinary. The UK government <a href="https://www.gov.uk/government/publications/cheri-technology-for-cyber-security/cheri-technology-for-cyber-security">invested</a> &#163;80 million alongside &#163;200 million from industry, with backing from DSIT, NCSC/GCHQ, DSTL, and DARPA. Industry giants Google, Microsoft, and Arm have joined alongside BT Group and Siemens, recognizing that hardware-level security is no longer optional.</p><p>I&#8217;m particularly excited about our working groups porting critical operating systems to CHERI. FreeBSD, FreeRTOS, Zephyr, and seL4 have all been ported to run on CHERI hardware, with teams actively developing and maintaining these implementations. This ecosystem work ensures CHERI can protect everything from embedded IoT devices to enterprise servers, making memory safety accessible across the entire computing stack.</p><p>Microsoft found CHERI would have <a href="https://www.microsoft.com/en-us/msrc/blog/2020/10/security-analysis-of-cheri-isa">prevented</a> two-thirds of their 2019 vulnerabilities. The technology is practical too &#8211; existing software often needs <a href="https://freebsdfoundation.org/blog/enhancing-memory-safety-in-programming-insights-from-the-freebsd-vendor-summit/">less than 0.03% code changes</a> to become memory-safe. As we deploy AI and connect critical infrastructure, we can&#8217;t afford to keep patching symptoms. CHERI addresses the root cause.</p><p>While I originally launched this Substack to chronicle computer architecture and university life, my passion for operating systems has taken the wheel. Going forward, you&#8217;ll find articles, updates, and announcements covering operating systems and CPU architectures&#8212;particularly FreeBSD, Linux, CHERI, and RISC-V.</p><p>If your company takes cybersecurity seriously, consider joining the CHERI Alliance. We&#8217;re building secure-by-design systems and welcome everyone who shares this vision. It&#8217;s time to stop playing defense against memory vulnerabilities and solve the problem at its root.</p>]]></content:encoded></item><item><title><![CDATA[Why I'm Leaving Web Development]]></title><description><![CDATA[And what I learned]]></description><link>https://minsoo.io/p/why-im-leaving-web-development</link><guid isPermaLink="false">https://minsoo.io/p/why-im-leaving-web-development</guid><dc:creator><![CDATA[Minsoo Choo]]></dc:creator><pubDate>Wed, 30 Jul 2025 20:49:00 GMT</pubDate><enclosure url="https://substack-post-media.s3.amazonaws.com/public/images/9c3ce48a-5bd6-48bc-b2c8-4c897d8a953f_2000x1423.jpeg" length="0" type="image/jpeg"/><content:encoded><![CDATA[<h2><strong>The Beginning</strong></h2><p>I've been in web development since the end of 2023, for almost two years now. My first project was a <strong><a href="https://nbe3u.vercel.app/">summaive project</a></strong> for my Grade 11 English class written in Next.js. After that, I built websites for <strong><a href="https://nhsmusic.vercel.app/">my school band</a></strong> and <strong><a href="https://naclb.vercel.app/">city jazz band</a></strong>, again, written in Next.js. At first, it was fun, with all those Tailwind CSS and state management. Unlike other programming areas, I could see the results of my work immediately just by running <code>next dev</code> in my terminal. Compared to SwiftUI, web development felt more easier but more fun, especially with npm libraries that faciltate the development process.</p><p>Then, I found Vite and SvelteKit. I was amazed by the compiler approach (which Vue and React now have experimental support for) and the performance of Svelte. SvelteKit was similar to Next.js, so it was pretty easy to learn the fundamentals. I migrated all my three websites to SvelteKit, and it was a breeze. However, I encountered my first challenge in web development &#8212; dependencies. In my Next.js projects, I heavily used <strong><a href="https://motion.dev/">Motion</a></strong> (it was called <em>Framer Motion</em> back then). It was a great library, as I could apply fancy animations in a few lines of code. But it was binded to React, so when I migrated to SvelteKit, I had to implement the same animations in a different way. I spent almost a week trying to implement the same animations in Svelte, and that was the first time I was disappointed by the web development ecosystem.</p><h2><strong>First Big Project in My Life</strong></h2><p>Around the end of 2024, I joined <strong><a href="https://www.poliwave.com/ca/fed/projection">Poliwave</a></strong>, a platform that provides Canadian election projection. I was the only developer with previous experience in the team, and I was responsible for the frontend and backend. I was excited to work on a project that was actually useful, and I was excited to work with a team that was actually professional.</p><p>However, it was too difficult to maintain such a large project by myself. I was the only developer, and I was responsible for both the frontend and backend. I was overwhelmed by the amount of work, and since my colleague who maintained the actual electoral projection also wrote the code for the web app, it was really hard to maintain the codebase in a good state. Sometimes the code was deployed even though it failed checks on GitHub Actions, and when I tried to fix the issues, it was too late to fix them without reverting the changes to the initial state.</p><p>At last, it reached the state where the website was lagging and it had glitches everywhere, but I was unable to debug and fix the core issues due to the low quality of the codebase. We added patches on the codebase to mitigate the issues, but since the code was already in a bad state, another glitch appeared after the patch was applied.</p><p>We also had to migrate between different UI libraries, and everytime we did, it broke the existing codeflow. Since it was really hard to create our own design system in a team of two, we had to use a third party library, and it was painful to find the right components to use. Even though we made a decision on which library to use, our mind changed in a few days, and we had to migrate to a different library again.</p><p>I felt too tired of spending so much time and energy on visual side of the project. Unlike other fields of programming, frontend development is mostly about designing and implementing the UI, not the core logic of the project. Instead of building a complete project, I was just destroying and rebuilding the project over and over again without any progress.</p><p>For these reasons, I lost interest in most part of web development. Except for reading release notes of SvelteKit, Vite, and Bun, I switched to other fields of programming such as operating systems, embedded systems, AI, and blockchain.</p><h2><strong>Got a Job</strong></h2><p>In July 2025, I got a summer student job at <strong><a href="https://www.cheoresearch.ca/">CHEO RI</a></strong>, a research institute in Ottawa. I love the work I do there and my colleagues are great, but while I was working on the project, I made my decision to leave web development after this job is over in August.</p><p>My team spent first three days on determining the tech stack, which was changed again on the next week. I felt very unproductive and saw myself as a website designer, not a programmer. As a side project, I built a RAG-based chatbot platform with my friend. Because we focused more on the programming aspect rather than the design aspect, it was way more fun than any of my web projects.</p><p>I also studied blockchain and AI, and I was amazed by the potential of these technologies. I also had an opportunity to revisit the computer architecture and low-level programming, and although they were more difficult than web development, they didn't cause me as much frustration as web development did. I felt that I was being a computer engineer, not a designer, and that was the time that I decided to leave the world of web development.</p><h2><strong>Issues with Web Development Ecosystem</strong></h2><h3><strong>The Ecosystem is Too Fragmented</strong></h3><p>Let me list some technologies you can use to build a web project:</p><ul><li><p>Runtime: Node.js, Bun, Deno, etc.</p></li><li><p>Framework: Next.js, SvelteKit, Nuxt.js, Astro,etc.</p></li><li><p>Library: React, Vue, Svelte, etc.</p></li><li><p>UI Library: Tailwind CSS, Shadcn UI, etc.</p></li><li><p>Package Manager: npm, yarn, pnpm, bun, etc.</p></li><li><p>Build Tool: Vite, Webpack, rsbuild, Turbopack, etc.</p></li><li><p>Testing Framework: Jest, Vitest, Playwright, etc.</p></li><li><p>Linting &amp; Formatting: ESLint, Prettier, etc.</p></li><li><p>Typing: TypeScript, JSDoc, etc.</p></li><li><p>Database: Supabase, PostgreSQL, etc.</p></li><li><p>Hosting: Vercel, Netlify, etc.</p></li><li><p>CI/CD: GitHub Actions, GitLab CI, etc.</p></li><li><p>Monitoring: Sentry, etc.</p></li><li><p>Analytics: Google Analytics, etc.</p></li><li><p>and so on...</p></li></ul><p>There are so many options to choose from, and there is new technology coming out every day. In 2025, people complain about the best LLM model being updated every month, but compared to web technologies in 2022-2024, it's not even a big deal. It's really hard to keep up with the latest trends and technologies, and it's hard to find innovation in the web development ecosystem. The last time I remember innovation in the web development ecosystem was when Svelte introduced the compiler approach and when node-rs made using Rust in web development possible. Apart from that, most hyping techonologies that appearaed in that era is not even mentioned anymore (Who remembers Remix, MongoDB, Gatbsy, etc?).</p><h3><strong>Unsafe Nature of Javascript</strong></h3><p>No, I'm not talking about memory safety like C/C++. I'm talking about the type safety of Javascript. Although Typescript and JSDoc are great, they are not the core specification of Javascript. I used Typescript in my projects, but my colleague didn't follow the type safety rules, and even <strong>deployed</strong> the code while the CI check was failing. If this was a C/C++ project, the binary would have been built at the first place, even though they might contain memory safety issues.</p><h3><strong>Ecosystem that Has Both Legacy and Modern Technologies</strong></h3><p>In Javascript ecosystem, we see a lot of legacy syntax and technologes and their modenr counterparts. Callback vs async, Webpack vs Vite, CommonJS vs ESM, etc. Some times we need to use Javascript transpilers to run code on old browsers due to lack of something like ABI compatibility. Although this is not a big issue for building a new project, it's quite problematic when you're maintaining a legacy project. Imagine that you are working on two projects, one is relatively new using Vite and ES6 code while the other is legacy project using Webpack and deprecated Vue v2. Yes, it would be very painful to maintain those two at the same time.</p><p>You might say that this is the same problem in other fields of programming. But in web development, this happens too frequently. C++98 was used for 16 years until the release of C++11. Although there have been new features in C++20, it was not a major overhaul with breaking changes like CommonJS to ESM or Vue v2 to Vue v3. Note that while using C++11 is not <em>legacy</em> in 2025, Webpack, which people replaced with Vite, was released in 2012.</p><h2><strong>What's Next?</strong></h2><p>As I'm going to the University of Waterloo for computer engineering, I will focus on embedded programming and circuit design. I will also study AI and blockchain, although I'm not sure if I will be able to use them in my future career.</p><p>Although I will still follow the release notes of SvelteKit, Vite, and Bun, I will completely keep distance from the web development ecosystem. The only reason I'm still following the release notes is because I believe that those three are the only innovative projects left in the web development ecosystem. Others seem to repeating same ideas over and over again, which I'm not interested in.</p><p><em>Edit for September 20th, 2025: For the last two months, I&#8217;ve tried many things: infrastructure, database, AI, etc. At the end, I chose operating systems and compilers for my future careers. Even though I&#8217;ve been learning those for more than three years now, they are the most interesting and fascinating topics to me.</em></p>]]></content:encoded></item></channel></rss>