<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title></title>
    <description>lol hi</description>
    <link>https://www.simshadows.com/</link>
    <atom:link href="https://www.simshadows.com/feed.xml" rel="self" type="application/rss+xml"/>
    <pubDate>Wed, 20 Sep 2023 04:44:16 +0000</pubDate>
    <lastBuildDate>Wed, 20 Sep 2023 04:44:16 +0000</lastBuildDate>
    <generator>Jekyll v3.9.3</generator>
    
      <item>
        <title>Rest In Peace, TotalBiscuit.</title>
        <description>&lt;p&gt;Rest In Peace,&lt;/p&gt;

&lt;p&gt;John Peter “TotalBiscuit” Bain&lt;/p&gt;

&lt;p&gt;July 8, 1984 - May 24, 2018&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-25-01-img1-totalbiscuit.jpg&quot; alt=&quot;TotalBiscuit&quot; height=&quot;70%&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;
</description>
        <pubDate>Fri, 25 May 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/05/25/01-rest-in-peace-totalbiscuit/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/05/25/01-rest-in-peace-totalbiscuit/</guid>
        
        
        <category>People</category>
        
      </item>
    
      <item>
        <title>Death And Rebirth Of Discontinued Online Games</title>
        <description>
&lt;p&gt;In my &lt;a href=&quot;/2018/05/13/01-why-record-gameplay/&quot;&gt;last post&lt;/a&gt;, I briefly discussed the impending closure of Funorb on the 7th of August this year, and that I started recording all my Arcanists gameplay in order to keep &lt;a href=&quot;https://www.youtube.com/playlist?list=PLn8SsDCCDln2j5MBMmNICvLN3U3JisdYc&quot;&gt;an archive&lt;/a&gt; of my final moments of fun with the game.&lt;/p&gt;

&lt;p&gt;This highlights a problem in gaming where online games die without official support for playing them past server shutdown. &lt;strong&gt;We want to play the game, we bought copies of the game, and the code for the servers to make the game run exists, yet because someone decided it to no longer be a benefit to run them, that’s it. The game’s gone.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;This can be particularly frustrating for the fans, and it certainly sucked when I heard that about Jagex’s &lt;em&gt;Funorb&lt;/em&gt;, which hosts my childhood favourites &lt;em&gt;Arcanists&lt;/em&gt; and &lt;em&gt;Steel Sentinels&lt;/em&gt;, along with other great games like &lt;em&gt;Armies of Gielinor&lt;/em&gt; and &lt;em&gt;Void Hunters&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Even with the limitations my parents put on my gaming habits back during highschool and the fact that I only had a Funorb subscription for a few short months (since we didn’t have a credit card and I was paying through a friend), I racked up 1080 ranked games with Arcanists and 309 ranked games with Steel Sentinels, equating to 347 hours of ranked gameplay (assuming 15 minutes per game), and many more unranked games (particularly with Steel Sentinels). I absolutely loved Arcanists and Steel Sentinels back then, and I still believe they’re amazing and fun games that I’d love to return back to on occasion, even if it’s just to play with friends and have some casual fun.&lt;/p&gt;

&lt;p&gt;Similarly, I was a huge fan of EA’s &lt;em&gt;Battleforge&lt;/em&gt; back in the day for its unique and riotous-fun take on the real-time strategy formula, awesome theme, and its lovely and colourful art direction.&lt;/p&gt;

&lt;p&gt;Battleforge shut down on the 31st of October, 2013, which was also the day of my highschool HSC Physics exam. Despite the importance of that exam, I still decided to make the most of Battleforge’s final hours, even sleeping at my computer desk with Battleforge open the night before the exam.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img1-battleforge.jpg&quot; alt=&quot;Some Battleforge campaign gameplay.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;h2 id=&quot;community-revivals&quot;&gt;Community Revivals&lt;/h2&gt;

&lt;p&gt;Thankfully, it’s not always doom and gloom. If a game is popular enough, people are smart enough to eventually figure something out.&lt;/p&gt;

&lt;p&gt;Player-made private servers are a staple for MMORPGs such as &lt;em&gt;World of Warcraft&lt;/em&gt;, &lt;em&gt;Runescape&lt;/em&gt;, older titles such as &lt;em&gt;Ultima Online&lt;/em&gt;, and dead titles such as &lt;em&gt;Star Wars Galaxies&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img2-starwarsgalaxies.jpg&quot; alt=&quot;Star Wars Galaxies.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Even for currently-supported MMORPGs such as World of Warcraft, private servers are still popular for allowing players to &lt;a href=&quot;https://www.kotaku.com.au/2015/05/the-people-who-still-play-world-of-warcraft-like-its-2006/&quot;&gt;play older versions&lt;/a&gt; of these titles, particularly if these older versions are preferred over newer versions, or simply for the nostalgia. Private servers also naturally gave full control to the community, and even allowed adding of custom content to the games.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img3-worldofwarcraft.jpg&quot; alt=&quot;Vanilla World of Warcraft gameplay screenshot.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Moving away from MMORPGs, many other online games have also been successfully revived by players.&lt;/p&gt;

&lt;p&gt;Official servers were axed in 2011 for &lt;em&gt;Supreme Commander: Forged Alliance&lt;/em&gt;, though LAN play and a campaign were still available. The &lt;a href=&quot;https://www.faforever.com/&quot;&gt;&lt;em&gt;Forged Alliance Forever&lt;/em&gt;&lt;/a&gt; project was the community’s response to this, giving the game a multiplayer lobby and match-making (thus avoiding the need for VPNs) that continues to run to this day, and a community client with frequent patching for bug fixes and balance changes.&lt;/p&gt;

&lt;p&gt;The Forged Alliance Forever client even goes well-beyond the game’s original functionality, adding additional features such as improved map and mod management, online map/mod/replay repositories, social features, a rating system, and co-op campaigns.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img4-supcomfa.jpg&quot; alt=&quot;Supreme Commander gameplay screenshot.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Allegiance&lt;/em&gt; is a shining example of what happens when a company supports its community’s efforts for revival. Allegiance’s online servers got the axe back in 2002, but succeeded well beyond its expiration date thanks to its small but loyal following.&lt;/p&gt;

&lt;p&gt;LAN play was originally supported, which allowed the community to continue playing in a limited fashion. In 2004, Microsoft released the source code under a shared software license, smoothly allowing continued development by the community under the name &lt;a href=&quot;https://www.freeallegiance.org/&quot;&gt;&lt;em&gt;FreeAllegiance&lt;/em&gt;&lt;/a&gt; and allowing the hosting of a community-driven online lobby. And just last year, Microsoft converted the software license to the open-source MIT license, allowing the game to be re-released onto Steam.&lt;/p&gt;

&lt;p&gt;I discovered the game around 2005 through a free games magazine and despite being absolute terrible at it, I played the game for years until my family upgraded all the computers to Windows Vista. I stopped playing due to lack of support for Vista, though it improved eventually, allowing me to occasionally dive back in.&lt;/p&gt;

&lt;p&gt;Despite the dated graphics and technology, Allegiance in my opinion stands the test of time for its uniqueness, community, and gameplay breadth and depth that few games are able to compare with.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img5-allegiance.jpg&quot; alt=&quot;Allegiance combat gameplay screenshot.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;On the other side of the spectrum, companies are also known to flex their legal rights against server emulators, with &lt;em&gt;Asheron’s Call&lt;/em&gt; and it sequel &lt;em&gt;Asheron’s Call 2&lt;/em&gt; being merely two examples of emulator efforts &lt;a href=&quot;http://massivelyop.com/2017/09/18/asherons-call-emulator-lead-explains-what-went-down-with-the-cease-and-desist/&quot;&gt;falling to legal cease and desist orders&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Turning our sights back to Funorb and Battleforge, perhaps there’s still hope.&lt;/p&gt;

&lt;p&gt;Hanging around the Funorb unofficial Discord, there are certainly talks of reverse-engineering the games and building server emulators, and people who seem to have looked through the code and the internal game logic. While I haven’t seen anything concrete yet, I’m quite hopeful that someone’s going to make a server emulator at some point. I might even take the challenge up myself if need be (it can be a great learning experience!).&lt;/p&gt;

&lt;p&gt;Also, at the time of writing, a Battleforge server emulator seems a lot closer to being “ready”, with &lt;a href=&quot;https://forum.skylords.eu/index.php?/topic/3616-important-open-beta-status-announcement/&quot;&gt;this recent announcement&lt;/a&gt; by the &lt;a href=&quot;https://forum.skylords.eu/&quot;&gt;&lt;em&gt;Skylords Reborn&lt;/em&gt;&lt;/a&gt; project on progress towards an open beta, and videos of the game working such as this video with early-alpha footage:&lt;/p&gt;

&lt;div style=&quot;text-align: center;&quot;&gt;
    &lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube-nocookie.com/embed/NN9A0htIXLk?rel=0&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;

&lt;p&gt;Really, it’s all just a matter of time.&lt;/p&gt;

&lt;h2 id=&quot;ephemerality-of-official-support&quot;&gt;Ephemerality Of Official Support&lt;/h2&gt;

&lt;p&gt;There will always be a time when a games company no longer sees the continued support of an old game viable. The reason for this I think is fairly obvious: games companies are businesses, and legal complications may even prevent them from acting for the interests of the players.&lt;/p&gt;

&lt;p&gt;Even if a company wanted to release server software, they’d need to spend time sanitizing it to remove anything unfit for distribution, and this could even prove impossible depending on the design of their systems. And even with the technical challenges sorted, unless a games company is doing it for PR, there’s no good reason for them to spend employee hours to solve both the technical and legal challenges that may exist.&lt;/p&gt;

&lt;p&gt;There’s also the problem of avoiding cannibalizing its newer products, further disincentivizing any good will. As an example, consider a scenario where a company wants to release a new online-only arena shooter while also killing off support for an older online-only arena shooter. If the company released server programs for the old title, they’d consider it more likely that some people (no matter how small) who would’ve bought the newer title would instead continue playing the older title. It may not even matter how small the possibility is for the release of server programs to cannibalize. Releasing server code can potentially pull customers from any present and future titles.&lt;/p&gt;

&lt;p&gt;Keeping assets as close as possible is also advantageous, giving a company more exclusive rights and control over the market. Relinquishing a great deal of control over a product and allowing public hosting means they lose the option of reusing it at a later date, perhaps to revive and subsequently monetize it, or to sell the assets off to another developer.&lt;/p&gt;

&lt;p&gt;I’m sure there are plenty more points of discussion, especially since I haven’t even attempted to touch any legal problems that may arise (such as re-licensing). But the point still stands: companies gain nothing from giving communities control and can even suffer for it, so why should they bother?&lt;/p&gt;

&lt;h2 id=&quot;consumer-pains&quot;&gt;Consumer Pains&lt;/h2&gt;

&lt;p&gt;Letting go of a well-loved videogame can be particularly painful. Oftentimes, we’ve invested so much of our lives on the particular game, spent so much time playing it, thinking of how we could get better at it, formed communities and friendships, and made plenty of fond memories. Even if you hardly play a particular game nowadays, losing the ability to play it can feel like losing a part of your life.&lt;/p&gt;

&lt;p&gt;For games with no dependence on online services (such as retro console games and most single-player PC games), it’s not too bad to simply lose the disk, cartridge, and/or console. Someone probably ripped it and the game is probably playable on a console emulator. Or in the worst case, you’d likely still be able to find a second-hand copy of the game for sale somewhere, and an old console or a copy of Windows 95 to play it with. Everything is self-sufficient enough that it’s quite easy to go back to.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img6-nes.jpg&quot; alt=&quot;Nintendo Entertainment System&quot; height=&quot;70%&quot; width=&quot;70%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;But for online games with complete dependence on online services, the loss of these services renders them completely unplayable on their own. The online server components are often highly complex yet kept secret by the company that hosted them, meaning a major technical effort is required by a group of skilled reverse-engineers in order to bring it back. Depending on the game, this can take years before an acceptable server emulator is developed (if at all). It’s been almost 5 years yet the Skylords Reborn project is only just moving towards an open-beta for its Battleforge server emulator. And even if the game gets a server emulator, its accuracy depends on how well people understand the game from the outside. (Exact precise accuracy may not matter, but it’s still worth noting.)&lt;/p&gt;

&lt;p&gt;If the game is niche, unique, and actually good, its loss can be even more painful. If similar-enough games exist, then the loss of an original isn’t so bad. They won’t be the same, but they can be similar enough to still enjoy the same gameplay. However, this is certainly not the case for Arcanists, Steel Sentinels, Battleforge, and Allegiance. All of these are great games that offer unique gameplay elements and combinations unseen elsewhere.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-05-19-01-img7-steelsentinels.png&quot; alt=&quot;Steel Sentinels gameplay screenshot.&quot; height=&quot;90%&quot; width=&quot;90%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The uniqueness factor perhaps applies a bit less to Supreme Commander’s fairly bread-and-butter RTS gameplay (not to mention the fact that the campaign and LAN are still playable without servers anyway). However, I contend that Supreme Commander offers a well-crafted, timeless take on the genre that is difficult to replace, so it offers itself as an example, showing that you don’t need to be particularly niche to be sorely missed.&lt;/p&gt;

&lt;h2 id=&quot;legal-and-technical-challenges&quot;&gt;Legal and Technical Challenges&lt;/h2&gt;

&lt;p&gt;Two points must first be made:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;All of the server code exists. If it’s not released, server emulators will eventually be made, albeit at the unnecessary expense of potentially thousands of developer hours.&lt;/li&gt;
  &lt;li&gt;Companies often launch aggressive legal action against server emulators.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Thankfully, &lt;a href=&quot;https://www.digitaltrends.com/gaming/online-games-dmca-exemption/&quot;&gt;the law could soon protect community-run online game revival efforts in the US&lt;/a&gt;, though the Entertainment Software Association opposes this, arguing that laws exempting officially abandoned games from DMCA takedowns can be seen as a form of competition against currently supported titles.&lt;/p&gt;

&lt;p&gt;If the legal issues are solved, one might consider that it doesn’t matter too much to get companies to distribute their proprietary game server programs. It’s only a matter of time before someone builds an emulator, and “the problem of building a server emulator is someone else’s problem, not mine”. But what if we avoided the need to emulate from scratch anyway? Instead of thousands of developer hours merely getting something to work, all that effort could instead be fast-tracked with the release of source code or even merely the compiled server programs. Developer hours could instead be spent on improving on what already exists, or even working on completely new projects.&lt;/p&gt;

&lt;p&gt;I won’t attempt to discuss the legal aspects of the problem of the release of proprietary game server code (I’m completely the wrong person to talk law), but assuming the legal problems are all sorted, we’d need companies to take an interest in consumer rights, and the technical challenges would need to be addressed. Unfortunately, these require businesses to act on good will, actively costing them man-hours that they technically don’t need to spend.&lt;/p&gt;

&lt;p&gt;At the end of the day, the preservation of online videogames is not the end of the world. But the code exists, so why can’t we use it to play these damn videogames?&lt;/p&gt;
</description>
        <pubDate>Sat, 19 May 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/05/19/01-death-and-rebirth-of-discontd-online-games/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/05/19/01-death-and-rebirth-of-discontd-online-games/</guid>
        
        
        <category>Gaming</category>
        
      </item>
    
      <item>
        <title>Why Record Your Gameplay?</title>
        <description>&lt;p&gt;Recently, Jagex announced the upcoming closure of their mini-games site, Funorb (see the announcement &lt;a href=&quot;http://services.funorb.com/m=forum_fo/c=zx-5mqnxxNA/forums.ws?0,1,125,137654&quot;&gt;here&lt;/a&gt;). Funorb is a childhood favourite of mine, and I absolutely love Arcanists and Steel Sentinels, so it pains me to know that I may never be able to play these games again.&lt;/p&gt;

&lt;p&gt;Thankfully, we’ve at least been given 3 months notice along with free paid membership, so I decided to take the opportunity to not only play the game, but record it and dump the videos on &lt;a href=&quot;https://www.youtube.com/playlist?list=PLn8SsDCCDln2j5MBMmNICvLN3U3JisdYc&quot;&gt;YouTube&lt;/a&gt; unedited along with full voice chat with my friend.&lt;/p&gt;

&lt;iframe width=&quot;560&quot; height=&quot;315&quot; src=&quot;https://www.youtube.com/embed/x8EL6_2hfrI&quot; frameborder=&quot;0&quot; allow=&quot;autoplay; encrypted-media&quot; allowfullscreen=&quot;&quot;&gt;&lt;/iframe&gt;

&lt;p&gt;My original reason was of course for archival purposes. I wanted to record practically &lt;em&gt;all&lt;/em&gt; matches I play, perhaps along with commentary, and upload everything mostly unedited. Eventually, I should end up with a big catalogue of videos that I can look through one day to maybe relive the game a bit, from my younger-self’s perspective. I’m making these videos mainly for myself, but I also want to put it out there on YouTube to maybe be discovered by others. If I end up with an audience, then cool, I guess.&lt;/p&gt;

&lt;p&gt;Naturally, this prompted another idea:&lt;br /&gt;
&lt;strong&gt;&lt;em&gt;What if I record all my other gameplay and put it on YouTube?&lt;/em&gt;&lt;/strong&gt;&lt;br /&gt;
(Or well, maybe not &lt;em&gt;all&lt;/em&gt; my gameplay, but the idea’s there.)&lt;/p&gt;

&lt;h3 id=&quot;archiving-and-building-a-big-time-capsule&quot;&gt;Archiving And Building A Big Time Capsule&lt;/h3&gt;

&lt;p&gt;As already discussed, it could be interesting to archive everything, essentially building up a big time capsule of my gameplay. Technically speaking, this entire venture shouldn’t cost me much (although my PC is 6 years old at this point, so it might struggle to record later games). All it should cost is a bit of extra time to set up recording software, then to upload videos to YouTube and enter in metadata.&lt;/p&gt;

&lt;p&gt;Future me will thank past me for giving future me all this nostalgia material, and I could use these recordings to:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;look back at old gameplay to relearn how to play certain games (and my old strategies and builds),&lt;/li&gt;
  &lt;li&gt;review past games in the short-term to identify areas of improvement, and&lt;/li&gt;
  &lt;li&gt;to provide video evidence for random bugs and oddities in games.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Putting it on YouTube will also mean it won’t cost me any local storage space - everything is offloaded over to Google’s data centres. However, this does mean losing video quality due to the server-side transcoding. As advances in data storage technology causes significant drops in price and efficiency, I want to eventually keep the lossless recordings, but for the older recordings on YouTube, downloading a lossy compressed copy off YouTube is the best I can do (unless Google miraculously provides original-quality lossless copies in the future.&lt;/p&gt;

&lt;h3 id=&quot;sharing-experiences-with-the-world&quot;&gt;Sharing Experiences With The World&lt;/h3&gt;

&lt;p&gt;Although I can put the videos on YouTube publicly, it doesn’t have to be public; I can keep them private, or unlist them for privacy. However, making them public can be great for sharing my experiences, for anyone who cares to watch.&lt;/p&gt;

&lt;p&gt;However, that assumes anyone even cares to look. It’s certainly not out of the question that an entire massive archive of raw gameplay footage may never get any views for however long Google decides my videos can be kept for (centuries?). But even if no one watches my videos, I lost nothing.&lt;/p&gt;

&lt;h3 id=&quot;privacy-concerns&quot;&gt;Privacy Concerns&lt;/h3&gt;

&lt;p&gt;Unfortunately, putting all this gameplay footage online may be information that could be used against me one day.&lt;/p&gt;

&lt;p&gt;Picture this: perhaps one day, I might promise someone to do a certain task at home, but if I don’t get it done (or maybe even if I do), me dumping large amounts of gameplay onto YouTube could be used against me, with accusations along the lines of “if he wasn’t so lazy, this could’ve been completed”, or “if he wasn’t so lazy, this could’ve been done better”.&lt;/p&gt;

&lt;p&gt;Someone could also use my video uploading patterns for malicious purposes, such as for planning break-ins.&lt;/p&gt;

&lt;p&gt;All of these concerns are also shared with actual professional streamers (such as on Twitch) and professional YouTubers, so I could borrow some of their wisdom.&lt;/p&gt;

&lt;p&gt;For instance, I’ll need to ensure that I allow no personal information to leak into my videos. This can be easy if I’m gaming on my own, but it can be more of a problem when I’m casually playing with friends with voice chat. We don’t necessarily always talk about our personal lives, but occasionally, we can get things like:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Occasionally mentioning names and other private information,&lt;/li&gt;
  &lt;li&gt;Occasionally mentioning birthdays and other events in our lives,&lt;/li&gt;
  &lt;li&gt;Forgetting to mute our microphones when our families may walk in and talk about private things, and&lt;/li&gt;
  &lt;li&gt;Saying or discussing things that may be offensive to others (even if none of us in the voice call are offended ourselves).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I’ll also need watch my uploading schedule. Highly frequent video postings can indicate that I’m having a long break from work or school, while gaps in my upload schedule can indicate when I’m heading out for work/school, or if I’m on a long trip overseas (or even domestic). All of these things could be leveraged by someone with the wrong intentions.&lt;/p&gt;

&lt;h3 id=&quot;feeling-less-relaxed-during-recordings&quot;&gt;Feeling Less Relaxed During Recordings&lt;/h3&gt;

&lt;p&gt;Without a recording going on, I’m naturally more relaxed, knowing that everything that’s happening is kept to myself, and I can go as crazy as I want. No one will know.&lt;/p&gt;

&lt;p&gt;While recording, I find that there’s added pressure to maintain privacy while also being presentable to the outside world. This can cause undesirable behavioural pattern shifts, such as increased stiffness and acting nervous as though one is in front of an audience, or otherwise simply not acting “natural”. This may also reduce the enjoyment of a videogame.&lt;/p&gt;

&lt;p&gt;Sure, I’m not necessarily making these videos for others, but I don’t want to produce something that may be looked on in disgust one day, even if the video is private and the only person who will know is myself.&lt;/p&gt;

&lt;p&gt;And even if I’m not the problem, it can be a problem for other people if they’re in the game with me (especially if voice chat is on). Even if people never say that they mind, I’ll still be worried.&lt;/p&gt;

&lt;h3 id=&quot;the-satisfaction-of-producing-content&quot;&gt;The Satisfaction Of Producing Content&lt;/h3&gt;

&lt;p&gt;I’ve gotten a bit negative with those last two discussion points, so I’d like to discuss a more positive one: satisfaction of producing content with my time.&lt;/p&gt;

&lt;p&gt;This is a lot of why I’m maintaining a blog. Content creation is satisfying because I want to produce things for others. Ideas and experiences are great, but sharing them is even better. So why not extend it to gaming? Gaming is already satisfying for the moment-to-moment experiences, so why not try to capture it?&lt;/p&gt;

&lt;p&gt;I personally feel that knowing my experiences are captured by screen recording and being intentionally (by myself) saved somewhere is satisfying. My time &lt;em&gt;feels&lt;/em&gt; much more well-spent if I produce things, no matter how mundane (such as raw gameplay videos), and I &lt;em&gt;feel&lt;/em&gt; more productive while playing videogames this way.&lt;/p&gt;

&lt;p&gt;And who knows, maybe I might actually end up building an audience and pivot into producing “proper” gaming content? I’m not exactly sure how that might happen, but then again, I’m not sure many of today’s successful YouTubers in the gaming category knew either. That &lt;em&gt;could&lt;/em&gt; be an even funner yet productive way of spending my leisure time while also making a bit of extra money on the side.&lt;/p&gt;

&lt;h3 id=&quot;closing-thoughts&quot;&gt;Closing Thoughts&lt;/h3&gt;

&lt;p&gt;It’s an attractive idea, yet also surprisingly complicated. For me, I think I’ll continue exploring this idea of uploading gameplay, although I’ll probably end up uploading the majority of them as private YouTube videos.&lt;/p&gt;
</description>
        <pubDate>Sun, 13 May 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/05/13/01-why-record-gameplay/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/05/13/01-why-record-gameplay/</guid>
        
        
        <category>Gaming</category>
        
      </item>
    
      <item>
        <title>Epic Fail #5: Not writing fast-fail code</title>
        <description>&lt;p&gt;For distributed systems class recently, we had to write a simulated distributed network in Erlang.&lt;/p&gt;

&lt;p&gt;The assignment involved getting a whole bunch of Erlang processes (which are &lt;em&gt;basically&lt;/em&gt; really lightweight threads) to send messages to each other according to the specification. It had a bit of a convoluted way of doing things, but it was intentionally to produce a model that demonstrated an important concept in distributed systems, albeit without the additional complexity layers of socket programming and networking.&lt;/p&gt;

&lt;p&gt;I ended up with a bug that wasted an embarrassing number of hours, which got me slowly stepping through a very substantial portion of my program’s functionality in reverse. The entire program culminated into one process producing a small amount of outputs. Being a simulation of a distributed system of several concurrently running nodes, this meant tracing through a web of message-passing.&lt;/p&gt;

&lt;p&gt;A lot of the time wasted during debugging was actually due to poor assumptions I made about how the system worked. That’s an entirely separate &lt;em&gt;epic fail&lt;/em&gt; on its own (see the appendix section), but that’s not the focus of this particular post.&lt;/p&gt;

&lt;p&gt;It turned out that towards the beginning of the entire message exchange, I made a one-character typo. This would’ve been caught instantly with good programming practices.&lt;/p&gt;

&lt;h2 id=&quot;disclaimer&quot;&gt;Disclaimer&lt;/h2&gt;

&lt;p&gt;I’m kinda a super-noob at Erlang and functional programming in general. I literally crash-coursed it over the course of an hour. If I’ve completely missed the mark on something, feel free to yell at me at &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;contact@simshadows.com&lt;/code&gt;.&lt;/p&gt;

&lt;h2 id=&quot;the-problematic-code&quot;&gt;The Problematic Code&lt;/h2&gt;

&lt;p&gt;The erroneous Erlang code took the following form:&lt;/p&gt;

&lt;div class=&quot;language-erl highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt;
    &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=:=&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;commited&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;true&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;This is basically equivalent to the following pseudocode if-else:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;IF (Foo == commited) THEN
    doSomething()
ELSE
    doSomethingElse()
END IF
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; variable was only expected one of two possible &lt;em&gt;atom&lt;/em&gt; values: &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;committed&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abort&lt;/code&gt;. Because of the typo, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doSomethingElse()&lt;/code&gt; was always executed, even if &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;doSomething()&lt;/code&gt; was meant to be executed instead.&lt;/p&gt;

&lt;p&gt;If you’re not familiar with Erlang’s &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;atom&lt;/code&gt; type, you can just think of them as a big global enum, and atoms are used in place of things like boolean types, magic number constants, and enum types as seen in other languages. For example, instead of the boolean type, we use the atoms &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;true&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;From the programmer’s perspective, atom literals can look somewhat like string literals. This makes them particularly susceptible to typos that only get tested during runtime.&lt;/p&gt;

&lt;p&gt;Though, using error-prone language constructs doesn’t have to be this painful. All those hours wasted debugging could’ve been solved using one simple technique: writing fast-failing code.&lt;/p&gt;

&lt;h2 id=&quot;the-fast-failing-solution&quot;&gt;The Fast-Failing Solution&lt;/h2&gt;

&lt;p&gt;What I should’ve done in my assignment is the following:&lt;/p&gt;

&lt;div class=&quot;language-erl highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;case&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;Foo&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;of&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;commited&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;doSomething&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;();&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;abort&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nf&quot;&gt;doSomethingElse&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;end&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the variable &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Foo&lt;/code&gt; is pattern-matched against the atoms &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;commited&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;abort&lt;/code&gt;. If the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt; statement fails to find a match, it raises an exception:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Eshell V9.3  (abort with ^G)
1&amp;gt; Foo = committed.
committed
2&amp;gt; case Foo of
2&amp;gt;     commited -&amp;gt;
2&amp;gt;         doSomething();
2&amp;gt;     abort -&amp;gt;
2&amp;gt;         doSomethingElse()
2&amp;gt; end.
** exception error: no case clause matching committed
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;With this version of the code, the error immediately makes itself known, and I would’ve fixed the typo and moved on with my life.&lt;/p&gt;

&lt;h2 id=&quot;another-fast-failing-example-in-python&quot;&gt;Another Fast-Failing Example In Python&lt;/h2&gt;

&lt;p&gt;Different languages work differently, so let’s have a look at a similar example in Python. Suppose we had a string that is expected to only be either &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;committed&quot;&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;&quot;abort&quot;&lt;/code&gt;. A fast-failing solution is the following:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;commited&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;abort&quot;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Here, the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; checks that if the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; block is entered, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;foo&lt;/code&gt; indeed does have the correct value. This would’ve caught the typo in much the same way as our Erlang solution:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; foo = &quot;committed&quot;
&amp;gt;&amp;gt;&amp;gt; if foo == &quot;commited&quot;:
...     do_something()
... else:
...     assert foo == &quot;abort&quot;
...     do_something_else()
...
Traceback (most recent call last):
  File &quot;&amp;lt;stdin&amp;gt;&quot;, line 4, in &amp;lt;module&amp;gt;
AssertionError
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;assert&lt;/code&gt; will not work with the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;-O&lt;/code&gt; flag, so if you absolutely have to raise an exception in production, it should be checked in an &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;elif&lt;/code&gt; block and an exception raised in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;else&lt;/code&gt; block:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;if&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;commited&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;elif&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;foo&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;==&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;abort&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;do_something_else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;()&lt;/span&gt;
&lt;span class=&quot;k&quot;&gt;else&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;raise&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;ValueError&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Unexpected value for foo.&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;taking-this-further&quot;&gt;Taking This Further&lt;/h2&gt;

&lt;p&gt;If you haven’t been using fast-failing code before, I hope I’ve convinced you to start using them now. However, fast-fail goes so much deeper than the scope of this post.&lt;/p&gt;

&lt;p&gt;For example, asserts are highly versatile in verifying the state of your program at specific points in the code while also usefully doubling as implicit documentation. The following example shows asserts being used to check function preconditions:&lt;/p&gt;

&lt;div class=&quot;language-python highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;def&lt;/span&gt; &lt;span class=&quot;nf&quot;&gt;frobnicate&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;x&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;):&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;x&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;&amp;lt;&lt;/span&gt; &lt;span class=&quot;mi&quot;&gt;10&lt;/span&gt;
    &lt;span class=&quot;k&quot;&gt;assert&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;isinstance&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;y&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;nb&quot;&gt;str&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;and&lt;/span&gt; &lt;span class=&quot;p&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;frob&quot;&lt;/span&gt; &lt;span class=&quot;ow&quot;&gt;in&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;&quot;y&quot;&lt;/span&gt;&lt;span class=&quot;p&quot;&gt;)&lt;/span&gt;
    &lt;span class=&quot;p&quot;&gt;...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Though, fast-fail is desirable in production, and asserts are usually not checked in production. There are many different practices for raising and handling errors, especially for critical applications such as aeronautics and distributed infrastructure. After all, you wouldn’t want your million-dollar aircraft exploding shortly after launch due to a missing semicolon, or your entire network of servers failing just because one server threw an error.&lt;/p&gt;

&lt;p&gt;And of course, I haven’t even touched the ultimate in fast-fail: compile-time errors (as opposed to runtime errors), and statically typed languages (as opposed to dynamically typed languages).&lt;/p&gt;

&lt;h2 id=&quot;appendix-other-comments&quot;&gt;Appendix: Other Comments&lt;/h2&gt;

&lt;p&gt;You can certainly still use the Erlang if-statement like so while still failing fast:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Eshell V9.3  (abort with ^G)
1&amp;gt; Foo = committed.
committed
2&amp;gt; if
2&amp;gt;     Foo =:= commited -&amp;gt;
2&amp;gt;         doSomething();
2&amp;gt;     Foo =:= abort -&amp;gt;
2&amp;gt;         doSomethingElse()
2&amp;gt; end.
** exception error: no true branch found when evaluating an if expression
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;However, I personally wouldn’t recommend it for this particular use-case (or even the majority of use-cases) since the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;case&lt;/code&gt; statement here is much clearer, concise, and less error-prone to write.&lt;/p&gt;

&lt;p&gt;It should of course also be noted that this is a quirk specific to Erlang. Python would just skip right over the if-statement:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; def f(x):
...     if x == &quot;commited&quot;:
...         print(&quot;bar&quot;)
...     elif x == &quot;aborted&quot;:
...         print(&quot;baz&quot;)
...     print(&quot;foo&quot;)
...
&amp;gt;&amp;gt;&amp;gt; f(&quot;commited&quot;)
bar
foo
&amp;gt;&amp;gt;&amp;gt; f(&quot;committed&quot;)
foo
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Be sure to learn the behaviour of your particular language when trying to write fail-fast code.&lt;/p&gt;

&lt;p&gt;Also, Python unfortunately lacks such a cases statement, though techniques such as the use of a dictionary may be used if it makes things clearer. The Python dictionary also usefully throws an error if no such key exists:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;gt;&amp;gt;&amp;gt; def f(x):
...     {
...         &quot;commited&quot;: lambda : print(&quot;bar&quot;),
...         &quot;abort&quot;:    lambda : print(&quot;baz&quot;)
...     }[x]()
...     print(&quot;foo&quot;)
...
&amp;gt;&amp;gt;&amp;gt; f(&quot;commited&quot;)
bar
foo
&amp;gt;&amp;gt;&amp;gt; f(&quot;committed&quot;)
Traceback (most recent call last):
  File &quot;&amp;lt;stdin&amp;gt;&quot;, line 1, in &amp;lt;module&amp;gt;
  File &quot;&amp;lt;stdin&amp;gt;&quot;, line 5, in f
KeyError: 'committed'
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;appendix-epic-fail-extra&quot;&gt;Appendix: Epic Fail Extra&lt;/h2&gt;

&lt;p&gt;I did mention that the way I went about debugging my assignment was its own epic fail, but it’s not particularly deserving of its own separate post so I’ll summarise it here in case it’s of interest to anyone. As a warning though, this explanation might be a bit abstract, and I really don’t blame you if you don’t get it. I’m writing this here for completeness.&lt;/p&gt;

&lt;p&gt;Each node in my simulated network potentially spawns a bunch of processes (which I will call “mini processes” for convenience) which it kills only if the network decides to return “abort”. If the network decides to return “committed” instead, the network doesn’t touch them.&lt;/p&gt;

&lt;p&gt;These mini processes in my test case receive messages from a controller process after the network makes its committed/abort response.&lt;/p&gt;

&lt;p&gt;However, I was finding that despite the network returning “committed”, the messages from the controller process didn’t seem to reach the mini-processes. Or perhaps more accurately, when I put print-statements in the mini-processes, expecting them to all print messages to the terminal, nothing was printed.&lt;/p&gt;

&lt;p&gt;Not knowing any better at the time, I focused intensely on why messages sent from one process may not reach a target process.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Maybe the process identifiers used to send the messages are actually subtly wrong, thus the messages are being sent to the wrong place?&lt;/li&gt;
  &lt;li&gt;Maybe the test case kills all processes too quickly, thus not allowing the mini processes to flush their write buffers?&lt;/li&gt;
  &lt;li&gt;Maybe it’s because the processes are far-relatives of each other?
    &lt;ul&gt;
      &lt;li&gt;Processes are created by a “parent process” spawning a “child process”.&lt;/li&gt;
      &lt;li&gt;I was considering that perhaps processes that are sufficiently far-relatives of each other might not be allowed to send messages.&lt;/li&gt;
      &lt;li&gt;On the other hand, perhaps closely related processes such as a parent and child, or two children of the same parent, may be sufficiently close enough to send messages to each other.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;I was also considering that maybe I just haven’t learnt enough about Erlang.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It took me far too long to realize that the bug as detailed in this blog post caused all nodes to instantly kill all mini-processes since the “abort” code was always executed. The mini-processes were always killed before they could receive the controller’s messages.&lt;/p&gt;

&lt;p&gt;Always challenge assumptions, kids.&lt;/p&gt;

</description>
        <pubDate>Fri, 04 May 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/05/04/01-epic-fail-5/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/05/04/01-epic-fail-5/</guid>
        
        
        <category>Tech</category>
        
        <category>Epic Fail</category>
        
        <category>Learning Diary</category>
        
      </item>
    
      <item>
        <title>Update #2: Why I Write, and Letting Go of Perfect</title>
        <description>&lt;p&gt;Lately, I’ve been starting to get back into writing content for this blog, and with that, my perspective on blogging has changed slightly. I’d like to discuss that briefly in this post.&lt;/p&gt;

&lt;h2 id=&quot;divorcing-myself-from-the-elusive-perfect&quot;&gt;Divorcing Myself from the Elusive Perfect&lt;/h2&gt;

&lt;p&gt;I created this blog to share my views and ideas on various things, all in one place. However, I previously felt like I wanted to achieve some minimum level of “quality”. I wanted this to be a place where if someone were to subscribe, I can give my personal guarantee that they will be reading top-quality, highly-relevant and super-interesting content each and every time I release a new post.&lt;/p&gt;

&lt;p&gt;However, wanting to have a high bar of quality I find gets in the way of getting any amount of content out. I’m finding that it leads to chronic procrastination with starting posts, and not to mention the amount of time I spend on any single post, focusing far too much on writing and editing.&lt;/p&gt;

&lt;p&gt;And even despite my best efforts to achieve my ideal, I still believe my blog is far from achieving it. Ultimately, all that procrastination and extra writing/editing time has only been wasted. My posts are terribly rambly, my grammar and organization of ideas are lacking greatly, I can get hand-wavy, etc.&lt;/p&gt;

&lt;p&gt;So even if I wanted to produce “quality”, I honestly don’t really know how to achieve that right now. I’m not a writer by trade, and I even practically failed highschool English. My grammar will need a huge amount of work, and since I don’t write much, I don’t really have a lot of experience structuring my thoughts and my communication. Sure, I’ve always read a tonne of articles on the internet, but I never really cared about learning how other people structure their writing until now; I just cared that I absorbed the ideas.&lt;/p&gt;

&lt;p&gt;As such, I’ve resolved to divorce my previous idea of “quality”. Rather than achieving that elusive “perfect”, “good enough for me” will be my goal. Of course, that’s never a valid excuse to never try to achieve some level of quality, but my focus will instead be on writing for the fun of it, writing what I want to write, and getting ideas out.&lt;/p&gt;

&lt;h2 id=&quot;improving-by-just-doing&quot;&gt;Improving by Just Doing&lt;/h2&gt;

&lt;p&gt;Quality should hopefully come naturally over time as I continue this blog.&lt;/p&gt;

&lt;p&gt;As I write, I’m constantly reassessing my grammar. If I’m unsure of something, I Google it. In fact, just a minute ago, I Googled &lt;em&gt;et cetera&lt;/em&gt; and how the abbreviation &lt;em&gt;etc.&lt;/em&gt; is used in writing. I’ve Googled grammar a lot with all my posts, and I hope that continuing to write and learning about grammar and writing this way will naturally lead to an accumulation of knowledge and improvement.&lt;/p&gt;

&lt;p&gt;My skill and instinct as a writer should hopefully also continue to improve as I get content out. By getting into the habit of writing, I want to practice identifying cool ideas I want to share with the world, developing habits that help me seek and retain key ideas, developing a better sense of how to structure my ideas in writing, and generally writing faster (rather than taking my time to agonize over how to write).&lt;/p&gt;

&lt;p&gt;Structuring my thoughts and building mental habits is also a skill that I want to improve in general. Being kinda a shut-in of a person at the moment, I hate to admit it but my communication skills in general just absolutely suck. Writing should help offset my problem, helping me to eventually integrate into becoming a productive member of society.&lt;/p&gt;

&lt;h2 id=&quot;why-i-write-and-looking-ahead&quot;&gt;Why I Write, and Looking Ahead&lt;/h2&gt;

&lt;p&gt;For now and hopefully continuing far into the future, I hope to keep using this blog as a “me-blog”. I write because I’m fed up of keeping my thoughts and ideas quietly to myself, and I just want to get them out in some fashion. &lt;strong&gt;Thoughts, ideas, and experiences are incredibly valuable yet ephemeral, so I want to capture them in the moment. Not putting them down on record is a damn waste of potential. Someone could’ve been inspired by them!&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Now, continually producing content in the way I described is cool and all, but I still want to produce resources one day that meet the “ideal perfect” that I described earlier. My plan is to maybe one day restructure my current blog to sectionalize it, or create new blogs which I might purposefully use for heavy-hitters, or more specific topics. But that’s something for another time.&lt;/p&gt;

&lt;h2 id=&quot;social-media&quot;&gt;Social Media…&lt;/h2&gt;

&lt;p&gt;To hopefully get my content a bit more visibility, I’ll be looking into using &lt;a href=&quot;https://twitter.com/simishadows&quot;&gt;Twitter&lt;/a&gt; and Reddit to link back to and promote my blog.&lt;/p&gt;

&lt;p&gt;I’m a bit of a nooblet when it comes to Twitter though, so let’s see how well this goes…&lt;/p&gt;

</description>
        <pubDate>Sat, 28 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/04/28/01-update-2/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/04/28/01-update-2/</guid>
        
        
        <category>Admin Updates</category>
        
      </item>
    
      <item>
        <title>Epic Fail #4: Poor data structure implementation</title>
        <description>&lt;p&gt;In my second year of university, I took a class that involved a series of AVR assembly language programming labs. One of them required an implementation of a &lt;em&gt;queue data structure&lt;/em&gt;. It was meant to be a simple lab, but an early design decision made it needlessly complicated. This additional complexity single-handedly turned debugging into a nightmare.&lt;/p&gt;

&lt;h2 id=&quot;my-epic-fail-queue-implementation&quot;&gt;My Epic Fail Queue Implementation&lt;/h2&gt;

&lt;p&gt;My implementation required that all elements be butted up to the front of the buffer. One pointer points to the back.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---+---+---+---+---+---+
| A | B | C |   |   |   |
+---+---+---+---+---+---+
          ^
          Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Enqueueing items would add to the back of the queue, and the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Back&lt;/code&gt; pointer is updated in the process:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---+---+---+---+---+---+
| A | B | C | D |   |   |
+---+---+---+---+---+---+
              ^
              Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dequeuing would require us to take from the front and shift the remaining elements forward to fill in the space:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;+---+---+---+---+---+---+
| B | C | D |   |   |   |
+---+---+---+---+---+---+
          ^
          Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Hopefully it should be obvious that this makes dequeuing so expensive to accomplish (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;O(n)&lt;/code&gt;) since you’d have to read and write across all the remaining elements in order to do the shifting.&lt;/p&gt;

&lt;p&gt;This mistake of choosing the wrong queue implementation bloated the code up by requiring an unnecessarily complex dequeue function to be implemented, and since the function didn’t work the first time around, it took at a nightmarish night of debugging.&lt;/p&gt;

&lt;p&gt;The program was failing in such weird ways, and there were so many other possible points of failure, with so many subsystems concurrently running and accessing data all at once. Remember, this is assembly language we’re talking about! If the dequeue function were simpler, I could’ve quickly “proved” that it works as expected, thus allowing me to focus on other places.&lt;/p&gt;

&lt;p&gt;In the end, the dequeue function was the problem.&lt;/p&gt;

&lt;p&gt;When I proudly presented the final working program to the lab demonstrator, while he was impressed that I got such a thing to work, he was shocked that I even attempted to implement such a thing in the first place. “You realize you could’ve implemented this with a circular buffer, right?”&lt;/p&gt;

&lt;h2 id=&quot;the-circular-buffer&quot;&gt;The Circular Buffer&lt;/h2&gt;

&lt;p&gt;In a circular buffer, your queue contents are continguously contained somewhere within the queue, not necessarily at the front or back. Two pointers point to the beginning and end.&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;          Front
          v
+---+---+---+---+---+---+
|   |   | A | B | C |   |
+---+---+---+---+---+---+
                  ^
               Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Dequeuing would simply grab whatever’s at the front and update the pointer:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;              Front
              v
+---+---+---+---+---+---+
|   |   |   | B | C |   |
+---+---+---+---+---+---+
                  ^
               Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And enqueing would simply add to the back and update the pointer:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;              Front
              v
+---+---+---+---+---+---+
|   |   |   | B | C | D |
+---+---+---+---+---+---+
                      ^
                   Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;If the end of the buffer is reached, we simply wrap to the end, using modular arithmetic to start reading from the beginning again:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;              Front
              v
+---+---+---+---+---+---+
| E |   |   | B | C | D |
+---+---+---+---+---+---+
  ^
  Back
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Simple and fast!&lt;/p&gt;

&lt;h2 id=&quot;the-takeaway&quot;&gt;The Takeaway&lt;/h2&gt;

&lt;p&gt;The really obvious takeaway here is to make sure you evaluate your data structures and implementations properly, otherwise you end up giving yourself so much pain later on.&lt;/p&gt;

&lt;p&gt;But for me personally, I think at the time, I was a bit too dangerously relaxed about the whole topic of data structures. At that point, I never experienced just how much worse poor design decisions can make everything.&lt;/p&gt;

&lt;p&gt;To me, this was a painful yet valuable lesson in ensuring the suitability of a design, and it highlights the importance of mastering and internalizing understanding of data structures and algorithms.&lt;/p&gt;

</description>
        <pubDate>Thu, 26 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/04/26/01-epic-fail-4/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/04/26/01-epic-fail-4/</guid>
        
        
        <category>Tech</category>
        
        <category>Epic Fail</category>
        
        <category>Learning Diary</category>
        
      </item>
    
      <item>
        <title>RSS: Syncing Inoreader and Newsboat via. GitHub</title>
        <description>&lt;p&gt;Web-based RSS readers are convenient for being a complete online service, but local RSS readers can offer their own advantages. So if you’re looking to get the best of both worlds, here’s my solution.&lt;/p&gt;

&lt;p&gt;I use &lt;a href=&quot;https://www.inoreader.com/&quot;&gt;Inoreader&lt;/a&gt; as my cloud-based RSS reader, and &lt;a href=&quot;https://github.com/newsboat/newsboat&quot;&gt;Newsboat&lt;/a&gt; as my local RSS reader.&lt;/p&gt;

&lt;p&gt;In summary, the whole thing works using three things:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Inoreader’s OPML subscription feature,&lt;/li&gt;
  &lt;li&gt;Newsboat’s OPML export feature (which I periodically run), and&lt;/li&gt;
  &lt;li&gt;Github to host OPML files.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, this scheme has a problem: I can’t structure my subscriptions! Newsboat only exports a single OPML file, and OPML doesn’t support tags (or similar constructs), so all that structure is lost when Inoreader reads the OPML file.&lt;/p&gt;

&lt;p&gt;To solve that problem, I also wrote a script to separate the original OPML file into separate OPML files (one for each tag).&lt;/p&gt;

&lt;p&gt;So how does everything work?&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Note: I assume basic familiarity with Inoreader, Newsboat, Git, GitHub, and automation/scripting.)&lt;/em&gt;&lt;/p&gt;

&lt;h2 id=&quot;the-opml-file-format&quot;&gt;The OPML file format&lt;/h2&gt;

&lt;p&gt;OPML is a file format that contains a list of web feeds. These are often used to export/import RSS subscriptions between different RSS readers.&lt;/p&gt;

&lt;p&gt;For example, if you’re using Feedly and you one day decide you want to switch to Inoreader, you can download all of your subscriptions from Feedly to your computer as an OPML file, then upload that file to Inoreader. Inoreader now has all your Feedly subscriptions.&lt;/p&gt;

&lt;p&gt;Here’s an example OPML file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;opml version=&quot;1.0&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;newsboat - Exported Feeds&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;http://simshadows.com/feed.xml&quot; htmlUrl=&quot;http://simshadows.com//&quot; title=&quot;Sim's Blog&quot;/&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;http://kuvshinov-ilya.tumblr.com/rss&quot; htmlUrl=&quot;http://kuvshinov-ilya.tumblr.com/&quot; title=&quot;Kuvshinov Ilya&quot;/&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;https://xkcd.com/rss.xml&quot; htmlUrl=&quot;https://xkcd.com/&quot; title=&quot;xkcd&quot;/&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;https://googleprojectzero.blogspot.com/feeds/posts/default&quot; htmlUrl=&quot;https://googleprojectzero.blogspot.com/&quot; title=&quot;Google Project Zero&quot;/&amp;gt;
  &amp;lt;/body&amp;gt;
&amp;lt;/opml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h2 id=&quot;newsboats-subscriptions-storage-and-opml-export&quot;&gt;Newsboat’s subscriptions storage and OPML export&lt;/h2&gt;

&lt;p&gt;Normally, your Newsboat subscriptions are stored in the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.newsboat/urls&lt;/code&gt; file. Mine can be found &lt;a href=&quot;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/.newsboat/urls&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To export everything into an OPML file, run the following command:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;newsboat -e &amp;gt; ~/subs.xml
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;My exported OPML file can be found at &lt;a href=&quot;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/autogenerated-opml/ORIGINAL.xml&quot;&gt;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/autogenerated-opml/ORIGINAL.xml&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;inoreaders-opml-subscription-feature&quot;&gt;Inoreader’s OPML subscription feature&lt;/h2&gt;

&lt;p&gt;When you add an OPML subscription to Inoreader, it periodically pings a URL containing an OPML file to monitor it for changes, which keeps your Inoreader subscriptions synchronized with it. This is literally the same basic principle in which RSS works!&lt;/p&gt;

&lt;p&gt;Here are my OPML subscriptions at the time of writing:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-04-25-01-img1-inoreader-opml-subs.png&quot; alt=&quot;My OPML subscriptions in Inoreader.&quot; height=&quot;100%&quot; width=&quot;100%&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Each OPML subscription in Inoreader is associated with a particular tag.&lt;/p&gt;

&lt;h2 id=&quot;hosting-the-opml-file-on-github&quot;&gt;Hosting the OPML file on Github&lt;/h2&gt;

&lt;p&gt;In order to use Inoreader’s OPML subscription on our Newsboat OPML export, we need a way to host the OPML file on the internet. This is where GitHub comes in.&lt;/p&gt;

&lt;p&gt;With Github, just &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; your file up to your public repository, and grab the URL to the &lt;em&gt;*RAW*&lt;/em&gt; file and subscribe to it with Inoreader. Every time you update, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt; again and Inoreader automatically updates your Inoreader subscriptions!&lt;/p&gt;

&lt;p&gt;You can find my raw OPML file at: &lt;a href=&quot;https://raw.githubusercontent.com/simshadows/sims-dotfiles/master/dotfiles/newsboat/autogenerated-opml/ORIGINAL.xml&quot;&gt;https://raw.githubusercontent.com/simshadows/sims-dotfiles/master/dotfiles/newsboat/autogenerated-opml/ORIGINAL.xml&lt;/a&gt;&lt;/p&gt;

&lt;h2 id=&quot;splitting-up-the-opml-file-by-tag&quot;&gt;Splitting up the OPML file by tag&lt;/h2&gt;

&lt;p&gt;As I mentioned before, you lose the tag structure from the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.newsboat/.urls&lt;/code&gt; file if you just use the raw OPML export from Newsboat, and I solved the problem with a script that separates the original OPML file into separate OPML files (one for each tag).&lt;/p&gt;

&lt;p&gt;All the script does is:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Parse the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/newsboat/.urls&lt;/code&gt; file for tags.&lt;/li&gt;
  &lt;li&gt;For each tag, make an exact copy of the original OPML file, except remove the lines containing subscriptions that don’t belong in the file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;For example, if we start with the following &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;~/.newsboat/urls&lt;/code&gt; file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;https://www.nasa.gov/rss/dyn/breaking_news.rss &quot;Science&quot;
http://www.folk-metal.nl/feed/ &quot;Music&quot;
https://myanimelist.net/rss/news.xml &quot;Weeb&quot;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;And we the following OPML file:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;opml version=&quot;1.0&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;newsboat - Exported Feeds&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;https://www.nasa.gov/rss/dyn/breaking_news.rss&quot; htmlUrl=&quot;http://www.nasa.gov/&quot; title=&quot;NASA Breaking News&quot;/&amp;gt;&amp;lt;/body&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;http://www.folk-metal.nl/feed/&quot; htmlUrl=&quot;http://www.folk-metal.nl&quot; title=&quot;Folk-metal.nl&quot;/&amp;gt; 
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;https://myanimelist.net/rss/news.xml&quot; htmlUrl=&quot;https://myanimelist.net/news?_location=rss&quot; title=&quot;News - MyAnimeList&quot;/&amp;gt;
&amp;lt;/opml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;To generate an OPML file for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Music&lt;/code&gt; tag, we simply copy over the original OPML file while deleting all unrelated entries, like so:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&amp;lt;?xml version=&quot;1.0&quot;?&amp;gt;
&amp;lt;opml version=&quot;1.0&quot;&amp;gt;
  &amp;lt;head&amp;gt;
    &amp;lt;title&amp;gt;newsboat - Exported Feeds&amp;lt;/title&amp;gt;
  &amp;lt;/head&amp;gt;
  &amp;lt;body&amp;gt;
    &amp;lt;outline type=&quot;rss&quot; xmlUrl=&quot;http://www.folk-metal.nl/feed/&quot; htmlUrl=&quot;http://www.folk-metal.nl&quot; title=&quot;Folk-metal.nl&quot;/&amp;gt; 
&amp;lt;/opml&amp;gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;It’s really that simple! Just subscribe to each separate OPML file on Inoreader.&lt;/p&gt;

&lt;p&gt;My implementation is technically actually split between two scripts:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/autogen.sh&quot;&gt;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/autogen.sh&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/split-opml-by-tags.py&quot;&gt;https://github.com/simshadows/sims-dotfiles/blob/master/dotfiles/newsboat/split-opml-by-tags.py&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;However, I wrote these scripts to fit my repository’s style (and the code’s not very robust), so I suggest you write your own.&lt;/p&gt;

&lt;p&gt;You can also find my OPML files for each tag here: &lt;a href=&quot;https://github.com/simshadows/sims-dotfiles/tree/master/dotfiles/newsboat/autogenerated-opml&quot;&gt;https://github.com/simshadows/sims-dotfiles/tree/master/dotfiles/newsboat/autogenerated-opml&lt;/a&gt;&lt;/p&gt;
</description>
        <pubDate>Wed, 25 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/04/25/01-rss-syncing-inoreader-and-newsboat/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/04/25/01-rss-syncing-inoreader-and-newsboat/</guid>
        
        <category>RSS</category>
        
        
        <category>Tech</category>
        
      </item>
    
      <item>
        <title>Eating Crisps with Chopsticks</title>
        <description>&lt;p&gt;Potato crisps (and similar snacks such as cheese twisties and corn chips, which I will refer to blanketly as crisps) are often greasy or otherwise messy to eat without utensils and other tools. Sure, you could just decide to not eat them while doing your term paper or playing videogames, or you could just suck it up and resign to the completely avoidable fate of getting your keyboard, mice, and books covered with food grease. Or, you could actually use a practical solution.&lt;/p&gt;

&lt;p&gt;Chopsticks are long and can reach deep into the bag. They’re nimble and have the ability to pick up large crisps, or bunches of various-sized crisps as needed. They make minimal surface contact with the food, but even if the ends get greasy with seasoning, simply run a single segment of toilet paper down the length of the chopsticks twice per stick (assuming you use smooth reusable chopsticks). Now, they’re clean enough to rest back down to be used again for the next bag.&lt;/p&gt;

&lt;p&gt;Chopsticks are of course not just limited to crisps and your more “traditional chopstick foods” such as ramen and dumplings. They’re great for anything else bite-sized: potato chips, chicken nuggets, Turkish pide, and sometimes even chicken wings (although those tend to be a lot more challenging to clean up around the bone), and many others are completely practical to eat with chopsticks.&lt;/p&gt;

&lt;p&gt;Other solutions certainly exist and can also be effective (usually depending on the nature of the snack). But for me, although it can look a bit silly, nothing beats the fine control, swiftness, and cleanliness of chopsticks.&lt;/p&gt;

</description>
        <pubDate>Sun, 08 Apr 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/04/08/01-eating-crisps-with-chopsticks/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/04/08/01-eating-crisps-with-chopsticks/</guid>
        
        
        <category>Lifestyle</category>
        
      </item>
    
      <item>
        <title>Epic Fail #3: Copy-Pasting Code With Unicode Quotes</title>
        <description>&lt;p&gt;For Web Application Security class last year, most of the final exam was an open-book, open-internet practical: we were given a remotely hosted web application to play with, and we had to obtain flags. No flag meant no mark.&lt;/p&gt;

&lt;p&gt;My prepwork involved making a PDF document using Latex containing all the written notes I needed. This was of course supplemented by other resources such as my archive of homework solutions, lecture slides, textbooks, etc. &lt;strong&gt;A key component of that Latex document of course was code that could be copy-pasted when needed.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The problem with that code, however, is that it’s not like a program you’re meant to compile and run locally, otherwise a compiler or interpreter would’ve caught the issue and issued the relevant warnings for the problem, allowing it to be resolved quickly. Instead, the code is often pasted directly into input text fields of a web page like so:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-03-27-01-img1-w4_img12.png&quot; alt=&quot;Code pasted into an input field on a web page on Chrome.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;Or, the significantly better method of using Burp Repeater and other such tools:&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;/images/posts/2018-03-27-01-img2-full.png&quot;&gt;&lt;img src=&quot;/images/posts/2018-03-27-01-img2-scaledown.png&quot; alt=&quot;Burp Suite Repeater example screenshot.&quot; /&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the above screenshot, the raw input data can be observed and modified here:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/images/posts/2018-03-27-01-img2-focused.png&quot; alt=&quot;Burp Suite Repeater example screenshot.&quot; /&gt;&lt;/p&gt;

&lt;p&gt;After sending off the input data to the remote server, feedback produced by the server may be limited and you may have to infer the web application’s state from minimal information. After all, web servers and applications are ideally designed to withstand attacks from the outside which look to coax the app/server into doing something to the attacker’s advantage. Intentionally hiding unnecessary information about the system is one of many tricks defenders use as part of the overall defense strategy.&lt;/p&gt;

&lt;p&gt;In reality, the amount of &lt;em&gt;relevant&lt;/em&gt; feedback emitted by the web server/application can vary significantly, depending on many aspects of the system. However, the fact still remains: A lot of the time, you’re swinging in the dark until you catch something. You may catch plenty, you may catch none, or you may even catch bait or misleading responses.&lt;/p&gt;

&lt;p&gt;In my case, despite having revised and practiced extensively before that final exam practical, I got zero flags. Even more painful was how I spent the two hours trying every trick and variation I knew, and feeling like I knew exactly what the solution should be for all flags that didn’t require knowledge of other flags, yet nothing did anything interesting. I kept thinking I missed some detail about the web application and continued to think along those lines.&lt;/p&gt;

&lt;p&gt;After the exam was over, I got a colleague to show me a flag. She got two of them instantly. (I think the application was taken down before we could try more flags.)&lt;/p&gt;

&lt;p&gt;That afternoon, I found my text document full of payload code I made during the exam. A lot of the quotation marks were found to be Unicode, as an artifact of my PDF document compiled from Latex. All my payloads were based off text copied from that PDF document. Although I can’t confirm, that was most likely the reason my payloads failed to make the web application budge one bit. If I just used ASCII quotation marks, I would’ve gotten at least a few flags.&lt;/p&gt;

&lt;h2 id=&quot;unicode-quotation-marks-what&quot;&gt;Unicode Quotation Marks? What?&lt;/h2&gt;

&lt;p&gt;By &lt;em&gt;Unicode quotation marks&lt;/em&gt;, I’m referring to the quotation marks that are not part of ASCII.&lt;/p&gt;

&lt;p&gt;The ASCII quotes &lt;em&gt;(including the grave mark)&lt;/em&gt; are:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Hex    Unicode   Raw   Description
----------------------------------------------------
0x22   U+0022    &quot;     QUOTATION MARK
0x27   U+0027    '     APOSTROPHE
0x60   U+0060    `     GRAVE ACCENT
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;The quotation characters above are the ones that are typically intended for the computer to parse with special meanings that are important in all aspects of a programmer’s work.&lt;/p&gt;

&lt;p&gt;The following is a subset of what I consider to be the “Unicode quotation marks”:&lt;/p&gt;

&lt;div class=&quot;language-plaintext highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;Unicode   Raw   Description
----------------------------------------------------
U+2018    ‘     LEFT SINGLE QUOTATION MARK
U+2019    ’     RIGHT SINGLE QUOTATION MARK
U+201C    “     LEFT DOUBLE QUOTATION MARK
U+201D    ”     RIGHT DOUBLE QUOTATION MARK
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;&lt;em&gt;(Note: Technically, ASCII is a strict subset of Unicode blocks, hence ASCII characters are also Unicode characters, but Unicode characters are not all ASCII characters.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;These “Unicode quotation marks” are intended to be more typographically accurate than ASCII quotes (which appear straight compared to the curliness of Unicode quotes). They are not typically meant to be interpreted by computers in place of Unicode quotes.&lt;/p&gt;

&lt;p&gt;In my case, the ASCII quotes I used in the Latex document were converted to Unicode quotes in the compiled PDF. Word processors (such as Microsoft Word) will often similarly convert quotes. Other applications (such as email) may also convert quotes. All of this is done to make the final document visually pleasing and typographically correct (much to the detriment of computing professionals out there).&lt;/p&gt;

&lt;p&gt;You &lt;em&gt;may&lt;/em&gt; have also noticed that this blog post’s quotation marks may have been converted into Unicode quotation marks (except in code blocks). Assuming I haven’t changed things too much since the time of writing, these blog posts are sourced from files written in Jekyll Markdown, and here, I use ASCII quotes.&lt;/p&gt;

&lt;p&gt;Further reading:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Raymond Chen (2009). Smart quotes: The hidden scourge of text meant for computer consumption. &lt;a href=&quot;https://blogs.msdn.microsoft.com/oldnewthing/20090225-00/?p=19033&quot;&gt;https://blogs.msdn.microsoft.com/oldnewthing/20090225-00/?p=19033&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;recommendations&quot;&gt;Recommendations&lt;/h2&gt;

&lt;p&gt;Even beyond things like rendered PDFs, Microsoft Word, and HTML web pages, you may run into the issue in simple plaintext files (such as if someone simply copy-pasted text in from Microsoft Word or a PDF, like during my web application security exam). Unicode quotes can come in from anywhere when you least expect it.&lt;/p&gt;

&lt;p&gt;This is one of those things where the best you can do is be aware and have it at the back of your mind, and hopefully this blog post has given you that awareness. Next time you run into a cryptic problem with seemingly no obvious reason, Unicode quotes may be worth considering.&lt;/p&gt;

&lt;h2 id=&quot;beyond-unicode-quotes&quot;&gt;Beyond Unicode Quotes&lt;/h2&gt;

&lt;p&gt;It really doesn’t take much to go beyond and find more problems related to using different characters that look visually similar (or the exact same). For instance, a popular example of this problem set is the &lt;a href=&quot;https://www.fileformat.info/info/unicode/char/037e/index.htm&quot;&gt;“GREEK QUESTION MARK” (U+037E)”&lt;/a&gt;. This character is visually similar to the semicolon character (&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;;&lt;/code&gt;), and is often used as an example of a prank that can be used on programmers (such as &lt;a href=&quot;https://stackoverflow.com/a/26965332&quot;&gt;this Stack Overflow post&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;In the context of security, the exploitation of such a mechanism is called a &lt;em&gt;homograph attack&lt;/em&gt;. IDN homograph attacks for instance can be used to trick users into believing they’re browsing &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;www.apple.com&lt;/code&gt; when in fact they are browsing &lt;a href=&quot;https://xn--80ak6aa92e.com/&quot;&gt;xn–80ak6aa92e.com&lt;/a&gt; (that link is not malicious at the time of writing, and was made to harmlessly illustrate the dangers of this IDN homograph vulnerabilities).&lt;/p&gt;

&lt;p&gt;Further Reading:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Xudong Zheng (2017). Phishing with Unicode Domains. &lt;a href=&quot;https://www.xudongz.com/blog/2017/idn-phishing/&quot;&gt;https://www.xudongz.com/blog/2017/idn-phishing/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;Jovi Umawing (2017). Out of character: Homograph attacks explained. &lt;a href=&quot;https://blog.malwarebytes.com/101/2017/10/out-of-character-homograph-attacks-explained/&quot;&gt;https://blog.malwarebytes.com/101/2017/10/out-of-character-homograph-attacks-explained/&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;em&gt;As for me, I took a supplementary exam for web application security class several weeks after the original exam. Needless to say, I made doubly sure I had properly formatted (with ASCII characters) code the second time around. My unicode quotes problem was no more.&lt;/em&gt;&lt;/p&gt;

</description>
        <pubDate>Tue, 27 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/03/27/01-epic-fail-3/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/03/27/01-epic-fail-3/</guid>
        
        
        <category>Tech</category>
        
        <category>Epic Fail</category>
        
        <category>Learning Diary</category>
        
      </item>
    
      <item>
        <title>VirtualBox Linux VM Development Environments</title>
        <description>&lt;p&gt;I’ve chosen to do the majority of my development work in a VirtualBox VM running an ultra-lightweight configuration of Arch Linux, with the VM typically running fullscreen or in a large window. All my files are in the virtual disk, I use a text editor inside the VM, and all of my tools are in there.&lt;/p&gt;

&lt;p&gt;It works beautifully for me, but for many, native development is suitable enough. Running natively has the distinct advantage of performance, tools for practically all popular needs exists on all major platforms, and you often won’t need to mess with the environment too much anyway once you’re established. Even the barrier to developing for Linux systems on Windows is largely lifted thanks to Vagrant, Docker, or possibly even WSL.&lt;/p&gt;

&lt;p&gt;And for some, native development will be the most sane option, particularly if hardware access is required as GPU access can be difficult and I/O may be poor. For instance:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Game developers often have heavy workloads that need the GPU, and games are often developed for Windows,&lt;/li&gt;
  &lt;li&gt;Machine learning and other scientific workloads often benefit greatly from GPU acceleration, and&lt;/li&gt;
  &lt;li&gt;I personally have trouble accessing any USB port from within any Linux VM. (This issue may be fixed though.)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;So if that’s you, you know who you are. There are solutions (such as &lt;a href=&quot;https://www.virtualbox.org/manual/ch09.html#pcipassthrough&quot;&gt;this&lt;/a&gt;), but I haven’t had a chance to play around with them yet.&lt;/p&gt;

&lt;p&gt;However, there are many interesting advantages that make a VirtualBox Linux VM well worth considering if it works for your workload.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note: I’ll be talking more on the pros and cons of the virtualization side of things rather than diving too specifically into my Linux setup.&lt;/strong&gt;&lt;/p&gt;

&lt;h2 id=&quot;advantages&quot;&gt;Advantages&lt;/h2&gt;

&lt;h3 id=&quot;advantage-0-virtualbox-and-linux-are-foss&quot;&gt;Advantage 0: VirtualBox and Linux are FOSS&lt;/h3&gt;

&lt;p&gt;Not really a point I’m arguing for (hence “Advantage 0”), but it’s most certainly a plus!&lt;/p&gt;

&lt;h3 id=&quot;advantage-1-its-literally-a-linux-system-that-just-bloody-works&quot;&gt;Advantage 1: It’s literally a Linux system that just bloody works.&lt;/h3&gt;

&lt;p&gt;For Windows users, I think this is the most important point. With a VirtualBox Linux VM, there is no need to wrestle with your native OS to get something working, and you dodge a lot of the weirdness and tech-acrobatics that can be required. Yes, it can work if you tried hard enough, but sometimes it’s nice to simply not have to go through that.&lt;/p&gt;

&lt;p&gt;On top of that, you’ll be working on &lt;em&gt;literally Linux&lt;/em&gt;. If you’re a Windows user taking computer science classes in college and your class requires you to program in C on a Unix-like system, this can save many headaches while at the same time familiarizing you with the same environment everyone else is using.&lt;/p&gt;

&lt;p&gt;Or if you, like me simply prefer working in Linux but for various reasons have to install Windows or Mac OS natively on your machine (such as to game on Windows or to reap other benefits Windows and Mac OS have over Linux), you can still feel right at home.&lt;/p&gt;

&lt;h3 id=&quot;advantage-2-portability&quot;&gt;Advantage 2: Portability&lt;/h3&gt;

&lt;p&gt;Not only does the VM work, but it generally works wherever the latest version of VirtualBox is supported.&lt;/p&gt;

&lt;p&gt;This is particularly awesome if you have multiple machines and you want to work on all of them. In my case, I have a Windows-based gaming desktop machine and a Macbook Pro, and I simply copy the VM files between them as necessary. (I only bother copying the VM after major system changes thanks to &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt;.)&lt;/p&gt;

&lt;p&gt;Everything moves, so the result is that &lt;strong&gt;it works and looks practically exactly the same, everything from your text editors to your tools, your files, and your perfectly arranged directory structure. Everything works exactly how you like it.&lt;/strong&gt; No need to somehow match certain settings between your computers, no need to resolve mismatched compatibility. And with the massive amount of customizability and choice in Linux-land, all those tweaks you made? Yep. They all stay with your VM.&lt;/p&gt;

&lt;p&gt;Reformatting and reinstalling your host OS is also made simpler since you don’t have to bother as much about your development environment; just reinstall VirtualBox and copy your VM back in. I’ve had to do that to resolve sluggish performance on my Mac.&lt;/p&gt;

&lt;h3 id=&quot;advantage-3-virtualbox-snapshots&quot;&gt;Advantage 3: VirtualBox Snapshots&lt;/h3&gt;

&lt;p&gt;The state of your entire machine can be versioned so you can go back to a different point at any time.&lt;/p&gt;

&lt;p&gt;To me, this has two broad but important implications.&lt;/p&gt;

&lt;p&gt;First, it allows you to recover faster from a broken system. However, this assumes that you create snapshots regularly. In my case, I generally make snapshots between major system changes, after successful whole-system updates, or major &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;/home&lt;/code&gt; directory structure changes. Since I use &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git&lt;/code&gt; and put repositories on GitHub quite liberally, I don’t really bother too much if I lose changes within repositories after being &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;git push&lt;/code&gt;ed.&lt;/p&gt;

&lt;p&gt;Second, snapshots enables experimentation, which I think is important for users learning how to use Linux (such as myself!). Snapshots can even be taken while the machine is running, so simply taking snapshots at key points will allow you to try new things, observe the effect, and easily recover if you end up breaking your system.&lt;/p&gt;

&lt;p&gt;Snapshots do take host disk space though, so I only keep two snapshots into the past (deleting old ones), and I don’t “fork”.&lt;/p&gt;

&lt;h3 id=&quot;advantage-4-isolation&quot;&gt;Advantage 4: Isolation&lt;/h3&gt;

&lt;p&gt;This can be a huge boon if you like tinkering and exploring, in case you mess something up or if you accidentally run malware or get hacked. Everything that happens inside the VM stays in the VM. If the VM crashes, it probably won’t mess up your host OS.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Do remember though that this isolation is not perfect. It does however make things increasingly difficult for attackers.)&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(Also, your VM may not be guarded against consuming your computer’s resources, so your computer may freeze if you hit it too hard. That should be obvious, but I’d like to mention that for clarity.)&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;advantage-5-a-virtualbox-vm-encourages-experimentation&quot;&gt;Advantage 5: A VirtualBox VM Encourages Experimentation&lt;/h3&gt;

&lt;p&gt;I’ve already touched on this in my discussion of snapshots, but all of these points so far are great for experimentation. I don’t think I need to explain any further.&lt;/p&gt;

&lt;h3 id=&quot;advantage-6-linux-is-awesome&quot;&gt;Advantage 6: Linux is Awesome&lt;/h3&gt;

&lt;p&gt;Depending on who you ask, the fact that you’re running Linux can be a huge advantage or disadvantage.&lt;/p&gt;

&lt;p&gt;In my case, I absolutely love using Linux, so I’ll list it as an advantage. (I’ll probably write more on this in the future, so I’ll leave it at that for now.)&lt;/p&gt;

&lt;h2 id=&quot;disadvantages&quot;&gt;Disadvantages&lt;/h2&gt;

&lt;p&gt;Such awesomeness unfortunately comes with a few major downsides that can make or break the entire experience.&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-1-hardware-access-difficulty-especially-gpu-and-usb&quot;&gt;Disadvantage 1: Hardware Access Difficulty (especially GPU and USB)&lt;/h3&gt;

&lt;p&gt;I’ve already mentioned this earlier: while the system works excellently from within, I’ve had major difficulties getting the VM to interface and work with USB (VirtualBox USB passthrough has been unusably unstable for me), and I suspect GPU isn’t so smooth sailing either with VirtualBox.&lt;/p&gt;

&lt;p&gt;However, there are probably better solutions out there (or maybe VirtualBox’s USB drivers are fixed). I haven’t really looked into it so if you find something, I’d love it if you could &lt;a href=&quot;mailto:contact@simshadows.com?Subject=I%20found%20cool%20virtualization%20software%20you%20should%20try!&quot;&gt;let me know&lt;/a&gt;!&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-2-performance&quot;&gt;Disadvantage 2: Performance&lt;/h3&gt;

&lt;p&gt;It should be obvious that VMs come with performance penalties. Your VM will be eating up a portion of your CPU, memory, and potentially your entire graphics card.&lt;/p&gt;

&lt;p&gt;However, I find my experience to be pleasantly smooth (no noticeable performance penalties) with the following settings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;2048-4096 MB RAM assigned to the VM,&lt;/li&gt;
  &lt;li&gt;Allow the VM to use as many cores as there are cores on your computer and with no execution cap,&lt;/li&gt;
  &lt;li&gt;256 MB Video RAM assigned to the VM, and&lt;/li&gt;
  &lt;li&gt;Enabled 3D and 2D acceleration on the VM.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These settings work perfectly on my late-2013 Macbook Pro with 8GB of RAM (and it even supports me using both a Linux VM and a Windows 7 VM concurrently!), but it may not work on your machine, especially if your VMs aren’t configured to be as lightweight as mine. As such, &lt;strong&gt;your mileage may vary.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;If you want ballpark numbers though, my (untested) advice is to have a minimum of 8GB of RAM in your computer in order to be comfortable using a VM. Otherwise, any decent 2-core laptop manufactured after 2012 will probably serve you fine.&lt;/p&gt;

&lt;p&gt;(Or, you could just test performance on your machine anyway since VirtualBox and Linux are free :)&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-3-the-vm-requires-extra-disk-space&quot;&gt;Disadvantage 3: The VM requires extra disk space&lt;/h3&gt;

&lt;p&gt;My Linux VM takes 34.86 GB at the time of writing, but it can be much smaller. Within the Linux VM, I’m only using 20.9 GB.&lt;/p&gt;

&lt;p&gt;That consumed space is barely felt in my 256 GB Macbook though, and I suspect that might be the same with many others users.&lt;/p&gt;

&lt;p&gt;As for the additional 14.0 GB of virtual disk bloat, I suspect it comes from several places:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Having to install the operating system,&lt;/li&gt;
  &lt;li&gt;Having to install a lot of standard tools that may already exist in the host, and&lt;/li&gt;
  &lt;li&gt;The virtual disk file is probably not filesystem-aware, so deleting files may not actually shrink the virtual disk file.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;There is a way to lessen the impact of point #3 by “compacting” the filesystem and zeroing unallocated blocks, but that can be a hassle. I don’t even bother anymore.&lt;/p&gt;

&lt;p&gt;(For reference: My Windows 7 VM takes 51.28 GB, and it’s basically a fresh install!)&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-4-your-entire-vm-is-accessible&quot;&gt;Disadvantage 4: Your entire VM is accessible&lt;/h3&gt;

&lt;p&gt;Generally, sensitive data is protected by preventing users’ direct access. I’m not just talking about your business documents and various embarrassing selfies; the software itself and various cryptographic secrets can be stolen or tampered. Having a full VM sitting on disk on your host OS and accessible through your user (as opposed to needing administrator/root access) opens you up to a variety of potential attacks. For instance:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Malware may scan your files and steal RSA private keys from your unprotected VM,&lt;/li&gt;
  &lt;li&gt;Malware may install rootkits in the VM that can be hidden from detection, and&lt;/li&gt;
  &lt;li&gt;If someone steals your VM, they’ve practically stolen your computer!&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A possible solution is to &lt;a href=&quot;https://blogs.oracle.com/scoter/virtualbox-50-enhancements-and-features:-disk-image-encryption&quot;&gt;enable virtual disk encryption&lt;/a&gt;. This should make it exceptionally more difficult to “smash-and-grab” from the disk, though it’s not perfect since keyloggers and other techniques can still be used to circumvent it.&lt;/p&gt;

&lt;p&gt;In practice, it &lt;em&gt;may&lt;/em&gt; not matter too much as long as you have good security practices; if your user is compromised, it’s probably just a matter of time before they gain deeper access to your machine. However, it pays to be a bit paranoid.&lt;/p&gt;

&lt;p&gt;&lt;em&gt;(I’d also like to clarify: You probably use disk encryption with your host OS, but that can only help against physical theft of your computer (and even then, &lt;a href=&quot;https://www.youtube.com/watch?v=pKeiKYA03eE&quot;&gt;it’s not necessarily perfect&lt;/a&gt;). You will still need to encrypt your virtual disk in order to mitigate those attacks I mentioned above.)&lt;/em&gt;&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-5-its-practically-another-system-to-maintain&quot;&gt;Disadvantage 5: It’s practically another system to maintain&lt;/h3&gt;

&lt;p&gt;Unfortunately, having a VM also means another system for you to maintain. However, that may not actually be that bad. This is a great way to learn Linux!&lt;/p&gt;

&lt;h3 id=&quot;disadvantage-6-if-it-aint-broke-dont-fix-it&quot;&gt;Disadvantage 6: If it ain’t broke, don’t fix it.&lt;/h3&gt;

&lt;p&gt;Perhaps everything is working perfectly fine for you developing in your native OS, so it can be difficult to see why you should move to a VM.&lt;/p&gt;

&lt;p&gt;However, maybe consider trying out a VM anyway. Trying new tools in general is a great way to learn new things and improve your workflow!&lt;/p&gt;

&lt;h2 id=&quot;final-thoughts&quot;&gt;Final Thoughts&lt;/h2&gt;

&lt;p&gt;Hopefully I’ve provoked some ideas on the possibilities with virtualization. However, you may still be wondering: Why Linux?&lt;/p&gt;

&lt;p&gt;After all, the entire GNU/Linux ecosystem is the other major part to consider if you want a VirtualBox &lt;strong&gt;Linux&lt;/strong&gt; VM.&lt;/p&gt;

&lt;p&gt;I’ll leave that for another post.&lt;/p&gt;

</description>
        <pubDate>Fri, 23 Mar 2018 00:00:00 +0000</pubDate>
        <link>https://www.simshadows.com/2018/03/23/01-virtualbox-linux-vm-dev-envs/</link>
        <guid isPermaLink="true">https://www.simshadows.com/2018/03/23/01-virtualbox-linux-vm-dev-envs/</guid>
        
        
        <category>Tech</category>
        
        <category>Learning Diary</category>
        
      </item>
    
  </channel>
</rss>
