Keep Ruby Weird 2015

A Collection of Fun with Ruby and Friends

A Collection of Fun with Ruby and Friends

by Will Leinweber

In the video titled "A Collection of Fun with Ruby and Friends," Will Leinweber presents at the Keep Ruby Weird 2015 event. The main theme revolves around playful and practical programming experiences with Ruby and Git, illustrating how personal projects can lead to creative solutions in coding. Key points discussed throughout the video include:

  • Introduction to Bundler: Will shares his experiences with Bundler, humorously revealing the confusion it creates when working with different Ruby versions. He created a gem called 'bundle' which simplifies the Bundler installation process.

  • G Vain Project: He introduces his project 'G Vain,' which allows users to add a vanity prefix to their git commits. Will compares himself to a crow in a parable about vanity, explaining how he used git's structure to achieve this.

  • Technical Details of SHA Manipulation: Will describes the mechanics behind git commit structures and details his strategy for obtaining desired SHA prefixes through timestamp manipulations, aiming to minimally disrupt commit order.

  • Optimization Techniques: He discusses optimizations, such as rewriting the project in C to improve performance and using profiling tools to analyze processing time, culminating in significant performance improvements.

  • Personal Anecdotes: Throughout the presentation, he shares anecdotes, like a humorous encounter while attempting to create fictitious commits for his GitHub profile, showcasing his quirky coding style.

  • Reflections on Commit Practices: Will reflects on the purpose and perception of unconventional commit practices, shifting from a vanity prefix to a more descriptive one over time.

  • Nostalgic Web Project: He discusses a web project that recreates older web aesthetics with contemporary functionalities, blending nostalgia with usability.

  • Ruby Method for Mischief: Concluding with a humorous note, he describes a mischievous Ruby method that can confuse collaborators, promoting the unpredictable side of coding.

Overall, the presentation enhances understanding of Ruby programming through light-hearted examples and emphasizes creativity in coding while acknowledging the balance between personal style and collaboration.

00:00:11.360 Thank you very much. It's a great honor to be here. I especially want to thank all the organizers who have done a great job so far. One of the organizers you may know is Terren. I work with Terren at Heroku, and he has spent a lot of time working on Bundler, which I use a lot. How many of you use Bundler?
00:00:22.199 You know when you use Bundler, it's always 'bundle this,' 'bundle that,' 'bundle install,' 'bundle update.' Every time I go to a new version of Ruby or a new environment, I could never get it into my head that I had to do 'gem install bundler' instead of just 'bundle.' That really drove me nuts.
00:00:40.200 So, I created a gem called 'bundle.' All it does is, when you install it, it calls Bundler for you. This was a couple of years ago, and it seems that a lot of other people have had this problem too. If you look at the code for it, you'll see it’s pretty simple – it's just a gem specification. While it may not be the best gem in the world, it probably has the most downloads per line of code.
00:01:02.079 I want to start off with that and move on to a little bit more serious topic. I have a project I wrote almost two years ago called 'G Vain.' The picture I included in the README is from a story about the vain crow, which you might not be familiar with. It's similar to a parable or something akin to Aesop. In the story, a crow, dissatisfied with his friends, sees some peacocks and decides he wants to hang out with them because they seem so phenomenal.
00:01:41.320 He tries to join the peacocks, but they don’t pay much attention to him. After they leave, he finds some of their feathers on the ground. The crow sticks them onto his tail and goes to his girlfriend, saying, "Hey, I don’t need you anymore. Look at me, I'm an awesome peacock!" The peacocks then see him and think, "Wow, this is a really ugly peacock; we should be nice to him." But soon, the feathers fall off, revealing his true self, and the peacocks tell him to get lost. That's the end of the story.
00:02:01.840 What I wrote, 'G Vain,' allows you to have your git commits begin with a vanity prefix of your choosing. I guess I'm the crow in this story. To understand how 'G Vain' works, you need to first understand how a git commit is structured. Essentially, you have a tree pointing to the SHA of the actual code change, a parent commit, and if it's a merge commit, it will contain two or three parent SHAs, depending on the type of merge it was.
00:02:44.000 You also have your author and committer information along with two new lines for your commit message. For example, I was adding Crystal support to Travis CI and wanted to plug Crystal a little. If you enjoy Ruby and you want a compiled language that is statically typed, fast, and self-hosted, Crystal is amazing. If you want to hear more about it, come talk to me afterward. However, I'm not going to turn this into a Crystal talk.
00:03:21.120 The SHA of your commit can be derived from taking the commit file and converting it to the SHA. In this case, my commit is a real one, and you can see that I started with the prefix 'Cafe.' If you want to brute force through commits, you'll need to focus on the areas where you can change parts of the commit. You can't change the tree or parent; you also don't want to change your name or email address. The only places you can change are the commit message and the timestamps of when the commit occurred.
00:04:01.840 When I was building this, I didn't want to annoy my co-workers more than I already do, so I didn't want to append anything to the end of my commit messages; that would clutter every single one of my commits. Instead, I decided to manipulate the timestamps. You can either move the timestamp forward or backward second by second, and you have two timestamps to play with.
00:04:43.320 The first version I wrote during a long plane ride home; it was somewhat functional but had one major issue. If you naively loop through with an incremented second and a decremented second on the author date, you might hit a valid collision for your commit hash to start with 'Cafe,' but one of your dates may end up way off by several hours.
00:05:09.600 My goal was to minimally disrupt the natural order of commits while achieving my desired SHA. To do this, I implemented a strategy to spiral out from my last solution to efficiently find that 'green dot' – the valid commit that starts with my desired prefix. I spent significant time figuring out how to spiral out and eventually found a helpful solution online.
00:05:54.720 In terms of optimization, I typically optimize my code only to a point where it’s fast enough. This project, however, started as intentionally irresponsible. The first step I took was rewriting it in C so that I could utilize real threads. One thing you can do with SHAs is pre-compute certain values and share that context with the different iterations of the loop, which sped everything up by about 50%. For instance, I was able to reduce 52 million collision checks from 89 seconds down to 59 simply by saving the context to the first timestamp.
00:06:45.440 Another surprising finding was that by using profiling tools, I noticed that when a thread found a solution, it would set a global flag so that all other threads could check it. However, I discovered that this check for the global boolean was consuming most of the processing time. By optimizing the lock check to happen only before actually performing any logic changes to the commit, I could still allow other threads to work without getting in each other's way, which resulted in an additional 20% performance increase.
00:07:27.440 I won’t go into much detail about this next part, but I wanted to share something cool about using C. I identified that using 'sprintf' was quite slow for my operations; thus, I initially tried 'i2a,' which converts integers to character arrays, but it was also slow. Consequently, I wrote this code by implementing 'div mod' directly. I learned a lot from this process because I was leveraging great tools offered by the Crystal programming language.
00:08:04.000 If you have a Mac, you can use Instruments on OS X, which is really beneficial for performance analysis. On Linux, 'perf' is okay, but Instruments offers a unique feature – you can click record, run your program, and then hit pause to view the performance data. You can break it down to see which instruction takes the most resources, which is extremely insightful.
00:08:40.360 Additionally, I've been using 'G Vain' for almost two years now on every commit I’ve made. Each time I commit, I adjust the hash so that my commits start with my preferred prefix, 'Cafe.' This has proven to be incredibly helpful. By simply glancing at commits, my co-workers can tell which ones are mine without even looking at the author information. It adds a nice layer of recognition.
00:09:24.720 One of the eye-opening moments was discovering that within the Git repository, shorter SHAs had inherent collision possibilities. That’s a bit unnerving, though I'm glad the system will generate additional hashes to avoid confusion. The expressive nature of my commits has enabled me to convey more information. For example, I recently shut down a project I initially loved, but that had turned painful over time. As I shut it down, I tagged the commits with ‘dead’ to reflect the closure.
00:10:03.600 In one of my main projects, I noticed we were approaching commit 1337. I couldn’t resist the urge to find a collision for that number. The search took about 10 to 20 minutes, during which I converted all comments in the source code to leetspeak. However, the team ultimately didn't merge the code changes due to some concerns regarding readability.
00:10:52.560 In this situation, I decided to automate an issue check. Every minute, a script verifies if our project reaches 1336 and, if so, automatically creates a new issue. Given the timing of this task with multiple urgent fixes being implemented, it was quite lucky and probably brought a touch of humor during a stressful patching period.
00:11:44.440 However, my journey hasn’t always been pleasant. I faced some criticism regarding the unconventionality of my commits and the apparent chaos they created. One creator of Crystal playfully hinted at my commit style, which was eventually acknowledged. After about 50 commits, I switched the prefix from ‘Cafe’ to ‘Code’ as this felt more descriptive of my contributions.
00:12:32.240 Switching topics, I want to discuss GitHub's commit graph feature. Initially, I was apprehensive about it because I didn't want my contributions tracked publicly to influence my work behavior. Therefore, I created a fun project where I simulated fictitious commits to produce a graphical representation on my GitHub profile.
00:13:06.640 So, I devised a way to engineer commits from varying timeframes and filled my GitHub with hundreds of thousands of faux commits. My profile ended up with a visually appealing display that seemed to showcase real productivity as it went through an animated marquee of activity.
00:13:45.320 Looking into more profound reflections—I think discussions around achieving zero-downtime deployments come and go with trends. While it might be essential for specific sites, I wonder if all the engineering effort dedicated to achieving zero-downtime could sometimes be better spent improving product functionality overall.
00:14:10.160 Redirecting blame for site errors often makes its way into these discussions. For example, implementing a webpage that states 'Your computer can't connect to the internet' diverts blame away from the website and toward the user's setup, which is a clever way to manage user experience while preserving website reputation.
00:15:04.560 I wanted to share a quick anecdote from lunch one day. A co-worker informed me that the demo site for one of my projects was malfunctioning. Ironically, I was preparing to present at an event, and my demo site was the one referenced. It turned out that it truly wasn’t working—his explanation was spot on.
00:15:30.720 The implementation to achieve this was rather simple. I explored different browsers, utilized the inspector tool to pull out relevant HTML, and encoded necessary assets like images in base64. This way, I ensured that the site would function even offline.
00:15:50.080 Another precaution involved adjusting my MIDI files that, due to some OS restrictions, I had to transcode for compatibility, but they still sounded remarkably similar. I even managed to get the title of my page to marquee across the top of the browser, but that had to be derived manually due to how modern browsers handle titles.
00:16:29.760 In recapping my website project, I made it intentionally reflective of older web designs. I forever felt like I was out of style; each time I updated my page, it would fall back behind. Hence, I built it with nostalgia at its core. It required lots of trial and error to make certain inclusions functional, such as the scrolling marquee text, especially given different browser behaviors.
00:17:29.560 The marquee script became my pride, allowing users to witness a version of what older web experiences might have resembled without the cringy elements typically associated with retro designs. Overall, the project had no real moral to it, but an inferred lesson could be to be bold in creating things independently. Embrace your inventive side.
00:18:55.520 To perform a nostalgic callback, I made certain to revive the use of frames but ensured that deep-linking was functional. I diligently crafted a solution whereby URLs would change when users engaged with the site, maintaining the nostalgia while introducing modern usability features.
00:20:54.320 Lastly, I want to conclude with a mischievous coding method I developed in Ruby. This method serves as a callback hook that allows you to undefine methods when they are created. Introducing this in a collaborator’s code can cause confusion during testing phases as dependencies start to fall apart unpredictably. The result is often a frantic search for the source of errors that, paradoxically, seem fine when isolated. My intent here is surely humorous; the repercussions of such a method could be quite severe, so this is definitely a tongue-in-cheek approach. Thank you very much!