tag:marianposaceanu.com,2005:/feedblog of Marian Posăceanu - rubyist most of the time2023-11-05T17:16:02Ztag:marianposaceanu.com,2005:Article/412023-11-05T17:16:02Z2023-11-05T17:40:29ZHarmonizing Projects: Navigating the Graph of Estimation and Detail<p>As someone who finds solace in the rich nuances of sound, I often draw parallels to the world of development. Ponder this: Just as the quality of music affects the depths of my appreciation, the broad overview of a project offers a satisfying clarity. Yet, the devil, as they say, is in the details.</p>
<p>In much the same way I lose myself in the symphonies of sound, developers often journey through the intricate web of a project, visualized as a vast graph. At the heart of this graph lies the core objective or goal, the resonating note that sets the tone. As we journey outwards, moving towards the peripheries, the graph branches out, much like the intricate harmonies and melodies in a musical piece.</p>
<p>And then, there are the leaf nodes, the finer details. Just as the subtlest notes in music might escape the casual listener, these granular elements of a project often elude our initial estimations. The further we delve into these leaves, the more we're confronted with the unexpected — the unforeseen challenges, the complexities that weren't apparent from a distance. It's akin to the ambient noise that permeates through my open-back headphones, often distracting and always unpredictable.</p>
<p>In the past months, I've found myself gravitating towards noise-cancelling headphones, a testament to the need for focused immersion. Similarly, as developers, our approach to project estimation needs that metaphorical noise-cancellation. Recognizing the uncertainties that lurk in the granular tasks, adjusting our approach, and continuously recalibrating our strategies becomes paramount. After all, in both music and development, it's about harmonizing the broad strokes with the intricate details, creating a masterpiece that resonates with purpose.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/402023-11-05T17:16:02Z2023-11-05T17:16:02ZDon’t stress, use the right gear for the job<p>Whilst I consider myself an audiophile, I also like to think I’m a pragmatist i.e. best of both worlds: don’t go over the top with snake oil gear but at the same time recognise that sound quality plays a pivotal role on how I listen and enjoy music.</p>
<p>As developers, we use various ways to relax, in my case music plays a vital role - it decouples me from the “now”, triggers the creation of happy chems in the brain and finally re-syncs my contorted perception towards “beauty can exist in the world whatever the circumstances might be”.</p>
<p>In the last couple of months, a new requirement has risen: noise cancelling headphones, as the surrounding noise was having a negative effect on my productivity. I mostly use open back headphones, actually all of them are open back so they let outside noise easily in.</p>
<p>I addressed the finding of the perfect pair of noise cancelling headphones by also factoring in their sound quality. After some weeks a candidate emerged: Sony WH-1000XM4, the fourth iteration of their NC cans - the reviews and online consensus revealed top of the notch NC and more than OK sound quality.</p>
<p>To digress a bit, my reference cans are the old timers from Sennheiser: the venerable HD600s released in 1997 with their odd coating. People affectionately call them “kitchen”-cans. Luckily, I got the original looking ones from ‘97. The updated design looks in-sync with the modern times. Before them I tried other headphones: I went from Grados (SR225e) to Audeze (LCD-2f), which I still own but rarely use, also listened to a myriad of other models. </p>
<p>For me, the 600s timber, especially in the vocals department, doesn’t have any competition. They’re just magic if you will, just like the classic BBC monitors, nowadays best incarnated as the Harbeth P3ESR - they’re not perfect speakers by any means, but their timbre and reproduction of vocals are just magic.</p>
<p>Back to the Sony’s - bought them, the NC feature worked like a charm but I had a major disappointment in the sound quality department - out of the box they come tuned with a huge bass bump which bleeds into the mids and makes everything sound… well, muddy. </p>
<p>I spent again a week researching different EQ settings, various fixes to make them sound better. Finally, I used <a target="_blank" href="https://rogueamoeba.com/soundsource/">SoundSource <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> coupled with Apple’s default AUNBandEQ (parametric EQ) to apply fixes I’ve found <a target="_blank" href="https://www.reddit.com/r/oratory1990/comments/kek3sn/sony_wh1000xm4_eq_preset_check/">online <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. The results - quite impressive, the sound was much better, but it wasn’t perfect, most likely because there are many factors that influence each individual frequency perception like the shape of the ear, the length of the ear canal, the inherent subjectivity of the brain, etc. </p>
<p>This was a failed experiment. I truly believe you can EQ your headphones to fit your ears; the issue is the amount of energy you have to put into this and there’s always seemed to be that one track where a cymbal just sounds off or too edgy.</p>
<p>Therefore, I caved. I just set the “Vocal” profile in their DSP, which doesn’t sound horrible, and went on with my business, ignoring the issue for some time but still having a feeling that they aren’t good enough somehow.</p>
<p>Then it downed on me: I got them for a specific role - noise cancellation i.e. not to trick my brain that I’m listening to magic. When thinking in that specific structure, the dissent went away, because when I wanted magic, I could always switch to my 600s coupled with the Chord Mojo or the Burson Soloist brute and a <a target="_blank" href="https://ifi-audio.com/products/micro-itube2/">tube buffer <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, all mixed with a quiet night: just sit back and enjoy the music. </p>
<p>As in programming and many other fields: use the right gear for the job and appreciate things for what they excel at.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/392023-11-05T17:16:02Z2023-11-05T17:16:02ZHierarchy of perceptions<p>I was thinking of the old conundrum of how we perceive the objective world or reality - it’s always through our limited sensory organs. Then is has to be processed: some small latency in the brain, maybe some evolutionary heuristics, our genetic background, etc. after all this we get a tainted fragment the world.</p>
<p>We know these facts: we aren’t getting a full picture, i.e., our perception is limited. We can have levels of perception which depend on various factors, some of which are internal (currently researched and refined in the fields of psychology & neuroscience) and others external. As a species, we have cultivated them, I’d reckon, starting with the first human tribes.</p>
<p>Society is both a necessity and a natural extension of the late humans. The interesting detail is society's effects on our perceptions or reality. I keep using perception at plural because I’m making the case there’s a multiplicity of them (maybe I’m channelling Deleuze here). What I want to add on top of the plurality of perception is its hierarchical property in relation to the immovable real world.</p>
<p>Why do I believe we can switch the perception of the world? Is self-evident, but this property forces it to move under our radars. We box ourselves into a certain instance of reality through a specific perception. </p>
<p>Let’s say, age wise, we are in our thirties and our carrier takes center stage - this becomes the instance of how we perceive the world. Thus, our prima perception is bound to this context and the other instances take a second place. Other instances? we can think of items that ooze meaning in our lives, e.g. our loved ones, passions, hobbies, etc.</p>
<p>This creates a hierarchy of perceptions which, if we’re not aware of it, we can designate as the most important the “wrong” instance of reality. These hierarchies are subjective, but to what degree? What if we get stuck in a perception bubble and we forget or ignore our health? - in the future we might experience the perception of being ill to a higher degree and, sadly, get stuck in it longer or for the rest of our life.</p>
<p>We can sketch this out at a macro and micro-level. The hierarchy of perceptions guides our choices to a certain extent in different periods of our lives (macro). But at any point there’s a multiplicity of perceptions of the same position of reality which unified unto infinity would give us a full picture.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/382023-11-05T17:16:02Z2023-11-05T17:16:02ZTips: macOS save screenshots as JPEG in a different location<p>I'm not really sure why taking screenshots in macOS defaults to PNG file format. I just googled this and the "answer" was:</p>
<blockquote>
<p>MacOS captures screenshots using PNG as the default image format, which provides lossless compression and preserves image quality while creating relatively small files.</p>
</blockquote>
<p>OK - I can understand somewhat the logic behind this - "we're a premium brand, even the screenshots should be premium, jokes aside, whilst I agree with the part about the format being lossless I'm surely (and don't call me Shirley!) that the part about small files is non-sense. </p>
<p>PNGs, especially when using the "Retina"-mode HiDPI, create large file as the format default compression engine is DEFLATE which is OK but the problem is not the algorithm itself, the issue is that is has to deal with a large set of data (lossless compression i.e. not one pixel can be lost). When using a 4K display in 1080p mode - that translates to really big files (usually a couple of megs). </p>
<p>Why is this an issue for me? I keep all my screenshots and sync them in iCloud. It be rather useful to have them - assign dates to images over large periods of time and you can reconstruct a bit of the past e.g. "What was I doing that day? Oh, I was making a meme about moths". </p>
<p>But I digress, I always forget how the command to change the default image format to jpeg and as far as I know still there's is no global UI way to set it - therefore here goes, the <em>magic</em> commands:</p>
<pre class='highlight'>defaults write com.apple.screencapture type jpg
killall SystemUIServer
</pre>
<p>The first line is easy to decipher as for the second one the only question is what SystemUIServer is - well, according to its man page:</p>
<pre class='highlight'>SystemUIServer(8) System Manager's Manual SystemUIServer(8)
NAME
SystemUIServer – Presents status items in the upper right of menu bar
DESCRIPTION
SystemUIServer is a system service which presents status items in your menu
bar.
There are no options for SystemUIServer, and users should not run
SystemUIServer manually.
macOS July 4, 2018 macOS
</pre>
<p>The cherry on the top? How to set the location of your newly saved JPEG screenshots: </p>
<p><code>Command + Shift + 5</code> => there's an UI at the bottom where you can click "Options" and select the new folder where the screenshots will be saved.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/372023-11-05T17:16:02Z2023-11-05T17:16:02ZInteresting links - Is logging a "code smell" ?<p>I was reading this <a target="_blank" href="https://dave.autonoma.ca/blog/2022/01/08/logging-code-smell/">article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> it raises quite an unexpected question - "Can we consider logging as a code smell"?</p>
<p>Clearly - the answer is more nuanced than that and whilst I do enjoy the <code>event bus</code> approach from the article - that seems like overkill for most applications.</p>
<p>It's interesting that Aspect Oriented Programming is mentioned but not in a positive light and I resonate with that to a certain extent - especially in Java but in Ruby world this is quite easy to implement - actually no one even calls AOP (most likely because is not in the pure definition of it) it's just neat <em>little</em> feature of <code>ActiveSupport</code> : more precisely <code>ActiveSupport::Notifications</code>.</p>
<p>To me that's quite similar to the implementation in the original article - it just comes as under the "instrumentation API for Ruby" moniker.</p>
<p>A simple example would look like:</p>
<pre class='highlight ruby'><span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Notifications</span><span class="p">.</span><span class="nf">instrument</span><span class="p">(</span><span class="s1">'some_action_that_requires_instrumentation'</span><span class="p">)</span> <span class="k">do</span>
<span class="n">run_the_action</span>
<span class="k">end</span>
</pre>
<p>In some other part of our logic - preferably in config file we can subscribe to those events:</p>
<pre class='highlight ruby'><span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Notifications</span><span class="p">.</span><span class="nf">monotonic_subscribe</span><span class="p">(</span><span class="s1">'render'</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="nb">name</span><span class="p">,</span> <span class="n">start</span><span class="p">,</span> <span class="n">finish</span><span class="p">,</span> <span class="nb">id</span><span class="p">,</span> <span class="n">payload</span><span class="o">|</span>
<span class="c1"># According to the docs we get a handy set of meta information:</span>
<span class="c1">#</span>
<span class="c1"># name => String, name of the event (such as 'render' from above)</span>
<span class="c1"># start => Monotonic time, when the instrumented block started execution</span>
<span class="c1"># finish => Monotonic time, when the instrumented block ended execution</span>
<span class="c1"># id => String, unique ID for the instrumenter that fired the event</span>
<span class="c1"># payload => Hash, the payload</span>
<span class="c1"># here we could implement our logging and instrumentation (Librato & friends)</span>
<span class="k">end</span>
</pre>
<h4>Credits</h4>
<ul>
<li><a target="_blank" href="https://dave.autonoma.ca/blog/2022/01/08/logging-code-smell">Original article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://api.rubyonrails.org/classes/ActiveSupport/Notifications.html">ActiveSupport docs <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/362023-11-05T17:16:02Z2023-11-05T17:16:02ZMultiple data stores and eventual consistency using micro-services<p>There are cases where there isn't a single source of truth when it comes to the data that a fleet of micro-services consume. The data is thus sparse across multiple storage solutions, each designed to solve a specific problem using a sub-sets of it. This can be either mirrored via syncing to a specific format (think for example of a graph database) or a set of specific features that exist only in another store (think of a relational database with some custom metadata) all derived from an "M:N" data store (this can be anything from a relational database, a document one or even a set of resources exposed as an API, all mixed together).</p>
<p>The question in this case is how to achieve eventual data consistency across all the data stores keeping in mind that the single source of truth is physically sparse across multiple data stores and third party APIs each with their own set of shortcomings. Moreover let's assume that consolidating them into one data store is not an option - in this specific case a strategy within a set of constraints is required in order to achieve an adequate level of consistency which can guarantee the correct resolution of end-user specific use-cases.</p>
<p>First it becomes clear that the criteria for each data store consistency needs to be properly defined - how fresh must the data be? does the access requires bi-directional access? read and writes or it's just a form of read-replica within a specific type of data store to optimally solve a problem e.g. moving the relations between users into a graph database in order to easily make connections between them and generate insights that can then be easily consumed through a micro-service by various clients (mobile, web apps, etc.)</p>
<p>The simplest case is read-only mode without any or minimal metadata, also it's important if the metadata is encapsulated or it leaks into other micro-services business logic. If we're talking about the former then defining the rules for how fresh the data is dictated by its consumers.</p>
<p>The next one is when we have to deal with bi-directional consistency i.e. a client updates something in our data store and we need to sync that back with all the sparse single source of truth data stores. Now, this becomes quite problematic, because we have a dependency tree with side-effects leaking on each leaf. Existing criteria dictated by the consumers will thus require syncing the data to lowest acceptable interval, otherwise we will break the consistency contract we have with our clients. This becomes quite complex with metadata that it's shared between multiple micro-services.</p>
<p>What about metadata? this is now a full fledged cross cutting concern that becomes dissonant with itself as it needs to be synced in multiple places and via different protocols (think about having similar metadata in a graph db. and a relational one). Optimally the metadata, since it's cross cutting across multiple micro-services it should reside in one data store but let's say this is not an option. </p>
<p>This quickly transforms into an aching architectural issue - the solution resides not in a shared data store but within a shared mechanism of keeping track of these changes. One solution could emerge in the form of queues with ack/retry capability backed by persistence (something à la RabbitMQ, Kafka, etc.). It is now self-evident that this adds another complication: how do we deal with persistent events in the queues that are now inconsistent due to how much time they resided (a simple example would be a set of unacked events that after some time "T" become invalid as the record/object they have a reference to doesn't exist anymore) as a result: this will require another mechanism to drop those event from the queues or add another high level abstraction leak as the clients will have to deal with the issues of out of date data.</p>
<p>Eventual consistency in a complex system of sparse single source of truth data store with an added complication of cross cutting metadata within a fleet of micro-services is quite an interesting problem to solve - it its most basic form we deal with a graph of (inter)dependencies that should govern the orchestration of both the micro-services and the syncing of the various data stores.</p>
<p>Finally the solution would be emergent of the graph of (inter)dependencies in the form of an attached mechanism which abstracts away the sparse single source of truth into just one that stays within the confines of its consumers, thus delivering the expected business value on all fronts. </p>
<h4>More information:</h4>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Eventual_consistency">Eventual consistency <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Single_source_of_truth">Single source of truth <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/342023-11-05T17:16:02Z2023-11-05T17:16:02ZThe perils of writing request specs using concurrent-ruby under the JVM<p>When I write an API, though I'm not a hard core TDD practitioner, I do like writing specs - especially requests specs that test the whole stack. </p>
<p>Adding them into an API is fast and yields quite good results compared to an app with an UI where you have to use chrome-cli or phantomjs just to get near of that level but at the cost of painfully slow execution time (yes, even if you optimise them to hell and back and get a runtime of five minutes - they're still slow in my book).</p>
<p>Anyhow, for some context - I've been writing Ruby APIs for quite some time but using the classic CRuby VM/interpreter - this time we switched to JRuby (thanks to <a target="_blank" href="https://andreimaxim.ro">Max <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>) since we needed to render extremely quick JSON responses (i.e. 202 status codes) - so everything from ActiveRecord CRUD operations to processing business logic is done using <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby">concurrent-ruby <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> with <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/blob/master/doc/future.md">Futures <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/blob/master/doc/thread_pools.md">ThreadPools <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> (which in JRuby they use <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/executor/thread_pool_executor.rb#L10:L15">Java's native implementation <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - awesome stuff since one can play with <a target="_blank" href="https://en.wikipedia.org/wiki/Software_transactional_memory">STM <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and all that good stuff - if required).</p>
<p>Next stop: the core of the issue: running request specs with all this parallelism in the background breaks most of our specs because RSpec is not aware of anything which runs in parallel and the inherent non-deterministic nature of running code in parallel.</p>
<p>The initial fix for this was to add a helper that basically forces a shutdown of the ThreadPool which will block until it's done - this "ensured" that all the parallel tasks (like creating a record) would finish before we got to the expect part in the specs. All nice and rosy except it did not work as expected.</p>
<p>This was the initial implementation btw. :</p>
<pre class='highlight ruby'><span class="k">def</span> <span class="nf">wait_for_thread_pool!</span><span class="p">(</span><span class="n">sleep_time</span> <span class="o">=</span> <span class="kp">nil</span><span class="p">)</span>
<span class="n">thread_pool_executor</span> <span class="o">=</span> <span class="n">executor</span><span class="p">.</span><span class="nf">instance</span>
<span class="n">pool</span> <span class="o">=</span> <span class="n">thread_pool_executor</span><span class="p">.</span><span class="nf">executor</span>
<span class="c1"># shutdown the pool and wait as long as it takes</span>
<span class="n">pool</span><span class="p">.</span><span class="nf">shutdown</span>
<span class="n">pool</span><span class="p">.</span><span class="nf">wait_for_termination</span>
<span class="c1"># we want a fresh thread pool for the next test</span>
<span class="n">thread_pool_executor</span><span class="p">.</span><span class="nf">send</span><span class="p">(</span><span class="ss">:initialize</span><span class="p">)</span>
<span class="k">end</span>
</pre>
<p>This is quite self-explanatory - it issues a ThreadPool shutdown which waits for all the threads to finish their work - the problem? In 10% of the cases using RSpec random spec execution it failed.</p>
<p>For the time being - the next best fix was to monkey patch the library (well, to be more precise our adapter for it) in order to run everything sequentially - especially keeping in mind that concurrent-ruby is an externally tested library and the issue should be an odd interaction between RSpec, <a target="_blank" href="https://github.com/DatabaseCleaner/database_cleaner">DatabaseCleaner <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and concurrent-ruby. </p>
<p>In any case until I can start digging into all those dependencies and see what the actual issue was this fixed the issue:</p>
<pre class='highlight ruby'><span class="c1"># run everything sequantial for now</span>
<span class="k">def</span> <span class="nf">disable_parallelism!</span><span class="p">(</span><span class="ss">context: </span><span class="kp">nil</span><span class="p">)</span>
<span class="k">case</span> <span class="n">context</span>
<span class="k">when</span> <span class="ss">:context_a</span>
<span class="n">future</span><span class="p">.</span><span class="nf">instance_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">execute</span><span class="p">(</span><span class="ss">executor: </span><span class="kp">nil</span><span class="p">,</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="n">block</span><span class="p">.</span><span class="nf">call</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">when</span> <span class="ss">:context_b</span>
<span class="n">future</span><span class="p">.</span><span class="nf">class_eval</span> <span class="k">do</span>
<span class="k">def</span> <span class="nf">add_observer</span><span class="p">(</span><span class="n">observer</span><span class="p">)</span>
<span class="vi">@observer</span> <span class="o">=</span> <span class="n">observer</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">initialize</span><span class="p">(</span><span class="n">opts</span> <span class="o">=</span> <span class="p">{},</span> <span class="o">&</span><span class="n">block</span><span class="p">)</span>
<span class="vi">@block_to_call</span> <span class="o">=</span> <span class="n">block</span>
<span class="k">end</span>
<span class="k">def</span> <span class="nf">execute</span>
<span class="n">proc_response</span> <span class="o">=</span> <span class="vi">@block_to_call</span><span class="p">.</span><span class="nf">call</span>
<span class="vi">@observer</span><span class="p">.</span><span class="nf">update</span><span class="p">(</span><span class="n">time</span><span class="p">.</span><span class="nf">now</span><span class="p">,</span> <span class="n">proc_response</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>I usually avoid monkey patching stuff like this - but then again this is also where monkey patching can give you some breathing time and keep you sane whilst the long process of debugging why:</p>
<pre class='highlight ruby'><span class="n">pool</span><span class="p">.</span><span class="nf">shutdown</span>
<span class="n">pool</span><span class="p">.</span><span class="nf">wait_for_termination</span>
</pre>
<p>it's not doing its job properly can continue as an async (pun intended) task. </p>
<p><strong>NB</strong>: please read the Updates section below on how this was fixed - to completely avoid the monkey-patching we can use:</p>
<pre class='highlight ruby'><span class="k">def</span> <span class="nf">disable_parallelism!</span>
<span class="no">CustomExecutor</span><span class="p">.</span><span class="nf">instance</span><span class="p">.</span><span class="nf">executor</span> <span class="o">=</span> <span class="no">Concurrent</span><span class="o">::</span><span class="no">ImmediateExecutor</span><span class="p">.</span><span class="nf">new</span>
<span class="k">end</span>
</pre>
<p>Regarding specs/coverage - the next step is to improve code-coverage in the unit-tests realm as to be sure all the small parts are working correctly.</p>
<h4>Conclusion</h4>
<p>JRuby + concurrent-ruby is a boon - there are some drawbacks as pointed above and many more which I'll detail in future posts but it really pays off when you really need quick responses. En plus, concurrent-ruby literally levels up JRuby to a place where it can compete with Elixir, well Erlang's concurrency model (yes it has <a target="_blank" href="http://ruby-concurrency.github.io/concurrent-ruby/Concurrent/Actor.html">Actors <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> but they're in the edge branch for now). Its abstractions are top notch and they remove a lot of pain from dealing with Threads with some minor caveats.</p>
<h4>Updates</h4>
<p>After the <code>r/ruby</code> <a target="_blank" href="https://www.reddit.com/r/ruby/comments/6w6hr0/the_perils_of_writing_request_specs_using/">discussion <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> some updates are required:</p>
<p>A fellow redditor - <code>i_know_sherman</code> suggested concurrent-ruby's <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/blob/master/lib/concurrent/executor/immediate_executor.rb">ImmediateExecutor <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> which is a special executor that basically runs everything sequentially:</p>
<blockquote>
<p>An executor service which runs all operations on the current thread, blocking as necessary. Operations are performed in the order they are received and no two operations can be performed simultaneously.</p>
</blockquote>
<p>A small caveat here: it works correctly except when using Futures with the option <code>dup_on_deref</code> set to <code>true</code>.</p>
<p>Another suggestion from <code>moomaka</code> - this time for keeping parallelism on:</p>
<blockquote>
<p>Problem may be that sometimes the tasks in the queue needs to queue other tasks on the same executor and those tasks are being rejected. May be able to fix this by setting the :fallback_policy of the executor to :caller_runs which will then run the rejected tasks immediately in the caller thread allowing everything to complete.</p>
</blockquote>
<p>This feature was implemented in concurrent-ruby by <code>jrochkind</code> <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/issues/192">here <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> i.e. <a target="_blank" href="https://github.com/ruby-concurrency/concurrent-ruby/commit/8bea918f0d949c3a13d74864efaa3c53c3cbc6ad">Improve behaviour when posting to a shutdown thread pool <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/332023-11-05T17:16:02Z2023-11-05T17:16:02ZJRuby, RVM and Vim walk into a (performance) bar<p>I'm not sure why RVM is still my default Ruby version manager yet the issue at hand should be reproducible on rbenv too. </p>
<p>Let's add a bit of context to this: we have an API written in Ruby and running on JRuby i.e. via JVM which implies slow start-up times compared to CRuby (yes, even with <code>export JRUBY_OPTS='--dev'</code>). I use Vim 8.0.502 which of course comes by default bundled with Tim Pope's <a target="_blank" href="https://github.com/vim-ruby/vim-ruby">vim-ruby <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>.</p>
<p>The problem: since I've switched to JRuby I started to notice a slowdown whilst working in Vim with .rb files. I did not pay too much attention to it at first (read almost for a month) but today it really started to bug me. I had no idea what was causing the slowdown so I tried Vim's trusty command-line option:</p>
<pre class='highlight'>vim --startuptime profile-data app/controllers/application_controller.rb
</pre>
<p>which yielded (edited for brevity):</p>
<pre class='highlight'>104.316 002.877 002.877: sourcing /usr/local/share/vim/vim80/syntax/ruby.vim
1228.691 1123.486 1123.486: sourcing /usr/local/share/vim/vim80/ftplugin/ruby.vim
1229.935 000.686 000.686: sourcing /usr/local/share/vim/vim80/indent/ruby.vim
{ edited }
1273.618 043.838: opening buffers
1274.471 000.853: BufEnter autocommands
1274.475 000.004: editing files in windows
1274.924 000.449: VimEnter autocommands
1274.932 000.008: before starting main loop
1299.500 024.568: first screen update
1299.501 000.001: --- VIM STARTED ---
</pre>
<p>Over one second to open a simple Ruby file? auch!</p>
<p>The relevant line in that file is:</p>
<pre class='highlight'>1228.691 1123.486 1123.486: sourcing /usr/local/share/vim/vim80/ftplugin/ruby.vim
</pre>
<p>Why are we spending one second in <code>ruby.vim</code> ? the answer is in <a target="_blank" href="https://github.com/vim-ruby/vim-ruby/blob/master/ftplugin/ruby.vim#L70:L80">this function <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> which gets executed before opening a .rb file:</p>
<pre class='highlight'>function! s:query_path(root) abort
let code = "print $:.join %q{,}"
if &shell =~# 'sh' && empty(&shellxquote)
let prefix = 'env PATH='.shellescape($PATH).' '
else
let prefix = ''
endif
if &shellxquote == "'"
let path_check = prefix.'ruby --disable-gems -e "' . code . '"'
else
let path_check = prefix."ruby --disable-gems -e '" . code . "'"
endif
</pre>
<p>Note: <code>ftplugin</code> stands for filetype and not FTP - so yes, this logic is required. </p>
<p>After all of this I did one more test: using <code>top</code> in another tmux window I could actually see the Java process running after Vim therefore the issue was trivial: <code>vim-ruby</code> was using JRuby.</p>
<p>The logical next step: instruct Vim to use CRuby if RVM with JRuby is detected. After <a target="_blank" href="https://github.com/vim-ruby/vim-ruby/issues/33#issuecomment-1004831">some <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> <a target="_blank" href="https://plus.google.com/114112334290393746697/posts/foWqKczaGff">googling <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> around the solution was an appendix to <code>.vimrc</code>:</p>
<pre class='highlight'>if !empty(matchstr($MY_RUBY_HOME, 'jruby'))
let g:ruby_path = '/usr/bin/ruby'
endif
</pre>
<p>Basically if RVM has set-up JRuby already instruct <code>vim-ruby</code> via its helpful <code>ruby_path</code> config to use the system's default Ruby (on macOS that being - CRuby version 2.0.0p648)</p>
<p>Results after the fix:</p>
<pre class='highlight'>104.643 002.876 002.876: sourcing /usr/local/share/vim/vim80/syntax/ruby.vim
106.938 001.369 001.369: sourcing /usr/local/share/vim/vim80/ftplugin/ruby.vim
108.062 000.622 000.622: sourcing /usr/local/share/vim/vim80/indent/ruby.vim
{ edited }
152.700 044.957: opening buffers
153.389 000.689: BufEnter autocommands
153.394 000.005: editing files in windows
154.086 000.692: VimEnter autocommands
154.092 000.006: before starting main loop
178.172 024.080: first screen update
178.174 000.002: --- VIM STARTED ---
</pre>
<p>~200ms => much better.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/352023-11-05T17:16:02Z2023-11-05T17:16:02ZKeep your Rails logs free of unwanted noise<p>I like to use <a target="_blank" href="http://rollbar.com">Rollbar <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>'s default plan for small apps or prototypes that are wip. Getting production exceptions in my inbox can be quite useful but most of them are actually 404s - sure there are a multitude of ways for filtering out the noise (<a target="_blank" href="https://www.digitalocean.com/community/tutorials/how-to-protect-an-nginx-server-with-fail2ban-on-ubuntu-14-04">Fail2Ban <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, hand written IPTables <a target="_blank" href="https://www.linode.com/docs/security/firewalls/control-network-traffic-with-iptables">rules <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, etc.)</p>
<p>The main idea here is to filter as much of the Rails's logs noise with simple enough changes — security is a completely different topic (though some of the tools do touch on that realm too).</p>
<h4>nginx</h4>
<p>First thing I've observed was that my app was getting scanned via the IP and not the domain name — so first the fix comes as a configuration change in nginx to enable responses only via the app's host:</p>
<pre class='highlight'>server {
listen 80;
server_name {the-ip-address};
return 404;
}
</pre>
<p>I'm not really sure whether I should use 404 or 403 — Not Found sounds correct since one should not access the app via its IP but Forbidden is somewhat equally suitable — the resource is here but you cannot access it via the server's IP.</p>
<p>This single configuration change reduced the logging noise by about 200 daily faux-requests — which is quite nice.</p>
<h4>Rack::Attack</h4>
<p>Next stop: automatic scans for WordPress vulnerabilities — lots and lots of requests for <code>wp-admin</code> and <code>wp-login</code> — just ghastly. </p>
<p>How can we fix this? We get down on the application level i.e. Rack.</p>
<p>The idea is simple: put a Rack middleware in front of the chain that can just drop all those pesky WP scans: <a target="_blank" href="https://github.com/kickstarter/rack-attack">Rack::Attack <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
<p>Installation is simple: add the gem to your Gemfile, create a config file like <code>/config/initialisers/rack_attact.rb</code> and add:</p>
<pre class='highlight ruby'><span class="c1"># After 1 blocked requests in 10 minutes, block all requests from that IP for 1 day.</span>
<span class="no">Rack</span><span class="o">::</span><span class="no">Attack</span><span class="p">.</span><span class="nf">blocklist</span><span class="p">(</span><span class="s1">'fail2ban pentesters'</span><span class="p">)</span> <span class="k">do</span> <span class="o">|</span><span class="n">req</span><span class="o">|</span>
<span class="c1"># `filter` returns truthy value if request fails, or if it's from a previously banned IP so the request is blocked</span>
<span class="no">Rack</span><span class="o">::</span><span class="no">Attack</span><span class="o">::</span><span class="no">Fail2Ban</span><span class="p">.</span><span class="nf">filter</span><span class="p">(</span>
<span class="s2">"pentesters-</span><span class="si">#{</span><span class="n">req</span><span class="p">.</span><span class="nf">ip</span><span class="si">}</span><span class="s2">"</span><span class="p">,</span>
<span class="ss">maxretry: </span><span class="mi">1</span><span class="p">,</span>
<span class="ss">findtime: </span><span class="mi">10</span><span class="p">.</span><span class="nf">minutes</span><span class="p">,</span>
<span class="ss">bantime: </span><span class="mi">1</span><span class="p">.</span><span class="nf">day</span>
<span class="p">)</span> <span class="k">do</span>
<span class="c1"># The count for the IP is incremented if the return value is truthy</span>
<span class="n">req</span><span class="p">.</span><span class="nf">path</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="s1">'wp-admin'</span><span class="p">)</span> <span class="o">||</span>
<span class="n">req</span><span class="p">.</span><span class="nf">path</span><span class="p">.</span><span class="nf">include?</span><span class="p">(</span><span class="s1">'wp-login'</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>Any requests to <code>/{wp-admin | wp-login}</code> will translate into an instant one-day ban for that IP. Clearly you could do this using Fail2Ban but <code>Rack::Attack</code> comes with other <a target="_blank" href="https://github.com/kickstarter/rack-attack#usage">niceties too <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and it ticks the <em>simple</em> checkbox whilst being more portable than Fail2Ban.</p>
<p>The final step is to actually use this middleware by prepending it in config.ru:</p>
<pre class='highlight ruby'><span class="nb">require</span> <span class="o">::</span><span class="no">File</span><span class="p">.</span><span class="nf">expand_path</span><span class="p">(</span><span class="s1">'../config/environment'</span><span class="p">,</span> <span class="kp">__FILE__</span><span class="p">)</span>
<span class="n">use</span> <span class="no">Rack</span><span class="o">::</span><span class="no">Attack</span>
<span class="n">run</span> <span class="no">YourApp</span><span class="o">::</span><span class="no">Application</span>
</pre>
<p>Why in config.ru and not in the config files of Rails? Mostly because of semantics — it's not related to the business logic of the app and it makes it explicit that's the first Rack middleware a request going through nginx will hit.</p>
<p>After all of this is set-up — a simple request to '/wp-admin' will result in a 403 with the Forbidden message and a one-day ban.</p>
<h4>Conclusion</h4>
<p>before: <strong>220 to 240</strong> - 404 exceptions/day<br>
after: <strong>10 or fewer</strong> - 404 exceptions/day</p>
<p>and this without completely turning off 404 exceptions.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/322023-11-05T17:16:02Z2023-11-05T17:16:02ZHow to reduce the size of your VMs (macOS Update)<p><br>
Lately I'm also running macOS virtualized for testing various apps. After some heavy usage the same problem popped up: the .vmdk uses way too much space on my quite small 256GB SSD. Currently is at around 70GB.</p>
<p>The process is similar to what I did on Windows and Linux i.e. write a null file that is erased at the end then use the command-line tools to compact the .vmdk and reclaim space (the example is specific for VMWare Fusion).</p>
<p>Without further ado: </p>
<h4>Step one</h4>
<p>Fill up all the empty space with 0x00</p>
<pre class='highlight'>$ cat /dev/zero > zeroed_empy_space; rm zeroed_empy_space
</pre>
<p>In case you're wondering what <code>/dev/zero</code> does:</p>
<blockquote>
<p><code>/dev/zero</code> is a special file in Unix-like operating systems that provides as many null characters (ASCII NUL, 0x00) as are read from it. One of the typical uses is to provide a character stream for initializing data storage.</p>
</blockquote>
<h4>Step two</h4>
<p>VMWare Fusion is installed by default in <code>/Applications/VMware Fusion.app</code> so you just have to run:</p>
<pre class='highlight'>$ cd ‘/Applications/VMware Fusion.app/Contents/Library/‘
$ vmware-vdiskmanager -k your_vm_name.vmdk
</pre>
<p>and wait until it finishes - please note that you need at least the .vmdk file size free space on disk or this operation will fail.</p>
<h3>Results</h3>
<p>Original vmdk size: 70GB<br>
After zeroing free space and clean-up: 40GB</p>
<h4>Credits:</h4>
<ul>
<li><a target="_blank" href="https://communities.vmware.com/thread/455978?start=0&tstart=0">vmware support #1 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=1003897">vmware support #2 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/312023-11-05T17:16:02Z2023-11-05T17:16:02ZProgramming archaeology: PHP's dollar sigil<p>I started out with Java as my professional language and before I discovered Ruby, PHP was my main programming language of choice for new projects. This was probably six to seven years ago or more. I had some pretty good times with CodeIgniter [0] and various libraries like HHMVC [1]. </p>
<p>In any case, I digress - even back then the most striking feature of its syntax was the dollar sign prepended to variables which made me think the aesthetics of the language were sub-par or at least annoying. Clearly it did not stop me for writing lots of apps in PHP since it was more of a small annoyance, if you will, something debatable mostly for scholastic purposes.</p>
<p>Recently the question popped into my mind: "What's the history of the dollar sign? and why is there." - so like every good question I started to Google my way into some answers:</p>
<p>First influence - Perl:</p>
<blockquote>
<p>Because PHP was based on Perl which used $, though the symbols Perl used were meaningful and plenty used to indicate the data type, ( such as @ used to indicate an array ) PHP just has $.</p>
</blockquote>
<p>via <a href="http://stackoverflow.com/a/3073818">http://stackoverflow.com/a/3073818</a></p>
<p>Perl might have this from shell tools like awk et al. hence:</p>
<blockquote>
<p>Having a symbol to denote variables makes string interpolation simple and clear. Shell, Perl and PHP grew out of the need for quick and easy string manipulation</p>
</blockquote>
<p>via <a href="http://stackoverflow.com/a/3596504">http://stackoverflow.com/a/3596504</a></p>
<p>Then Quora provided a very nice anecdote, collating the above results even more:</p>
<blockquote>
<p>PHP was originally implemented as a set of Perl scripts written by Rasmus to manage his website -- "PHP" stood for "Personal Homepage". A number of other syntactical elements in PHP are reminiscent of Perl as well.</p>
<p>Perl probably picked up this from awk and sh, which likely picked it up from BASIC, which predates Unix by about 5-10 years.</p>
<p>Bit of trivia: the $ (or @ or % in Perl 5) is referred to as a sigil.</p>
</blockquote>
<p>via <a href="https://www.quora.com/Why-we-use-dollar-symbol-before-variables-in-PHP">https://www.quora.com/Why-we-use-dollar-symbol-before-variables-in-PHP</a></p>
<p>From this we find out that $, @ and % are actually called sigils [3] in computer programming. Next stop was to see what these sigils indicated in Perl:</p>
<blockquote>
<p>Scalar values are always named with '$', even when referring to a scalar that is part of an array or a hash. The '$' symbol works semantically like the English word "the" in that it indicates a single value is expected.</p>
</blockquote>
<pre class='highlight'> $days # the simple scalar value "days"
$days[28] # the 29th element of array @days
$days{'Feb'} # the 'Feb' value from hash %days
$#days # the last index of array @days
</pre>
<blockquote>
<p>Entire arrays (and slices of arrays and hashes) are denoted by '@', which works much as the word "these" or "those" does in English, in that it indicates multiple values are expected.</p>
</blockquote>
<pre class='highlight'> @days # ($days[0], $days[1],... $days[n])
@days[3,4,5] # same as ($days[3],$days[4],$days[5])
@days{'a','c'} # same as ($days{'a'},$days{'c'})
</pre>
<blockquote>
<p>Entire hashes are denoted by '%':</p>
</blockquote>
<pre class='highlight'> %days # (key1, val1, key2, val2 ...)
</pre>
<p>via <a href="http://search.cpan.org/%7Eshay/perl-5.24.1/pod/perldata.pod#Variable_names">http://search.cpan.org/~shay/perl-5.24.1/pod/perldata.pod#Variable_names</a></p>
<p>Very interesting and they remind me of Ruby's shorthand or general delimited input:</p>
<pre class='highlight ruby'><span class="sx">%w(foo bar)</span> <span class="c1"># => ["foo", "bar"]</span>
<span class="c1"># %r() is another way to write a regular expression.</span>
<span class="c1"># %q() is another way to write a single-quoted string (and can be multi-line, which is useful)</span>
<span class="c1"># %Q() gives a double-quoted string</span>
<span class="c1"># %x() is a shell command</span>
<span class="c1"># %i() gives an array of symbols (Ruby >= 2.0.0)</span>
<span class="c1"># %s() turns foo into a symbol (:foo)</span>
</pre>
<p>Conclusion? the dollar sign for variables in PHP is actually a vestigial sigil since compared to Perl there aren't any for arrays and hashes. </p>
<p>[0] - <a href="https://codeigniter.com">https://codeigniter.com</a><br>
[1] - <a href="https://github.com/jenssegers/codeigniter-hmvc-modules">https://github.com/jenssegers/codeigniter-hmvc-modules</a><br>
[3] - <a href="https://en.wikipedia.org/wiki/Sigil_(computer_programming)">https://en.wikipedia.org/wiki/Sigil_(computer_programming)</a></p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/302023-11-05T17:16:02Z2023-11-05T17:16:02ZmacOS Sierra upgrade from a developer's perspective<p>Most developers (myself included) usually wait for the <code>point one</code> release of the next major macOS upgrade. This is mostly in order so that all the related tools/applications maintainers will have time to upgrade and iron out their bugs/issues with the <em>new</em> OS.</p>
<p>Since I use my Mac mostly as a glorified *nix replacement, the GUI applications are scarce (notably: <a target="_blank" href="https://www.iterm2.com/downloads.html">iTerm <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, <a target="_blank" href="https://paw.cloud/">Paw <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, <a target="_blank" href="http://postgresapp.com/">Postgres.app <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, Xcode and a couple of small utilities) i.e. the bulk of my development is dependent on <a target="_blank" href="http://brew.sh">Homebrew <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> working correctly + the good old <a target="_blank" href="https://rvm.io/">RVM <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>.</p>
<p>All of these work flawlessly under Sierra, one just has to remember to update them beforehand via:</p>
<pre class='highlight'>$ brew update
$ rvm get stable
</pre>
<p>Afterwards a clean output from <code>brew doctor</code> should fix whatever potential issues remain.</p>
<p>The main issues after the OS upgrade were, ironically, not the apps/utilities but the crushingly slow default values for <code>KeyRepeat</code>, a pink external EIZO display, the Notes.app crashing like nuts and finally some minor performance tweaks (mostly for aesthetics)</p>
<h4>Fixing slow key repeat</h4>
<p>If you use vim in a terminal you'll quickly realize that the navigation is back to <em>slow as heck</em>. That's due to the <code>KeyRepeat</code> values. In El Capitan this could be fixed easily via Karabiner but for 10.12 their developers have a wip Karabiner-Elements which it's useless at this point (at least for me as it tells that I should edit JSON files).</p>
<p>Well, no thank you good sirs: if I'm going to edit config files, I'd rather do it directly at the OS level. </p>
<p>After some testing around I got back the fast and snappy vim scroll/navigation via:</p>
<pre class='highlight'>$ defaults write NSGlobalDomain KeyRepeat -int 1
$ defaults write NSGlobalDomain InitialKeyRepeat -int 12
</pre>
<p>Note: these can be reset back to their default via:</p>
<pre class='highlight'>$ defaults delete NSGlobalDomain KeyRepeat
$ defaults delete NSGlobalDomain InitialKeyRepeat
</pre>
<p>In order for them to take effect you can just log out or restart your Mac.</p>
<h4>Fixing my pink external EIZO display</h4>
<p>This was rather easy but tedious: it basically boils down to repeating the same steps again from Mathew's <a target="_blank" href="http://www.mathewinkson.com/2013/03/force-rgb-mode-in-mac-os-x-to-fix-the-picture-quality-of-an-external-monitor">article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> i.e.: </p>
<p>Disable macOS's SIP by booting into recovery mode (using <code>Command-R</code> whilst rebooting your mac and then running <code>csrutil disable</code> in the terminal).</p>
<p>Download the linked Ruby script and run it via <code>ruby patch-edid.rb</code>. It will generate a directory.</p>
<p>Move the directory into (back-up the old one if it exists):<br>
<code>/System/Library/Displays/Contents/Resources/Overrides</code></p>
<p>Then you can restart again into recovery mode and enable back SIP by running <code>csrutil enable</code> into the terminal.</p>
<p>After all this: my external LCD was crystal clear and NOT pink anymore.</p>
<h4>Notes.app crashing and minor performance tweaks</h4>
<p>The first one is simple: just disable/enable the iCloud Notes syncing. </p>
<p>Regarding the second one you can tick <em>reduce transparency and motion</em> in the Accessibility section in Settings (this should offload the GPU if you have an older Mac with Intel graphics and as aesthetics and UX go, I'm not a fan of over-the-top animations and transparency).</p>
<h4>Other issues</h4>
<p><em>Wi-Fi not working</em></p>
<p>Rachel pointed out her Wi-Fi wasn't working anymore. The fix: after posting the issue on Apple forums someone suggested <a target="_blank" href="http://www.cydiageeks.com/fix-slow-wi-fi-issues-macos-sierra-upgrade.html">this article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> that finally fixed it.</p>
<p>I also had a small problem with it but it quickly went away by turning the Wi-Fi off and then back on. In any case hopefully this will ease the upgrade for someone.</p>
<h4>Conclusion</h4>
<p>Bonus: right after the upgrade prepare for 100% CPU usage on all logical cores for ~ one hour or less, the culprit will be <code>photoanalysisd</code>:</p>
<blockquote>
<p>If you’ve just installed Mac OS Sierra and now see photoanalysisd sucking 100 to 200% CPU power, this process is doing some kind of face detection + object / image recognition / indexing on your Photos library. via <a target="_blank" href="https://blog.yimingliu.com/2016/09/20/check-progress-of-photoanalysisd/">check progress of photoanalysisd <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
</blockquote>
<p>In the end the upgrade wasn't painless e.g. El Capitan went smoothly compared but at least I removed an extra dependency - I no longer need to have Karabiner running in the background and somehow it feels a tad faster even whilst the memory pressure is now lower.</p>
<h4>Credits</h4>
<ul>
<li><a target="_blank" href="https://pqrs.org/osx/karabiner">karabiner <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://www.mathewinkson.com/2013/03/force-rgb-mode-in-mac-os-x-to-fix-the-picture-quality-of-an-external-monitor">Force RGB mode in Mac OS X <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://github.com/mathiasbynens/dotfiles/issues/687#issuecomment-249026654">Validate KeyRepeat values for Sierra <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="
https://coderwall.com/p/jzuuzg/osx-set-fast-keyboard-repeat-rate">Reset KeyRepeat <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/292023-11-05T17:16:02Z2023-11-05T17:16:02ZUsing RVM for quite some time? You should clean it up a bit<p>I can't even remember the last time I ran <code>rvm implode</code>, I'd reckon I've been using RVM for about three years. </p>
<p>Sure: I always update it via <code>rvm get stable</code> but I never really clean up old Rubys or gems, I only run <code>bundle clean --force</code> in each repository from time to time since I don't always use <code>bundle exec</code>.</p>
<p>In any case, time to see how much space it eats up on macOS via <code>rvm disk-usage all</code>:</p>
<pre class='highlight'> Downloaded Archives Usage: 1.3M
Repositories Usage: 0B
Extracted Source Code Usage: 5.2M
Log Files Usage: 28K
Packages Usage: 0B
Rubies Usage: 298M
Gemsets Usage: 11G
Wrappers Usage: 212K
Temporary Files Usage: 0B
Other Files Usage: 5.6M
Total Disk Usage: 11G
</pre>
<p><strong>Eleven gigabytes</strong> of gems, sources, caches and various paraphernalia, wow, that's something. Let's try to clean this up a bit:</p>
<h4>Step one</h4>
<p>Always update RVM to its latest stable release:</p>
<pre class='highlight'>$ rvm get stable
</pre>
<h4>Step two</h4>
<p>Share the gem cache with all Ruby versions (note this might introduce some subtle bugs if you like to edit your gems like me for debug purposes):</p>
<pre class='highlight'>$ rvm gemset globalcache enable
</pre>
<h4>Step three (attention destructive)</h4>
<p>Run this simple script by <a target="_blank" href="https://gist.github.com/kugaevsky/5830602">kugaevsky <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> to further clean up your gems.</p>
<p>Note:</p>
<blockquote>
<p>This process could be too destructive sometimes and you may need to run 'bundle' command from your project directory.</p>
</blockquote>
<h4>Step four</h4>
<p>Let RVM clean-up after itself:</p>
<blockquote>
<p><code>rvm cleanup</code> Lets you remove stale source folders / archives and other</p>
</blockquote>
<pre class='highlight'>$ rvm cleanup all
</pre>
<p>Note: this will take some time to complete.</p>
<h4>Results</h4>
<pre class='highlight'>$ rvm
" .etc
Total Disk Usage: 9.0G
</pre>
<p>Not bad (let's keep in mind that I did not remove any gemsets or Ruby installs and for my main projects I didn't need to run bundle after running kugaevsky's script).</p>
<p>Btw. if you're using a VM for development you can try <a target="_blank" href="http://marianposaceanu.com/articles/how-to-reduce-the-size-of-your-vms">this <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> afterwards to further reduce its size.</p>
<h4>Credits:</h4>
<ul>
<li><a target="_blank" href="https://coderwall.com/p/x3z2ag/cleanup-rvm">Cleanup RVM <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://gist.github.com/kugaevsky/5830602">kugaevsky's cleanup_all_gemsets.sh <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/262023-11-05T17:16:02Z2023-11-05T17:16:02ZMaking Rails asset pipeline faster<p>We all know that for a rather large Rails app where the front-end is quite stuffed, the asset pre-compilation and more importantly - development mode changes are far from instantaneous.</p>
<p>The front-end we're referring to is the kind that makes heavy use of sass, sass libraries (Compass, Bourbon, etc.) and transpiled JavaScript languages (like the old CoffeeScript, ES6, etc.)</p>
<h4>Replacing Ruby Sass with libsass</h4>
<p>On the Sass front for quite some time there's a pure C/C++ implementation of the Sass CSS precompiler: <a target="_blank" href="https://github.com/sass/libsass">libsass <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. Clearly, being implemented in C/C++ this means it should run orders of magnitude faster than the Ruby implementation.</p>
<p>All we need is a gem that uses it: enter <a target="_blank" href="https://github.com/sass/sassc-rails">sassc-rails <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> which is a drop-in replacement for the <code>sass-rails</code> gem. </p>
<p>How fast is <code>sassc-rails</code> compared to the vanilla gem in the real world? (benchmarks straight from their repo)</p>
<pre class='highlight'># Using sassc-rails
[1] pry(main)> Benchmark.bm { |bm| bm.report { Rails.application.assets["application.css"] } }
user system total real
1.720000 0.170000 1.890000 ( 1.936867)
# Using sass-rails
[1] pry(main)> Benchmark.bm { |bm| bm.report { Rails.application.assets["application.css"] } }
user system total real
7.820000 0.250000 8.070000 ( 8.106347)
</pre>
<p>Not really orders of magnitude faster but then again a 4.5x is not bad at all. </p>
<p>The only issue with this is that it doesn't fully work with the usual sass gems like Compass and more i.e. before using it in production make sure it can actually compile your scss files without issues.</p>
<p>To help with that you can check the <a target="_blank" href="http://sass-compatibility.github.io/">Sass Compatibility <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> website and run your app with the gem installed in a different branch to test things out.</p>
<h4>Compass intermission</h4>
<p>What grinds my gears is that Compass doesn't work at all with <code>sassc-rails</code>:</p>
<ul>
<li><a target="_blank" href="https://github.com/sass/sassc-rails/issues/19">sassc-rails GH issue <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://github.com/Compass/compass-rails/issues/242">compass-rails GH issue <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
<p>Also as a side note Compass seems, well, kinda dead:</p>
<ul>
<li><a target="_blank" href="https://github.com/Compass/compass">last commit in master a year ago <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://compass-style.org/blog">last blog post two years ago <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://wecodetheweb.com/2015/05/20/is-compass-dead/">Is Compass dead? <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://www.devbridge.com/articles/increasing-sass-compiling-performance-or-when-every-second-counts">Increasing Sass Compiling Performance or "When Every Second Counts” <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
<p>I think I'm going to migrate my front-ends that still use Compass to <a target="_blank" href="https://github.com/thoughtbot/bourbon">Bourbon <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and maybe <a target="_blank" href="https://github.com/ai/autoprefixer-rails">autoprefixer-rails <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
<h4>Replacing the JS transpiling/minification/etc. with mini_racer</h4>
<p>The problem with <a target="_blank" href="https://github.com/cowboyd/therubyracer">therubyracer <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> is that it uses version <code>~> 3.16.14.0</code> of <a target="_blank" href="https://github.com/cowboyd/libv8">libv8 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> ("a gem for distributing the v8 runtime libraries and headers in both source and binary form") whereas <a target="_blank" href="https://github.com/discourse/mini_racer">mini_racer <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> uses <code>~> 5.1</code> which as one might expect is quite faster than the former.</p>
<p>Some quick benchmarks from their repository:</p>
<pre class='highlight'>$ ruby bench_uglify.rb
Benching with MiniRacer
MiniRacer minify discourse_app.js 13813.36ms
MiniRacer minify discourse_app_minified.js 18271.19ms
MiniRacer minify discourse_app.js twice (2 threads) 13587.21ms
Benching with therubyracer
MiniRacer minify discourse_app.js 151467.164ms
MiniRacer minify discourse_app_minified.js 158172.097ms
MiniRacer minify discourse_app.js twice (2 threads) - DOES NOT FINISH
Killed: 9
</pre>
<p>Here we are talking about a 10x improvement i.e. really nice gains and thus an order of magnitude faster. On the compatibility side this seems to be a drop-in replacement i.e. so far in the apps I've added it in the Gemfile there were no issues whatsoever.</p>
<h4>Alternative to mini-racer for best possible performance</h4>
<p>Sprockets uses <a target="_blank" href="https://github.com/rails/execjs">ExecJS <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> which “picks the best runtime available to evaluate your JavaScript” this means that if you don't mind having an extra dependency installed you can just use <a target="_blank" href="https://nodejs.org">Node.js 6.x <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> to get the <em>maximum</em> performance.</p>
<p>Since I deploy my assets by precompilling them locally I just installed Node.js 6.2.0 via brew <code>brew install node</code> and ran <code>time rake assets:clobber assets:precompile</code> on a 2K lines CoffeeScript JS file. Without further ado, here are the results:</p>
<p><strong>node.js 6.2.0</strong></p>
<pre class='highlight'>rake assets:clobber assets:precompile 7.30s user 1.27s system 102% cpu 8.358 total
</pre>
<p><strong>mini-racer with libv8 5.x</strong></p>
<pre class='highlight'>rake assets:clobber assets:precompile 14.96s user 1.20s system 101% cpu 15.943 total
</pre>
<p>That's another 2x speed-up! Also, I tried it with 10K lines of CoffeeScript - in this case mini-racer didn't even finish.</p>
<p>Kudos goes to <a target="_blank" href="https://twitter.com/attilagyorffy">@attilagyorffy <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> for pointing this out.</p>
<h4>Should I use these in production?</h4>
<p>In a set-up where the assets are pre-compiled locally then uploaded to the actual VM this is not a big issue i.e. if something fails just revert to the original gems. </p>
<p>Mini-racer looks rock solid so far whereas sassc-rails still has issues with some libraries i.e. not ready for production in all use-cases yet.</p>
<p>If you don't mind installing node.js and want maximum performance then by all means do it since it works flawlessly with ExecJs.</p>
<p>In the optimal case where you can integrate both into your Gemfile you will get quite a nice boost during deploys and more importantly: during development (in apps with large sets of assets of course).</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/232023-11-05T17:16:02Z2023-11-05T17:16:02ZHow to Web conference, random thoughts, mostly live - five years later<p>Almost five years since the last post about How to Web [0] - wow that's some large slice of space-time continuum. I recall I almost started this blog for stuff like this, good memories [1]. </p>
<p>Half a decade later, what's changed one might ask? Well, the scale looks bigger and so far the talks have been interesting at least the ones I got to see. </p>
<p>Colette Balou [2] quick talk about being a decent human being i.e. not a total jackass when asking a potential person for advice.</p>
<p>The idea behind Mendele [3] is quite interesting and Jan Reichelt's talk explained it eloquently.</p>
<p>Not bad for half a day.</p>
<ul>
<li> [0] <a target="_blank" href="http://2015.howtoweb.co">2015 How To Web <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li> [1] <a target="_blank" href="http://marianposaceanu.com/articles/how-to-web-conference-random-thoughts-mostly-live">original article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li> [2] <a target="_blank" href="https://twitter.com/coletteballou">@coletteballou <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li> [3] <a target="_blank" href="https://www.mendeley.com">Mendeley <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/252023-11-05T17:16:02Z2023-11-05T17:16:02ZShedding some light into UUID version 4 in Ruby and Rails<p>Ruby's standard library and Rails's PostgreSQL adapter use by default version 4 UUIDs. This can be changed in Rails migrations via:</p>
<pre class='highlight ruby'><span class="ss">default: </span><span class="s1">'uuid_generate_v1()'</span>
</pre>
<p>param whereas Ruby's stdlib only supports version 4.</p>
<p>Another interesting difference is in the implementations:</p>
<h5>In the Ruby's stdlib the UUID method is found in SecureRandom:</h5>
<pre class='highlight ruby'> <span class="c1"># SecureRandom.uuid generates a random v4 UUID (Universally Unique IDentifier).</span>
<span class="c1">#</span>
<span class="c1"># The version 4 UUID is purely random (except the version).</span>
<span class="c1"># It doesn't contain meaningful information such as MAC addresses, timestamps, etc.</span>
<span class="c1">#</span>
<span class="c1"># See RFC 4122 for details of UUID.</span>
<span class="c1">#</span>
<span class="k">def</span> <span class="nf">uuid</span>
<span class="n">ary</span> <span class="o">=</span> <span class="n">random_bytes</span><span class="p">(</span><span class="mi">16</span><span class="p">).</span><span class="nf">unpack</span><span class="p">(</span><span class="s2">"NnnnnN"</span><span class="p">)</span>
<span class="n">ary</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">ary</span><span class="p">[</span><span class="mi">2</span><span class="p">]</span> <span class="o">&</span> <span class="mh">0x0fff</span><span class="p">)</span> <span class="o">|</span> <span class="mh">0x4000</span>
<span class="n">ary</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">=</span> <span class="p">(</span><span class="n">ary</span><span class="p">[</span><span class="mi">3</span><span class="p">]</span> <span class="o">&</span> <span class="mh">0x3fff</span><span class="p">)</span> <span class="o">|</span> <span class="mh">0x8000</span>
<span class="s2">"%08x-%04x-%04x-%04x-%04x%08x"</span> <span class="o">%</span> <span class="n">ary</span>
<span class="k">end</span>
</pre>
<p><a target="_blank" href="https://github.com/ruby/ruby/blob/trunk/lib/securerandom.rb#L229">source-code <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> </p>
<h5>The Rails version uses <code>uuid-ossp</code> postgres extension:</h5>
<pre class='highlight ruby'> <span class="c1"># By default, this will use the +uuid_generate_v4()+ function from the</span>
<span class="c1"># +uuid-ossp+ extension, which MUST be enabled on your database.</span>
<span class="k">def</span> <span class="nf">primary_key</span><span class="p">(</span><span class="nb">name</span><span class="p">,</span> <span class="n">type</span> <span class="o">=</span> <span class="ss">:primary_key</span><span class="p">,</span> <span class="n">options</span> <span class="o">=</span> <span class="p">{})</span>
<span class="k">return</span> <span class="k">super</span> <span class="k">unless</span> <span class="n">type</span> <span class="o">==</span> <span class="ss">:uuid</span>
<span class="n">options</span><span class="p">[</span><span class="ss">:default</span><span class="p">]</span> <span class="o">=</span> <span class="n">options</span><span class="p">.</span><span class="nf">fetch</span><span class="p">(</span><span class="ss">:default</span><span class="p">,</span> <span class="s1">'uuid_generate_v4()'</span><span class="p">)</span>
<span class="n">options</span><span class="p">[</span><span class="ss">:primary_key</span><span class="p">]</span> <span class="o">=</span> <span class="kp">true</span>
<span class="n">column</span> <span class="nb">name</span><span class="p">,</span> <span class="n">type</span><span class="p">,</span> <span class="n">options</span>
<span class="k">end</span>
</pre>
<p><a target="_blank" href="https://github.com/rails/rails/blob/4-2-stable/activerecord/lib/active_record/connection_adapters/postgresql/schema_definitions.rb#L108-L127">source-code <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> </p>
<p>The only difference is how the actual numbers are being generated in each library - this is quite interesting to investigate - let's start with the Ruby stdlib.</p>
<h5>Ruby standard library implementation</h5>
<pre class='highlight ruby'><span class="k">module</span> <span class="nn">SecureRandom</span>
<span class="k">if</span> <span class="n">defined?</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Random</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">gen_random</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="vi">@pid</span> <span class="o">=</span> <span class="mi">0</span> <span class="k">unless</span> <span class="n">defined?</span><span class="p">(</span><span class="vi">@pid</span><span class="p">)</span>
<span class="n">pid</span> <span class="o">=</span> <span class="vg">$$</span>
<span class="k">unless</span> <span class="vi">@pid</span> <span class="o">==</span> <span class="n">pid</span>
<span class="n">now</span> <span class="o">=</span> <span class="no">Process</span><span class="p">.</span><span class="nf">clock_gettime</span><span class="p">(</span><span class="no">Process</span><span class="o">::</span><span class="no">CLOCK_REALTIME</span><span class="p">,</span> <span class="ss">:nanosecond</span><span class="p">)</span>
<span class="n">ary</span> <span class="o">=</span> <span class="p">[</span><span class="n">now</span><span class="p">,</span> <span class="vi">@pid</span><span class="p">,</span> <span class="n">pid</span><span class="p">]</span>
<span class="no">OpenSSL</span><span class="o">::</span><span class="no">Random</span><span class="p">.</span><span class="nf">random_add</span><span class="p">(</span><span class="n">ary</span><span class="p">.</span><span class="nf">join</span><span class="p">(</span><span class="s2">""</span><span class="p">).</span><span class="nf">to_s</span><span class="p">,</span> <span class="mi">0</span><span class="o">.</span><span class="mi">0</span><span class="p">)</span>
<span class="vi">@pid</span> <span class="o">=</span> <span class="n">pid</span>
<span class="k">end</span>
<span class="k">return</span> <span class="no">OpenSSL</span><span class="o">::</span><span class="no">Random</span><span class="p">.</span><span class="nf">random_bytes</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">end</span>
<span class="k">else</span>
<span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">gen_random</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="n">ret</span> <span class="o">=</span> <span class="no">Random</span><span class="p">.</span><span class="nf">raw_seed</span><span class="p">(</span><span class="n">n</span><span class="p">)</span>
<span class="k">unless</span> <span class="n">ret</span>
<span class="k">raise</span> <span class="no">NotImplementedError</span><span class="p">,</span> <span class="s2">"No random device"</span>
<span class="k">end</span>
<span class="k">unless</span> <span class="n">ret</span><span class="p">.</span><span class="nf">length</span> <span class="o">==</span> <span class="n">n</span>
<span class="k">raise</span> <span class="no">NotImplementedError</span><span class="p">,</span> <span class="s2">"Unexpected partial read from random device: only </span><span class="si">#{</span><span class="n">ret</span><span class="p">.</span><span class="nf">length</span><span class="si">}</span><span class="s2"> for </span><span class="si">#{</span><span class="n">n</span><span class="si">}</span><span class="s2"> bytes"</span>
<span class="k">end</span>
<span class="n">ret</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p><a target="_blank" href="https://github.com/ruby/ruby/blob/trunk/lib/securerandom.rb#L49-L74">source-code <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
<p>Is starts with <code>OpenSSL::Random</code> which can be described as:</p>
<blockquote>
<p>OpenSSL cannot generate truly random numbers directly. The choices are to use a cryptographically secure PRNG with a good random seed (i.e. with OS harvested data from effectively random hardware events); or use a real hardware RNG. [1]</p>
</blockquote>
<p>If OpenSSL is not present it falls back to Ruby's pseudo-random number generator implemented in <code>Random.raw_seed</code> which uses a modified Mersenne Twister with a period of 2**19937-1.</p>
<h5>uuid-ossp extension implementation</h5>
<p>Looking at <code>uuid-ossp</code> source-code we can find:</p>
<pre class='highlight ruby'><span class="no">Datum</span>
<span class="n">uuid_generate_v4</span><span class="p">(</span><span class="no">PG_FUNCTION_ARGS</span><span class="p">)</span>
<span class="p">{</span>
<span class="k">return</span> <span class="n">uuid_generate_internal</span><span class="p">(</span><span class="no">UUID_MAKE_V4</span><span class="p">,</span> <span class="no">NULL</span><span class="p">,</span> <span class="no">NULL</span><span class="p">,</span> <span class="mi">0</span><span class="p">);</span>
<span class="p">}</span>
</pre>
<p>and the <code>uuid_generate_internal</code> relevant part of the function:</p>
<pre class='highlight ruby'><span class="k">case</span> <span class="mi">4</span><span class="p">:</span> <span class="sr">/* random uuid */</span>
<span class="ss">default:
</span><span class="p">{</span>
<span class="c1">#ifdef HAVE_UUID_E2FS</span>
<span class="n">uuid_t</span> <span class="n">uu</span><span class="p">;</span>
<span class="n">uuid_generate_random</span><span class="p">(</span><span class="n">uu</span><span class="p">);</span>
<span class="n">uuid_unparse</span><span class="p">(</span><span class="n">uu</span><span class="p">,</span> <span class="n">strbuf</span><span class="p">);</span>
<span class="c1">#endif</span>
<span class="k">break</span><span class="p">;</span>
<span class="p">}</span>
</pre>
<p>As we can see there's a call to <code>uuid_generate_random</code> - what can this be?</p>
<blockquote>
<p>uuid_generate_random(3) - Linux man page </p>
</blockquote>
<p>Its description:</p>
<blockquote>
<p>The uuid_generate_random function forces the use of the all-random UUID format, even if a high-quality random number generator (i.e., /dev/urandom) is not available, in which case a pseudo-random generator will be substituted. Note that the use of a pseudo-random generator may compromise the uniqueness of UUIDs generated in this fashion.</p>
</blockquote>
<p>Interesting to note that if <code>/dev/urandom</code> is not available - again it falls back to PRNG - It seems there's a nuance here or even a contradiction as <code>/dev/urandom</code> uses csPRNG (cryptographically secure pseudorandom number generator) [3]</p>
<h5>Conclusions</h5>
<p>This started as a simple curiosity on what versions of UUID I could use - note that this is not a critique of truly-random vs PRGNs as the RFC clearly states:</p>
<blockquote>
<p>The version 4 UUID is meant for generating UUIDs from truly-random or pseudo-random numbers. [0]</p>
</blockquote>
<p>which makes both implementations correct. </p>
<p>It makes sense for the UUID method to be in SecureRandom in Ruby since it's only the version 4 implementation and by default it uses <code>OpenSSL::Random</code>. The only minor gripe I have with this is that there's no UUID lib for general use in Ruby supporting all the versions [2].</p>
<p>Regarding their implementations it should be noted that they differ and if the <em>quality of randomness</em> is important one should further investigate (e.g. due to missing OpenSSL - Ruby will use the internal PRNG which at first look it appears quite solid as it uses for seeding <code>dev/urandom</code> [6] but it might not be in the same class of csPRNG)</p>
<p>For UUIDs both implementations should yield usable random UUIDs even if the library falls back to a non csPRNG algorithm. In the end there's a <em>small gotcha</em>:</p>
<blockquote>
<p>Distributed applications generating UUIDs at a variety of hosts must be willing to rely on the random number source at all hosts. If this is not feasible, the namespace variant should be used.</p>
</blockquote>
<p>In order to <em>avoid</em> UUID collisions [4].</p>
<p>[0] - <a target="_blank" href="http://www.ietf.org/rfc/rfc4122.txt">RFC-4122 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> <br>
[1] - Why OpenSSL can't use /dev/random directly? <a target="_blank" href="http://security.stackexchange.com/a/47882">question <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a><br>
[2] - I usually use <a target="_blank" href="https://github.com/sporkmonger/uuidtools">uuidtools <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a><br>
[3] - Myths about <a target="_blank" href="http://www.2uo.de/myths-about-urandom">/dev/urandom <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a><br>
[4] - <a target="_blank" href="http://programmers.stackexchange.com/questions/130261/uuid-collisions">uuid-collisions <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a><br>
[5] - bonus read <a target="_blank" href="http://www0.cs.ucl.ac.uk/staff/d.jones/GoodPracticeRNG.pdf">GoodPracticeRNG <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a><br>
[6] - <a target="_blank" href="https://github.com/ruby/ruby/blob/trunk/random.c#L458">source-code <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/242023-11-05T17:16:02Z2023-11-05T17:16:02ZThe half-life of a programmer<blockquote>
<p>Half-life (t1/2) is the amount of time required for the amount of something to fall to half its initial value. The term is very commonly used in nuclear physics to describe how quickly unstable atoms undergo radioactive decay, but it is also used more generally for discussing any type of exponential decay.</p>
</blockquote>
<p>I had this almost random idea of when a programmer hits his or hers career <em>half-life</em>. </p>
<h4>Tangents</h4>
<p>First a few points that need explaining: <em>almost random</em> is in the sense that next year this time I'll be hitting thirty (Faith No More <a target="_blank" href="https://www.youtube.com/watch?v=U8b88US-6ts">track <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> is already playing in my head).</p>
<p>The next point is how one should understand the word "career" in the context of the field I'm working in. The word itself makes me think of a reductionist fifties like view of how one works and/or deals with work. </p>
<p>This begets the question <em>"What does 'career' mean for a programmer?"</em> - tricky question and interesting tangent: methinks it refers to that period of time when one starts to work professionally (getting paid) to the point in time when one stops doing that.</p>
<p>Let's jump on another tangent: <em>"Why is the end of a programming career when one stops writing code?"</em> - clearly one could easily jump on a management position and still call oneself a programmer - that for me is not programming any more, maybe I'm a purist and yes I'm not fond of labels like "team leader", "CTO", "lead developer", "senior developer" and all that paraphernalia that in the end is just utter non-sense.</p>
<h4>Relation to age</h4>
<p>If one looks around the "average" age or more likely the anecdotal age (yes this is not even proper empiric data) of developers in shiny start-ups is around twenty seven, I reckon. And it makes sense - they're relatively fresh out of university programmers with a decent experience on that hi(y)ppie new programming language or paradigm.</p>
<p>I don't want to turn this into a rant, methinks I was also in that situation and it's a sane approach as long as one doesn't go into extremes (like using MongoDB, OrientDB, InfluxDB, etc. for a problem's domain where a relational DB is eye melting clear).</p>
<p>In any case, years pass, one gets experience and more importantly, experience at a higher level i.e. when one can much more easily understand the inner-workings of complex systems. The problem that stems out of this is that at some point work gets repetitive (if you let it) and one can easily get entrenched in a tool-chain.</p>
<h4>The half-life of a programmer</h4>
<p>I'm starting to feel this is the crux of the problem: a programmer hits half-life when he realizes that most of the work he does is repetitive and he or she gets entrenched in a tool-chain. Clearly, if one cannot overcome these slight issues then we have a problem that might lead to a non-programming career or an <em>illusory</em> one: "team leader", "CTO", "lead developer", "senior developer", "consultant" etc.</p>
<p>The issue with those terms is that some programmers start to take it way too seriously whilst completely ignoring what I like to call <em>referential humility</em>.</p>
<p>Most of my heroes: the likes of <a target="_blank" href="http://onestepback.org">Jim Weirich <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, <a target="_blank" href="http://www.sandimetz.com">Sandi Metz <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and more seem to be in for life (the career) and I find that very reassuring.</p>
<h4>Referential humility</h4>
<p>What does that mean in the end? - just a play of words from <em>referential integrity</em>:</p>
<blockquote>
<p>Referential integrity is a property of data which, when satisfied, requires every value of one attribute (column) of a relation (table) to exist as a value of another attribute in a different (or the same) relation (table).</p>
</blockquote>
<p>In other words: there's always something "new" or something we still don't have a grasp of - hence the end of the road in a programmer's career is virtually non-existent.</p>
<h4>Conclusion</h4>
<p>Once you hit this <em>half-life</em> - choose wisely, work in the end is just another distraction from death, it's in our best interest to make that distraction authentic.</p>
<p>Vaguely related to the <em>distraction from death</em> tangent:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=wHWbZmg2hzU">Friedrich Nietzsche via The School of Life <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=D9JCwkx558o">Soren Kierkegaard via The School of Life <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=IgbHzFb1hGw">The Soul of Software by Avdi Grimm <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/212023-11-05T17:16:02Z2023-11-05T17:16:02ZRuby 2.2.0 Preview 1 quick Rails benchmarks<p>Great news everyone! Ruby 2.2 preview 1 has been <a target="_blank" href="https://www.ruby-lang.org/en/news/2014/09/18/ruby-2.2.0-preview1-released/">released <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>! I'm really curios about the <a target="_blank" href="https://bugs.ruby-lang.org/issues/10137">Incremental GC <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and <a target="_blank" href="https://bugs.ruby-lang.org/issues/9634">Symbol GC <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> so let's run some quick Rails benchmarks on a normal Rails API app.</p>
<p>First off let's install the preview via RVM:</p>
<pre class='highlight'>rvm install ruby-2.2.0-preview1
</pre>
<p>After fiddling around about five minutes trying to find a part of the application that doesn't fail under the Preview I stopped at the simple <code>/profiles</code> endpoint that just renders a JSON of all profiles, quite simple indeed. Using the trusty <a target="_blank" href="https://github.com/wg/wrk">wrk <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> I fired up a quick bench:</p>
<pre class='highlight'>wrk -t10 -c10 -d20s http://localhost:8080/profiles
</pre>
<p>The results are as follows:</p>
<h4>Ruby 2.1.2p95</h4>
<pre class='highlight'>Running 20s test @ http://localhost:8080/profiles
10 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 255.02ms 25.10ms 372.80ms 67.61%
Req/Sec 3.21 0.70 5.00 71.13%
771 requests in 20.01s, 4.40MB read
Requests/sec: 38.53
Transfer/sec: 225.31KB
------------------------------
50%,252 ms
90%,285 ms
99%,328 ms
99.999%,372 ms
</pre>
<h4>Ruby 2.2.0preview1</h4>
<pre class='highlight'>Running 20s test @ http://localhost:8080/profiles
10 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 253.27ms 30.64ms 344.75ms 64.21%
Req/Sec 3.34 0.70 5.00 89.63%
786 requests in 20.02s, 4.49MB read
Requests/sec: 39.26
Transfer/sec: 229.60KB
------------------------------
50%,251 ms
90%,291 ms
99%,329 ms
99.999%,344 ms
</pre>
<p>I'm not really sure that I should interpret them yet it seems that under the Preview we have a slight improvement but within margins of error. At this point I don't think is the best benchmark for the Preview as we don't use views thus Rails won't bloat up the memory with Strings.</p>
<p>On the memory usage side we have 65M vs 75M (Preview vs. 2.1) so in this scenario we clearly have a winner. </p>
<p><strong>note</strong>: this was measured using OSX's Activity Monitor after wrk finished the benchmark and it's the average of the unicorn workers sizes.</p>
<h4>Issues</h4>
<p>Bundler and all the gems installed without issue but in some cases I got silent failures. The benchmarks were run on an actual working/production Rails 4.0.x app with around 25 gems. Nonetheless all of the gems installed and I could boot up Rails with unicorn and benchmark the simpler endpoints which is great.</p>
<h4>Conclusion</h4>
<p>TBD - this is work in progress I will update it with more information</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/122023-11-05T17:16:02Z2023-11-05T17:16:02ZImprove Rails performance by adding a few gems<p>Working with Rails for some time you start nitpicking on how to improve it. This is a first in the series of articles regarding on how to improve (even marginally) Rails's performance.</p>
<p>I'll focus on a bunch of gems that speed up, in some cases considerably, small parts of Rails, like the html escaping, the String#blank? and JSON utils.</p>
<h4>Benchmarking methodology</h4>
<p>Methodology is a strong word for just running a couple of times in the console <code>wrk</code> but I'm not searching for the holy grail here, just to get a raw idea.</p>
<p>I switched from the old apache ab to <a target="_blank" href="https://github.com/wg/wrk">wrk <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>: </p>
<blockquote>
<p>wrk is a modern HTTP benchmarking tool capable of generating significant<br>
load when run on a single multi-core CPU.</p>
</blockquote>
<pre class='highlight'>wrk -t10 -c10 -d10s http://localhost:3000
</pre>
<p>This runs a benchmark for 10 seconds, using 10 threads, and keeping 50 HTTP connections open i.e. this should suffice. Just remember to benchmark on your actual app to see the real improvements.</p>
<h4>The escape_utils gem</h4>
<p>Just faster all html escaping via the lovely <a target="_blank" href="https://github.com/brianmario/escape_utils">escape_utils <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> gem. In order to use it in Rails one needs to add an initializer that patches things up:</p>
<pre class='highlight ruby'><span class="k">begin</span>
<span class="nb">require</span> <span class="s1">'escape_utils/html/rack'</span> <span class="c1"># to patch Rack::Utils</span>
<span class="nb">require</span> <span class="s1">'escape_utils/html/erb'</span> <span class="c1"># to patch ERB::Util</span>
<span class="nb">require</span> <span class="s1">'escape_utils/html/cgi'</span> <span class="c1"># to patch CGI</span>
<span class="nb">require</span> <span class="s1">'escape_utils/html/haml'</span> <span class="c1"># to patch Haml::Helpers</span>
<span class="k">rescue</span> <span class="no">LoadError</span>
<span class="no">Rails</span><span class="p">.</span><span class="nf">logger</span><span class="p">.</span><span class="nf">info</span> <span class="s1">'Escape_utils is not in the gemfile'</span>
<span class="k">end</span>
</pre>
<p>The logic to test it:</p>
<pre class='highlight ruby'><span class="k">def</span> <span class="nf">escape_utils</span>
<span class="vi">@escape_me</span> <span class="o">=</span> <span class="o"><<-</span><span class="no">HTML</span><span class="sh">
<body class="application articles_show">
<!-- Responsive navigation
==================================================== -->
<div class="container">
<nav id="nav">
<ul>
<li><a href="/"><i class="ss-standard ss-home"></i>home</a></li>
<li><a href="/home/about"><i class="ss-standard ss-info"></i>about</a></li>
<li><a href="/contact"><i class="ss-standard ss-ellipsischat"></i>contact</a></li>
<li><a href="/home/projects"><i class="ss-standard ss-fork"></i>projects</a></li>
<li><a href="/tags"><i class="ss-standard ss-tag"></i>tags</a></li>
<li><a href="/articles?query=code"><i class="ss-standard ss-search"></i>search</a></li>
</ul>
</nav>
<a href="#" class="ss-standard ss-list" id="nav-toggle" aria-hidden="true"></a>
</span><span class="no"> HTML</span>
<span class="n">render</span> <span class="ss">inline: </span><span class="s2">"Hello world <%= @escape_me %>"</span>
<span class="k">end</span>
</pre>
<p>With standard Rails:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 35.40ms 3.55ms 64.70ms 91.98%
Req/Sec 142.19 11.68 164.00 83.12%
2837 requests in 10.00s, 4.92MB read
Requests/sec: 283.61
Transfer/sec: 503.34KB
</pre>
<p>With the escape_utils gem:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 34.06ms 3.89ms 63.92ms 89.10%
Req/Sec 148.65 13.36 180.00 75.94%
2960 requests in 10.00s, 5.46MB read
Requests/sec: 295.98
Transfer/sec: 558.72KB
</pre>
<h4>The fast_blank gem</h4>
<p>Living under the impression that the blank? method is too slow? say no more and just try the <a target="_blank" href="https://github.com/SamSaffron/fast_blank">fast_blank <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> gem!</p>
<p>Just add <code>gem 'fast_blank'</code> to your Gemfile and this should speed up quite nicely the String#blank? method as described in <a target="_blank" href="http://thechangelog.com/fast_blank-stringblank-in-c/">this article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. For testing I just added this code:</p>
<blockquote>
<p>fast_blank is a simple extension which provides a fast implementation of active support's string#blank? function</p>
</blockquote>
<pre class='highlight ruby'> <span class="k">def</span> <span class="nf">fast_blank_test</span>
<span class="n">n</span> <span class="o">=</span> <span class="mi">1000</span>
<span class="n">strings</span> <span class="o">=</span> <span class="p">[</span>
<span class="s2">""</span><span class="p">,</span>
<span class="s2">"</span><span class="se">\r\n\r\n</span><span class="s2"> "</span><span class="p">,</span>
<span class="s2">"this is a test"</span><span class="p">,</span>
<span class="s2">" this is a longer test"</span><span class="p">,</span>
<span class="s2">" this is a longer test
this is a longer test
this is a longer test
this is a longer test
this is a longer test"</span>
<span class="p">]</span>
<span class="no">Benchmark</span><span class="p">.</span><span class="nf">bmbm</span> <span class="k">do</span> <span class="o">|</span><span class="n">x</span><span class="o">|</span>
<span class="n">strings</span><span class="p">.</span><span class="nf">each</span> <span class="k">do</span> <span class="o">|</span><span class="n">s</span><span class="o">|</span>
<span class="n">x</span><span class="p">.</span><span class="nf">report</span><span class="p">(</span><span class="s2">"Fast Blank </span><span class="si">#{</span><span class="n">s</span><span class="p">.</span><span class="nf">length</span><span class="si">}</span><span class="s2"> :"</span><span class="p">)</span> <span class="k">do</span>
<span class="n">n</span><span class="p">.</span><span class="nf">times</span> <span class="p">{</span> <span class="n">s</span><span class="p">.</span><span class="nf">blank?</span> <span class="p">}</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="k">end</span>
<span class="n">render</span> <span class="ss">nothing: </span><span class="kp">true</span>
<span class="k">end</span>
</pre>
<p>With standard Rails:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.40s 207.72ms 1.58s 92.68%
Req/Sec 3.10 2.11 6.00 53.66%
69 requests in 10.01s, 33.08KB read
Requests/sec: 6.90
Transfer/sec: 3.31KB
</pre>
<p>With the fast_blank gem:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 1.33s 179.56ms 1.41s 93.33%
Req/Sec 3.07 0.80 4.00 40.00%
72 requests in 10.00s, 34.52KB read
Requests/sec: 7.20
Transfer/sec: 3.45KB
</pre>
<h4>The oj gem</h4>
<pre class='highlight ruby'><span class="c1"># oj gem</span>
<span class="n">gem</span> <span class="s1">'oj'</span>
<span class="n">gem</span> <span class="s1">'oj_mimic_json'</span> <span class="c1"># we need this for Rails 4.1.x</span>
</pre>
<p>The test logic is simple, just serialize all articles into JSON:</p>
<pre class='highlight ruby'><span class="k">class</span> <span class="nc">SidechannelsController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">oj</span>
<span class="n">render</span> <span class="ss">json: </span><span class="no">Article</span><span class="p">.</span><span class="nf">all</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>With standard Rails serializers:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 108.37ms 5.12ms 134.90ms 83.33%
Req/Sec 45.76 3.60 55.00 57.69%
922 requests in 10.00s, 57.41MB read
Requests/sec: 92.17
Transfer/sec: 5.74MB
</pre>
<p>With oj gem:</p>
<pre class='highlight'>Running 10s test @ http://localhost:3000/sidechannels/bench
2 threads and 10 connections
Thread Stats Avg Stdev Max +/- Stdev
Latency 78.06ms 4.43ms 92.83ms 81.31%
Req/Sec 63.64 5.33 71.00 64.49%
1277 requests in 10.00s, 79.83MB read
Requests/sec: 127.65
Transfer/sec: 7.98MB
</pre>
<h4>Using jemalloc</h4>
<p>OK, this is not really a gem, if you want to dig into it then do check out my <a target="_blank" href="https://gist.github.com/dakull/5f3d22eff5fffb43e511">gist <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. On initial testing it won't yield much performance gains, at least for my use case. </p>
<p><strong>note</strong>: it will be included by default in Ruby at some point.</p>
<p><strong>update</strong>: do try the <a target="_blank" href="https://github.com/kzk/jemalloc-rb">jemalloc <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> gem by kzk:</p>
<pre class='highlight shell'>gem install jemalloc
je -v rails s
</pre>
<h4>Dig into your Rails app</h4>
<p>Fear not and use <a target="_blank" href="https://github.com/MiniProfiler/rack-mini-profiler">MiniProfiler <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> with the awesome <a target="_blank" href="http://samsaffron.com/archive/2013/03/19/flame-graphs-in-ruby-miniprofiler">FlameGraphs <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> by Sam Saffron.</p>
<h4>Conclusion</h4>
<p>Depending on what your app is doing you might want to add to your Gemfile some of these gems, I usually add them all just for good measure (you might want to check your RAM usage and have a full test suite before doing this though).</p>
<p>The <strong>oj</strong> gem is just great for a Rails based JSON API where you can drop the views and just serialize using representers or your pattern of choice.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/142023-11-05T17:16:02Z2023-11-05T17:16:02ZIs Rubinius 2.2.3 production ready ?<p>Ruby 2.1 was released this Christmas, great news everyone! It sports a better GC (RGenGC - gerational GC), hierarchical method caching, some small syntax changes and non-experimental rafinements. All in all one can expect 5% to 15% performance increase which is quite awesome.</p>
<p>As I was reading the comments in the hacker news thread related to the release, one of them caught my eye - we need JIT in the MRI Ruby VM. OK but looks like everyone forgets about Rubinius that sports for some time a LLVM-based JIT, native threads, low-pause generational garbage collector and almost perfect support of C extensions.</p>
<p>Yes we also have JRuby - it might just be the fastest implementation and when coupled with a server like TorqueBox is even faster, the main issue: some C libraries need to be swapped but as one can see later in the article this was just old thinking at play, clearly things are much better now as most gems do support JRuby without any issue.</p>
<p>So we have this awesome middle-ground so to say between Ruby VMs: it supports both C extensions without a problem (yet, empirically at least, some more exotic gems might fail to install) but somehow it gets ignored ?</p>
<p>The plan is simple, take one production Rails 4.0.2 app with all its dependences and convert it to Rubinius, install Puma and do some benchmarking then if all good deploy to staging.</p>
<h3>The setup</h3>
<p>Rubinius extracted most of the standard library into gems so in order to properly boot any Ruby script that uses them one needs this into the Gemfile:</p>
<pre class='highlight'>gem 'racc'
gem 'rubysl'
gem 'puma'
</pre>
<p>Notes:</p>
<ul>
<li>rubysl - is a rather cryptic name for ruby standard library gem</li>
<li>racc is a LALR(1) parser generator written by tenderlove - is also a
hard requirement for Rubinius or else no booting up Rails.</li>
<li>puma - well this is the best server choice for Rubinius as it supports
native threads</li>
</ul>
<p>Gems that won't work with Rubinius (will update if I'll find more):</p>
<pre class='highlight'># gem 'oj'
</pre>
<p>Remember to comment them out or again Rails won't boot up.</p>
<p>For VM install and switching I'm using the good old RVM with the latest version of Rubinius 2.2.3 and Ruby 2.1.0.</p>
<h3>On to the benchmarks!</h3>
<p>OK for obvious reasons I can't share the source code of the app, at some point I might create a public repository with something meaty for<br>
testing. These benchmarks are for a special case only and for some good fun also so before making any decisions based on them <strong>DO TEST</strong> first on your own.</p>
<p>The Rails app is actually an API so most of the important parts are disabled (i.e. Streaming DataStreaming Rendering RequestForgeryProtection) also the sprockets railtie.</p>
<h4>ApacheBench config</h4>
<p>I used the simple ApacheBench, Version 2.3 - clearly not the ideal tool for benchmarking (one should use siege or something similar) but<br>
for a quick glance like this test it fits the job nicely.</p>
<p>The command to start it up:<br>
<code>ab -n400 -c16 -T'application/json' http://localhost:3000/entries</code></p>
<h4>unicorn.rb</h4>
<pre class='highlight ruby'><span class="c1"># config/unicorn.rb</span>
<span class="n">worker_processes</span> <span class="no">Integer</span><span class="p">(</span><span class="no">ENV</span><span class="p">[</span><span class="s2">"WEB_CONCURRENCY"</span><span class="p">]</span> <span class="o">||</span> <span class="mi">3</span><span class="p">)</span>
<span class="n">timeout</span> <span class="mi">15</span>
<span class="n">preload_app</span> <span class="kp">true</span>
<span class="n">before_fork</span> <span class="k">do</span> <span class="o">|</span><span class="n">server</span><span class="p">,</span> <span class="n">worker</span><span class="o">|</span>
<span class="c1"># et cetera</span>
<span class="k">end</span>
</pre>
<p>The command to start it up: <br>
<code>unicorn_rails -c config/unicorn.rb -p 3000</code></p>
<p>Results after some runs:</p>
<pre class='highlight'>Concurrency Level: 16
Time taken for tests: 6.769 seconds
Complete requests: 400
Failed requests: 0
Write errors: 0
Total transferred: 3611600 bytes
HTML transferred: 3346800 bytes
Requests per second: 59.09 [#/sec] (mean)
Time per request: 270.766 [ms] (mean)
Time per request: 16.923 [ms] (mean, across all concurrent requests)
Transfer rate: 521.03 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 1.0 0 5
Processing: 49 267 36.8 270 331
Waiting: 44 266 36.8 269 330
Total: 49 267 36.3 270 331
Percentage of the requests served within a certain time (ms)
50% 270
66% 283
75% 288
80% 293
90% 308
95% 315
98% 324
99% 327
100% 331 (longest request)
</pre>
<h4>puma.rb on Rubinius 2.2.3</h4>
<pre class='highlight ruby'><span class="c1"># config/puma.rb</span>
<span class="n">threads</span> <span class="mi">8</span><span class="p">,</span><span class="mi">32</span>
<span class="n">workers</span> <span class="mi">1</span>
<span class="n">preload_app!</span>
<span class="n">on_worker_boot</span> <span class="k">do</span>
<span class="c1"># et cetera</span>
<span class="k">end</span>
</pre>
<p>The command to start it up: <br>
<code>puma -C config/puma.rb -b tcp://localhost:3000</code></p>
<p>Results after several runs (so that the JIT can do its magic):</p>
<pre class='highlight'>Concurrency Level: 16
Time taken for tests: 9.383 seconds
Complete requests: 400
Failed requests: 0
Write errors: 0
Total transferred: 3590400 bytes
HTML transferred: 3346800 bytes
Requests per second: 42.63 [#/sec] (mean)
Time per request: 375.311 [ms] (mean)
Time per request: 23.457 [ms] (mean, across all concurrent requests)
Transfer rate: 373.69 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 84 371 105.4 348 731
Waiting: 83 363 104.1 338 728
Total: 84 371 105.3 348 732
Percentage of the requests served within a certain time (ms)
50% 348
66% 390
75% 431
80% 458
90% 526
95% 571
98% 640
99% 683
100% 732 (longest request)
</pre>
<h4>puma.rb on JRuby 1.7.9</h4>
<pre class='highlight ruby'><span class="c1"># config/puma.rb</span>
<span class="n">threads</span> <span class="mi">8</span><span class="p">,</span><span class="mi">32</span>
<span class="n">preload_app!</span>
<span class="n">on_worker_boot</span> <span class="k">do</span>
<span class="no">ActiveSupport</span><span class="p">.</span><span class="nf">on_load</span><span class="p">(</span><span class="ss">:active_record</span><span class="p">)</span> <span class="k">do</span>
<span class="no">ActiveRecord</span><span class="o">::</span><span class="no">Base</span><span class="p">.</span><span class="nf">establish_connection</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>The command to start it up: <br>
<code>puma -C config/puma.rb -b tcp://localhost:3000</code></p>
<p>Gems that need replacement:</p>
<pre class='highlight'># gem 'pg'
gem 'activerecord-jdbcpostgresql-adapter'
</pre>
<p>Results after several runs (so that the JIT can do its magic):</p>
<pre class='highlight'>Concurrency Level: 16
Time taken for tests: 4.019 seconds
Complete requests: 400
Failed requests: 0
Write errors: 0
Total transferred: 3590400 bytes
HTML transferred: 3346800 bytes
Requests per second: 99.53 [#/sec] (mean)
Time per request: 160.760 [ms] (mean)
Time per request: 10.048 [ms] (mean, across all concurrent requests)
Transfer rate: 872.42 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 0 0 0.1 0 1
Processing: 35 158 31.5 157 389
Waiting: 34 151 27.1 149 261
Total: 36 158 31.5 157 389
Percentage of the requests served within a certain time (ms)
50% 157
66% 166
75% 173
80% 177
90% 189
95% 204
98% 232
99% 260
100% 389 (longest request)
</pre>
<h3>Conclusion</h3>
<p>The poor Rubinius performance might be related to the racc gem as it might be really slow as detailed in this Github <a target="_blank" href="https://github.com/rubinius/rubinius/issues/2632">thread <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
<p>14 req/s vs 60 req/s (I disabled cache and the app produces lots of ActiveRecord objects that's why the numbers are rather low) makes Rubinius, for now, not a good choice for this particular Rails app.</p>
<h4>Update</h4>
<p>Thanks to <a target="_blank" href="https://twitter.com/headius">headius <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> I've revised the benchmarks:<br>
- apparently my VM was accessing only one core (thus the initial abysmal performance of Rubinius and JRuby) - bumped to four<br>
- updated all benchmarks and also added JRuby 1.7.9</p>
<pre class='highlight'> jruby 99.53 #################################
cruby 59.09 ###################
rubinius 42.63 ##############
</pre>
<p>As one can clearly see from the chart above JRuby is the winner by an impressive margin and with only one gem change I think it deserves to be pushed to staging.</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/132023-11-05T17:16:02Z2023-11-05T17:16:02ZHow to reduce the size of your VMs<p>As the host OS I use Windows 8 (just upgraded to 8.1), well why ? one might ask.Is rather simple: Steam and after some dreadful searching and configuring tools I managed to install the basics for writing and deploying code: Vim, Git, PuTTy and a decent console replacement like Console2 [0].</p>
<p>Of course those aren't enough as 80% of my coding is *nix dependent and I wouldn't run it on anything else; actually I'm still thinking of dropping Windows for something like ArchLinux [1] <em>I fiddled with it and enjoyed all the low level stuff that just doesn't exist in Ubuntu Desktop</em>.</p>
<p>Needless to say I use lots of VMs: I currently have three images that I use daily: Ubuntu Desktop, Ubuntu Server and an old Windows XP <em>(well, I don't use it daily more like monthly)</em>. The problem of using just a few VMs with many projects is that it involves a lot of hdd trashing (i.e. git, deleting and creating lots of files).</p>
<p>What I did not realize is that my VMs were growing bigger and bigger by the day while their internal hdd space usage stayed mostly the same as I deleted old files and cleaned them up. For reference these were the initial sizes:</p>
<ul>
<li>Ubuntu desktop: <strong>19.7 GB</strong></li>
<li>Ubuntu server: <strong>8.0 GB</strong></li>
<li>Windows XP : <strong>7.9 GB</strong></li>
</ul>
<p>While trashing the SSD with all the writes and deletes I was expanding the VHDs despite the fact that I deleted the files in the VM. The cause: the actual blocks weren't nil so running a <code>VM compact</code> wouldn't yield any results.</p>
<blockquote>
<p>With the --compact option, can be used to compact disk images, i.e. remove blocks that only contains zeroes. This will shrink a dynamically allocated image again; it will reduce the physical size of the image without affecting the logical size of the virtual disk. Compaction works both for base images and for diff images created as part of a snapshot.</p>
</blockquote>
<p>The fix was clear: one needs from time to time to nullify the free space. After doing some quick research I've found easy ways to do it on every platform.</p>
<h2>On Linux</h2>
<p>The first version is using a tool like secure delete but with a very fast run:</p>
<pre class='highlight shell'>sudo apt-get install secure-delete
sfill -f -z -l -l -I -v /
</pre>
<p>Where:</p>
<pre class='highlight shell'>-f fast <span class="o">(</span>and insecure mode<span class="o">)</span>: no /dev/urandom, no synchronize mode.
-z last wipe writes zeros, not random data.
-l lessens the security <span class="o">(</span>use twice <span class="k">for </span>total insecure mode<span class="o">)</span>
-I just wipe space, not inodes
-v is verbose mode.
</pre>
<p>Or a much simpler way:</p>
<pre class='highlight shell'>sudo dd <span class="k">if</span><span class="o">=</span>/dev/zero <span class="nv">of</span><span class="o">=</span>/bigemptyfile <span class="nv">bs</span><span class="o">=</span>4096k
sudo rm -rf /bigemptyfile
</pre>
<p>This will fill the entire empty space with a null file that is erased at the end. I haven't tested this too much, it might yield issues but is faster than the first version.</p>
<h2>On Windows</h2>
<p>On Windows Xp one just has to download SysinternalsSuite [2] and run <code>sdelete –z</code> from the command prompt.</p>
<p>OK once all of this is over: shutdown the VMs and run compact on the VHD. Using VirtualBox just run from the console <code>VBoxManage modifyhd thedisk.vdi --compact</code>, using VMware, well just click around till you find it.</p>
<h2>OK time for results:</h2>
<ul>
<li>Ubuntu desktop: <strong>11.0 GB</strong> ~ -45%</li>
<li>Ubuntu server: <strong>4.3 GB</strong> ~ -47%</li>
<li>Windows XP : <strong>6.6 GB</strong> ~ -16%</li>
</ul>
<p>That's a whopping <strong>13.7 GB</strong> out of my main SSD 128G drive that I use as the system drive, not bad, not bad at all !</p>
<p>Credits:</p>
<ul>
<li><a target="_blank" href="http://sourceforge.net/projects/console">[0] Console2 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://www.archlinux.org">[1] Arch Linux <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://technet.microsoft.com/en-us/sysinternals/bb842062.aspx">[2] Sysinternals Suite <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/202023-11-05T17:16:02Z2023-11-05T17:16:02ZChunked transfer encoding in Rails (streaming)<p>Anyone that has written a little PHP knows what the <code>flush()</code> family of functions do. The ideal usage scenario for using chunked transfer[0] is when we have something costly to render e.g. the first three most recent articles on a blog. Why ? one might ask.</p>
<p>Is rather simple: in a normal request where the server responds with a <code>Content-Length</code> header the browser will wait until the whole page comes down the wire then it goes loading the assets et al. </p>
<p>Using the <code>Transfer-Encoding: chunked</code> header, the server will send chunks of the rendered page back to the browser so in the case of Rails, it starts with the layout and sends out the <code><head></code> part including assets like js and css. </p>
<p>It's clear how this helps the rendering of the page on the client side : get the first chunk containing the <code><head></code> with assets, immediately start loading the assets while waiting for the rest of the response. Of course, browsers nowadays include lots of micro-optimizations that might already do something similar but still this remains a good practice.</p>
<p>Implementation wise, you just need to add to your controller methods something like :</p>
<pre class='highlight ruby'><span class="k">class</span> <span class="nc">YourController</span> <span class="o"><</span> <span class="no">ApplicationController</span>
<span class="k">def</span> <span class="nf">index</span>
<span class="vi">@articles</span> <span class="o">=</span> <span class="no">Article</span><span class="p">.</span><span class="nf">most_recent</span>
<span class="n">render</span> <span class="ss">stream: </span><span class="kp">true</span>
<span class="k">end</span>
<span class="c1"># other controller logic</span>
<span class="k">end</span>
</pre>
<p>The latest version of Unicorn (4.x) comes by default[1] with support for chunked response. You can always add to your <code>unicorn_config.rb</code> something like: </p>
<pre class='highlight ruby'><span class="c1"># :tcp_nopush This prevents partial TCP frames from being sent out</span>
<span class="c1"># :tcp_nodelay Disables Nagle’s algorithm on TCP sockets if true.</span>
<span class="n">port</span> <span class="o">=</span> <span class="no">ENV</span><span class="p">[</span><span class="s2">"PORT"</span><span class="p">].</span><span class="nf">to_i</span> <span class="o">||</span> <span class="mi">3000</span>
<span class="c1"># the ENV["PORT"] is a Heroku environment variable</span>
<span class="n">listen</span> <span class="n">port</span><span class="p">,</span> <span class="ss">tcp_nopush: </span><span class="kp">false</span><span class="p">,</span> <span class="ss">tcp_nodelay: </span><span class="kp">true</span>
</pre>
<p>We also have some quirks when using streaming in Rails because of the inversion of template rendering order[2]:</p>
<blockquote>
<p>When streaming, rendering happens top-down instead of inside-out. Rails starts with the layout, and the template is rendered later, when its yield is reached .</p>
</blockquote>
<p>tl;dr: use <code>provide</code> instead of <code>content_for</code> when you have multiple calls to <code>content_for</code> otherwise it will break the purpose of streaming and/or it will concatenate the values from <code>content_for</code>.</p>
<p>There's also a “small” issue with NewRelic agent and Heroku: you need to disable browser instrumentation or else you'll get a blank page[3], thankfully the fix is rather trivial:</p>
<pre class='highlight ruby'><span class="c1"># config/newrelic.yml</span>
<span class="ss">browser_monitoring:
</span><span class="c1"># By default the agent automatically injects</span>
<span class="c1"># the monitoring JavaScript into web pages</span>
<span class="c1"># Turn this to false</span>
<span class="ss">auto_instrument: </span><span class="kp">false</span>
</pre>
<p>There's also <code>ActionController::Live</code> that can be used to create a simple Rails 4 chat application[4][5].</p>
<ul>
<li><a target="_blank" href="http://en.wikipedia.org/wiki/Chunked_transfer_encoding">[0] Chunked transfer encoding <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://unicorn.bogomips.org/Unicorn/Configurator.html#method-i-listen">[1] Unicorn Configurator <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://api.rubyonrails.org/classes/ActionController/Streaming.html">[2] Rails API - Streaming <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://icelab.com.au/articles/new-relic-heroku-and-rails-streaming-responses/">[3] New Relic, Heroku and Rails Streaming Responses <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://robots.thoughtbot.com/post/55421584115/chat-example-app-using-server-sent-events">[4] Chat Example App Using Server-Sent Events <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://rubysource.com/streaming-with-rails-4/">[5] Streaming with Rails 4 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/32023-11-05T17:16:02Z2023-11-05T17:16:02ZOn Ruby modules and concerns<p>Modules are useful for highly specialized code that can be injected into other classes for fun and profit or for creating Namespaces. An interesting approach is to use modules as an alternative to classical inheritance (without its the usual trade-offs) : the core idea is to share an abstracted <em>role</em> that can be included in a set of different classes.</p>
<p>One should start with the simplest definition of the word <em>role</em> : </p>
<blockquote>
<p>The function assumed or part played by a person or thing in a particular situation.</p>
</blockquote>
<p>“... <em>or thing in a Particular situation</em>” is key here so how we <em>encode</em> particulars in an object oriented way ? We create classes: blueprints that we can later instantiate and use at will. Next : <em>a function assumed by a thing</em> i.e. a well defined function that is used by objects in particular situations; more exactly different objects start playing a common role and when this happens it becomes clear that the common behaviour can be extracted into a module.</p>
<p>A <em>concern</em> is a nice abstraction that simplifies sharing behaviour using modules. It can be found in <a target="_blank" href="http://api.rubyonrails.org/classes/ActiveSupport/Concern.html">ActiveSupport::Concern <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and it just removes some boiler-plate code e.g. :</p>
<pre class='highlight ruby'><span class="k">def</span> <span class="nc">self</span><span class="o">.</span><span class="nf">included</span><span class="p">(</span><span class="n">base</span><span class="p">)</span>
<span class="n">base</span><span class="p">.</span><span class="nf">extend</span> <span class="no">ClassMethods</span>
<span class="n">base</span><span class="p">.</span><span class="nf">class_eval</span> <span class="k">do</span>
<span class="c1"># ...</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">ClassMethods</span>
<span class="c1"># ..</span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>tl;dr : <code>included</code> gets called when we do something like <code>include MyModule</code> into a class, the <code>base</code> argument is the object in which we include the module i.e. a Class instance (remember that classes in Ruby are instances of Class - interestingly the class of Class is again Class, so <em>it's all turtles all the way down</em>). </p>
<p>The abstracted code looks like this : </p>
<pre class='highlight ruby'><span class="k">module</span> <span class="nn">M</span>
<span class="kp">extend</span> <span class="no">ActiveSupport</span><span class="o">::</span><span class="no">Concern</span>
<span class="n">included</span> <span class="k">do</span>
<span class="c1"># ...</span>
<span class="k">end</span>
<span class="k">module</span> <span class="nn">ClassMethods</span>
<span class="c1"># this gets included automatically </span>
<span class="k">end</span>
<span class="k">end</span>
</pre>
<p>Bit cleaner but the classic way is not bad either as long as you know what's actually going on. We all love Rails's “magic” yet one could say that using it without having any clue on what's going on behind the scenes is an exercise in futility. </p>
<p>Going back to our Concerns : what I do like is how it easily resolves dependencies -> one can ponder further upon the <a target="_blank" href="https://github.com/rails/rails/blob/5b50c7d4d569069a1826c2876d654da7b047acc8/activesupport/lib/active_support/concern.rb#L107">source <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> -> some interesting coding going on in there.</p>
<p>Some simple uses for Concerns ? One can use them to apply the <a target="_blank" href="http://martinfowler.com/refactoring/catalog/extractMethod.html"><em>Extract Method</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> refactoring i.e. “code fragments that can be grouped together”. In <a target="_blank" href="http://37signals.com/svn/posts/3167-code-spelunking-in-the-all-new-basecamp">this 37signals article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> we have a simple example of a before filter that does some cookie mingling. The only issue here is that taking before filters out of the controller might result in some hard to debug code, one could argue that seeing all the filters per controller requires less mental switching than parsing <code>include Ajax</code> -> “oh wait this sets a before filter”. </p>
<p>Some much better usage one can find in this highly referenced article by DHH : <a target="_blank" href="http://37signals.com/svn/posts/3372-put-chubby-models-on-a-diet-with-concerns">“Put chubby models on a diet with concerns” <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> e.g. a Taggable, Visible and Dropboxed are clusters of functionality that can be injected in other classes so that they can share a common role.</p>
<p>Next stop up the ladder is the <a target="_blank" href="https://en.wikipedia.org/wiki/Data,_context_and_interaction">DCI paradigm <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, from a bird eye view, this is a more formalized way of using/sharing roles that also includes a scaffold framework of thinking for organizing code. I'll get into the nitty-gritty details in a new post.</p>
<p>Interesting stuff </p>
<ul>
<li><a target="_blank" href="http://stackoverflow.com/questions/156362/what-is-the-difference-between-include-and-extend-in-ruby">Include vs. extend detailed for reference <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://martinfowler.com/refactoring/catalog/index.html">Martin Fowler - Refactoring catalog <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://yehudakatz.com/2009/11/12/better-ruby-idioms">Better Ruby Idioms by Yehuda Katz <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://speakerdeck.com/qrush/basecamp-next-code-spelunking">Basecamp Next - Slides <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/42023-11-05T17:16:02Z2023-11-05T17:16:02ZOn semantic Ruby block constructs<p>I was cruising around my Github notifications and I found an interesting open issue created by Jim Weirich : “The Semantic Rule for { } VS do/end” in the Ruby style guide <a target="_blank" href="https://github.com/bbatsov/ruby-style-guide">repository <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>.</p>
<blockquote>
<p>The semantic rule says use <code>{ }</code> for blocks where the primary purpose of the block is to return a value, use do/end for blocks where the primary purpose of the block is to execute side effects.</p>
</blockquote>
<p>The main issue with this rule is that it implies the existence of some cases when one must use <code>do/end</code> on a single line. So what's the problem with this ? Well, most will argue it's not very good looking, it's verbose and it feels a bit hacky e.g. :</p>
<pre class='highlight'># one-liner that abides to the semantic rule
(1..10).each do |i| some_instance.side_effect = i end
</pre>
<p>versus :</p>
<pre class='highlight'># idiomatic Ruby one-liner
(1..10).each { |i| some_instance.side_effect = i }
</pre>
<p>I would say the difference is not that big and by abiding to the semantic rule one could make code more readable. Moreover it's not only about the aesthetics of code but also on its inherent semantics.</p>
<p>This can branch out in two directions : <em>good</em> i.e. improves codes readability or <em>bad</em> i.e. it might be confusing to developers that don't know how to interpret it.</p>
<p>This can also be applied to the lambda notation :</p>
<pre class='highlight'>-> { ... }
->(obj) { ... }
</pre>
<p>versus</p>
<pre class='highlight'>-> do ... end
->(obj) do ... end
</pre>
<p>Lambdas have one more semantic bagagge so to say: I usually use them to do some computation and return the result to be used somewhere else without creating side-effects for everything else procs are better suited.</p>
<p>One could argue that the <code>{ }</code> VS <code>do/end</code> distinction is superfluous for lambdas.</p>
<p>Pondering on it, the visual difference doesn't seem colossal so I think I'll adhere to this rule in my codebases from now on.</p>
<p>Credits :</p>
<ul>
<li><a target="_blank" href="http://devblog.avdi.org/2011/07/26/the-procedurefunction-block-convention-in-ruby">Avdi Grimm detailed article on the issue <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://onestepback.org/index.cgi/Tech/Ruby/BraceVsDoEnd.rdoc">Jim Weirich original article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://github.com/bbatsov/ruby-style-guide/issues/162">Ruby style guide issue <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://gist.github.com/dakull/5507946">Proc VS lambda <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/102023-11-05T17:16:02Z2023-11-05T17:16:02ZOn Ruby 2.0 memory usage, Unicorn and Heroku<p>On UNIX-like operating systems (e.g. Linux) there's the concept of process forking via the <code>fork()</code> system call. When one calls fork from a parent-process it will spawn a new child-process - that is a copy of its parent, then both processes return from fork. The child-process has an exact copy of the parent's memory in a separate address space. Due to this clearly not being efficient, UNIX implements the copy-on-write semantics (i.e. CoW): this delays the actual copying of memory until it needs to be written - simple and elegant.</p>
<h2>The old days of Ruby 1.8.7 and REE</h2>
<p>Historically, Ruby has been really bad at forking and I'm not referring to the language itself but to its VMs implementations: especially the MRI and the YARV. The issue is the way garbage collection works in these versions, without entering into details, when the GC runs to clear some unused references from memory it changes every object making them "dirty" i.e. CoW fails quickly as the whole memory becomes dirty. Why is this important ? The best Rack compliant servers use pre-forking to max out all CPUs (e.g. <a target="_blank" href="http://unicorn.bogomips.org/">Unicorn <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, <a target="_blank" href="https://www.phusionpassenger.com/">Phusion Passenger <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>). </p>
<p>When you fire up a Unicorn server it creates a number of a priori configured workers via the <code>fork()</code> system call. On a 64bit Linux, a Rails 3.x, almost vanilla application takes out ~ 70M of memory and a rather complex one ~ 200M, now multiply that to the number of available cores on your system, let's say eight and we have a memory usage spanning from <em>560M</em> to a whopping <em>1.6G</em>. Using Ruby 1.8.7 yields a nice bonus : there's a CoW friendly version with an updated garbage collection algorithm written by the guys at <a target="_blank" href="http://www.phusion.nl">Phusion <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - in the form of Ruby Enterprise Edition - <a target="_blank" href="http://www.rubyenterpriseedition.com">REE <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>.</p>
<p>This is not a solution as 1.8.7 nears EOL on June 2013 and REE <a target="_blank" href="https://blog.engineyard.com/2012/ruby-1-8-7-and-ree-end-of-life">is next <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, nevertheless REE was/is a great piece of software.</p>
<h2>The recent release of Ruby 2.0</h2>
<p>Narihiro Nakamura implemented the new GC algorithm - bitmap marking: in a nutshell - the Ruby VM can do its sweeping without actually modifying the objects i.e. CoW works as expected now. For more details you can check out a <a target="_blank" href="http://vimeo.com/38994805">video <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> about Ruby's GC and a recent really nice <a target="_blank" href="http://patshaughnessy.net/2012/3/23/why-you-should-be-excited-about-garbage-collection-in-ruby-2-0">high-level explanation <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> by Pat Shaughnessy.</p>
<p>When you combine Ruby 2.0 with Unicorn you can get some pretty impressive results. Using this simple script <a target="_blank" href="https://gist.github.com/dakull/5454732">memstats.rb <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> I checked the memory usage with eight workers:</p>
<pre class='highlight'> Memory Summary:
private_clean 0 kB
private_dirty 1,584 kB
pss 12,884 kB
rss 80,152 kB
shared_clean 1,984 kB
shared_dirty 76,584 kB
size 275,704 kB
swap 0 kB
</pre>
<p>Based on this <a target="_blank" href="https://gist.github.com/kenn/5105175">gist <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> : “rss represents the physical memory that is actually used, and it's comprised of private_clean + private_dirty + shared_clean + shared_dirty” so practically ~ 76M is shared and ~ 1.5M is private. This is a huge step-up from YARV 1.9.3 where there's no CoW friendly GC i.e. no memory sharing whatsoever. These results are impressive, of course my app is rather trivial (it just runs this blog) so in real ones the ratio will not be as high but still big enough to save lots or ram.</p>
<h2>What about Heroku ?</h2>
<p>One Heroku Dyno is limited to 512M of ram after which it starts swapping memory until it crashes and/or Heroku will send a SIGKILL and restart your app - <a target="_blank" href="http://blog.newrelic.com/2013/03/07/new-relics-instances-tab/">more info <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. Due to the recent routing-miscommunication, we all know that the best server for a Rack compliant app is Unicorn (actually, that should be common knowledge). </p>
<pre class='highlight'># config/unicorn.rb
worker_processes 8
</pre>
<p>What happens when you upgrade to Ruby 2.0 ? You can crank up the workers as much as doubling them without hitting the hard quota. </p>
<h2>Wrap-up</h2>
<p>Clearly this does not benefit only Heroku users, the upgrade to Ruby 2.0 is painless as in most cases is a drop-in replacement with the added bonus of lower memory usage. The big issue is with apps that run 1.8.7 or REE as upgrading from 1.8.7 to 1.9.3 and 2.0 yields some compatibility problems.</p>
<h3>Related articles</h3>
<ul>
<li><a target="_blank" href="https://news.ycombinator.com/item?id=3748175">Ruby GC implementations HN discussion <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://gist.github.com/authorNari/1273387">Narihiro Nakamura video transcript <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://tech.pro/blog/1247/ruby-versions-demystified">Ruby Versions Demystified <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="http://globaldev.co.uk/2013/03/ruby-2-0-0-in-detail">Ruby 2.0.0 in Detail <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/72023-11-05T17:16:02Z2023-11-05T17:16:02ZOn font rendering consistency across browsers<p>Back in the day (i.e. when Firefox's version was a single digit) font rendering was at its best on Mozilla's browser. I remember comparing Firefox's anti-aliasing to the new-kid-on-the-block Chrome : the difference was huge. </p>
<p>Time went by and we all know what happened : most web developers found themselves using Chrome as their main browser for doing their work and this is exactly what happened to me. Somehow the font rendering issue went under the radar.</p>
<p>Fast-forward to today : I fired up Firefox to check the rendering of my blog and surprise: <em>faux</em> <em>bold</em> on all my main body text. I've tried the classic <code>font-weight: normal</code> and <code>opacity: 0.99</code> with no luck. </p>
<p>After some major goggling around I've found there's a special CSS property that addresses this namely : <code>text-stroke</code>. The <a target="_blank" href="http://css-tricks.com/beefing-up-dull-text-in-webkit/">irony <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> : the article referencing this was trying to replicate the exact opposite i.e. making text render in Webkit browsers in a faux bold style à la Firefox. </p>
<p>Playing a bit with the property in Chrome one can easily duplicate the FF rendering style with <code>text-stroke: 0.35px</code> and by setting it to <code>0px</code> we practically reset it ergo using the same in FF will reset its rendering. Sadly as you can see in this lovely table by <a target="_blank" href="http://caniuse.com/text-stroke">caniuse <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> Firefox and Opera don't support it, well, Opera by going the Webkit way, it <em>will</em> support it soon. </p>
<p>How about Internet Explorer ? Good question indeed ! and since IE10 is out for some time I updated my old version 9 (it needed a restart of course) and fired it up. Results : <em>horrendous</em> text rendering and a very snappy experience.</p>
<p>I'll probably do some testing (all of this was done on Windows) on Linux and OS X soon, there I hope/should get more consistent results. </p>
<p>There's also: </p>
<pre class='highlight'>css
-webkit-font-smoothing: none;
-webkit-font-smoothing: antialiased;
-webkit-font-smoothing: subpixel-antialiased;
</pre>
<p>yet it doesn't seem to do much. </p>
<p>It seems that font rendering is <em>not</em> consistent at all under the Windows platform, I reckon some of these problems are also due to the hardware acceleration implementation. I really dislike how Firefox renders fonts via the CSS <code>@font-face</code> property (and yes the Verb typeface is optimized for web). </p>
<p>The issue is clearly visible when using font sizes in the range of 16 ~ 32 pixels. On smaller sizes the effect is actually useful as it makes the text more readable.</p>
<h2>Update № 1</h2>
<p>There's a simple fix for Firefox : detection is done via JavaScript and it just adds a class to the body element, then we can do :</p>
<pre class='highlight'>css
.firefox_is_bad section p { opacity: 0.75; }
</pre>
<p>That's just a joke I still love Mozilla's browser. </p>
<p>The code for easily detecting Firefox :</p>
<pre class='highlight'>coffeescript
is_firefox: ->
if window.mozInnerScreenX is undefined then false else true
</pre>
<h2>Update № 2</h2>
<p>Status on OS X : same issue yet the native antialiasing is somewhat better compared to the win platform. </p>
<p>The <code>-webkit-font-smoothing</code> css property seems to work here in Chrome the rendering looks like :</p>
<ul>
<li><a target="_blank" href="https://dl.dropbox.com/u/145562/none.png">none <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://dl.dropbox.com/u/145562/antialiased.png">antialiased <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
<li><a target="_blank" href="https://dl.dropbox.com/u/145562/subpixel-antialiased.png">subpixel-antialiased <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></li>
</ul>
<p>As one can clearly see using <code>-webkit-font-smoothing: antialiased;</code> renders the text best, somehow I was living under the impression that subpixel antialiasing would render better.</p>
<p>Hopefully this will get fixed at some point. </p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/52023-11-05T17:16:02Z2023-11-05T17:16:02ZOn unnamed abstracts, entities and happiness<p>When I look upon my day to day behavior the pattern that pops out is that of abstracted sets of ideas interchanging one another or making connection to other entities, bringing them in the foreground, into my field of subjectivity.</p>
<p>We try to to make perception ours thus abstracting it away in nicely grouped entities that can relate to one another. I'm doing this daily e.g when I open my browser and visit a webpage, what I'm actually doing is accessing an abstracted entity from my memory : a browser, a webpage, the Internet.</p>
<p>The issue here is that a subjective quotient comes into play that creates leaky abstractions. Reductionist views in which details dissolve without a trace, one could argue that by themselves abstractions can be viewed as a reductionist view of perception or better yet : semantic compression of streaming information.</p>
<p>We must draw a line between what a “good” abstraction would involve and<br>
a leaky one would dissolve. Seems like we have more questions than facts.<br>
Looking from another angle and replacing the "good" with the standard<br>
definition of utilitarianism :</p>
<blockquote>
<p><em>Utilitarianism</em> is a theory in normative ethics holding that the proper course of action is the one that maximizes utility, specifically defined as maximizing happiness and reducing suffering.</p>
</blockquote>
<p>From this perspective a proper abstraction is one that maximizes utility (happiness could be a far product of this). Utility in the sense that while keeping semantic compression close to an ideal ratio our abstraction preserves its most important details; by contrast a leaky one would miss them which in relationship with other entities this would cause wrong interpretations and thus unhappiness. </p>
<p>Getting back to reality: all abstractions are leaky, the important thing is not to miss those capital details that could blur everything up. Our perception is by definition subjective but we also apply a semantic compression to different chunks of it to be able to easily work with them.</p>
<p>This leads to another layer of subjectivity, the key is that we should be eternally vigilant.</p>
<ul>
<li><a target="_blank" href="http://utilitarianphilosophy.com/definition.eng.html">Utilitarianism 1 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - a much better description</li>
<li><a target="_blank" href="http://en.wikipedia.org/wiki/Utilitarianism">Utilitarianism 2 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - quote source</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/192023-11-05T17:16:02Z2023-11-05T17:16:02ZOn writing artisanal code<p>Every artisan at a certain point in time just stops and starts thinking about the inner-workings of his craft. He ponders on the whole process from an Outside while trying to make connections between apparently dissimilar entities that his craft is made of.</p>
<p>One might argue that this is a purely subjective endeavor: well, without any formal applicable theories it certainly is ! yet this doesn’t mean it cannot spark insights.</p>
<p>Coding is a very elusive mixture, it involves formal rules (the language), it can be mixed or even expressed via mathematical modeling and it’s also a first-class subjective practice. Coding is thus artisanal because we have the metaphor of shaping an abstracted real-world idea into another realm. </p>
<p>Code is ephemeral, it is driven by a set of semantics that must be transmitted. We can see it as a machine, yet one that must be plugged into another machine: the artisan himself, together they create meaning.</p>
<p>The issue with this is that meaning is hardly quantifiable: it depends on a transient object -> the mind that interprets it thus code is an incomplete little machine. </p>
<p>The question rises: what characteristics of code have enough in common with all minds that can form plateaus of recognizable values ? Well, if code conveys meaning, we want code that is expressive so that is able to convey its creator semantics to any reader or to put it another way : we want to maximize the function of adherent readers. </p>
<p>OK, what makes code expressive ? Looking at its form we can have code that is verbose versus code that is succinct. How do we choose which one is better ? We might say that it depends on the code but think about this: let’s say we have two versions of the same implementation of a solution to a problem, now: giving that they have the same quotient of conveying meaning which one we choose ? The answer is clear: the succinct code but only when the quotient approaches the idealized value of one. </p>
<p>How we maximize this quotient of conveying meaning ? I’ll ponder some more on this.</p>
<blockquote>
<p>“It helps to have a language that is like molding clay rather than carving stone.” - Paul Graham</p>
</blockquote>
Marian Posăceanutag:marianposaceanu.com,2005:Article/282023-11-05T17:16:02Z2023-11-05T17:16:02ZBuzzwords and manifestos<p>Do we really need them ? I mean sometimes I ask myself what’s the point of all the so-called ways to get things done or tons of guides for getting you to be a “better” you, like NLP, the secret of life and all that stuff.</p>
<p>To quote Nassim N. Taleb:</p>
<blockquote>
<p>“I went to a happiness conference: researchers looked very unhappy” - Nassim N. Taleb</p>
</blockquote>
<p>This really strikes me as big problem of modern society, maybe is something related to herd-mentality, we want to be stupid and not believe or motivate ourselves by the sheer power of our will. We suffer from a disease: the laziness of the will, gone is the will to power (or any other philosophical system that puts you in control of yourself, like existentialism for a change), nowadays we have a new direction: will to brainwash, will to not have a will. Is really sad and I find myself in the same situation too from time to time, yet solving half of the problem is realizing that you have it.</p>
<p>I think therefore I might be wrong: let’s just say, for the sake of the argument, that all of these systems are in fact useful. They might guide to a better path, yet the problem is that it is not your path, someone else created it to fit as many of <em>you’s</em> as possible; generalizing and having a reductionist view of reality makes it inauthentic for the individual. I’m not saying that everything else that’s not ours is irrelevant or not useful, no, what I mean is that by choosing what we like from the outer world and mashing all of that in something we can use that makes sense to us is far more effective than blindly fallowing some program and in the end realizing that nothing had changed.</p>
<p>So let’s drop the buzzwords or fallowing blindly someone else system without taking it through a critical hell ride in our minds.</p>
<p>Good stuff:</p>
<ul>
<li><a target="_blank" href="http://www.themadtolive.com/wp-content/uploads/2010/11/A-Kick-In-the-Pants.pdf">A Kick In the Pants <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - a great pdf</li>
<li><a target="_blank" href="http://www.themadtolive.com">via <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - themadtolive.com</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/82023-11-05T17:16:02Z2023-11-05T17:16:02Z The inherent entropy in our lives: to resist or to... <p>I’ve started thinking about it after I read this <a target="_blank" href="http://forge38.com/blog/2010/07/fight-entropy-keep-moving-forward">article <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> and this tweet got me going for a couple of days: “My whole life I’ve been fighting entropy, maybe it’s time I stop fighting” by <a target="_blank" href="http://twitter.com/#%21/stevenbristol/status/15960363246">@stevenbristol <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. I love stuff like this, makes me ponder on what would be the best way one could choose and what would the solution imply, let’s say, in an empirical way.</p>
<p>Firstly, one must define entropy, so here’s my cherry picked definition:</p>
<blockquote>
<p>“entropy is a measure of the uncertainty associated with a random variable.”</p>
</blockquote>
<p>Of course there are more, but I like this one because it works almost flawlessly as a metaphor for life itself: that random variable = life, entropy being the hazard (one should take this with a grain of whatever he/she likes, it’s merely a <em>reductionist definition</em> for the purpose of this article).</p>
<p>So let’s see... at the surface I see two possible solutions: to fight entropy (not necessarily fight it but more in a way of how a sailor doesn’t fight the storm, he embraces the flow of the weaves and the wind so he can make it safely to the other side) or to go with it. I just realized that I’ve been fighting entropy in a bad way, I’m always trying to apply structure to my life and to everything that I do, like work, yet most of the time something like "random(life)" happens and all that abstract structure that exists in my head goes away in a blink of an eye.</p>
<p>There’s nothing wrong with having structures in your life, it’s a good thing, but one (especially me) must realize that it doesn’t always work out and high expectations go hand in hand with high delusions and the latter ones, hurt like hell. Going back to my point: one must embrace the flow of entropy, yet with a small nuance, not in a deterministic way, I mean, not in the way of letting our lives be driven by sheer randomness of events (that’s actually the second solution: to go with it), that’s bad. I find it hard to define it.</p>
<p>Why is it bad to go with entropy, to embrace it and let one life be driven by it ? It’s pretty obvious, I think: we lose all little control we have on our lives. It’s clear we cannot be in full control of external things, yet at least we can be in full control of how we react to entropy (I think that’s the key I needed for the previous paragraph).</p>
<p>The solution: one must learn to be in control of his/hers reactions to entropy. How do we do that ? It varies from person to person, one might code an app for that or someone else (like me) might just realize this and try to apply it from now on.</p>
<p>In the end, I wish you all the best and a Merry Christmas.</p>
<p>Bibliography:</p>
<ul>
<li><a target="_blank" href="http://en.wikipedia.org/wiki/Entropy_%28information_theory%29">1 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - wiki definition</li>
<li><a target="_blank" href="http://forge38.com/blog/2010/07/fight-entropy-keep-moving-forward">Fight Entropy! Keep Moving Forward! <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - nice article</li>
<li><a target="_blank" href="http://twitter.com/#%21/stevenbristol/status/15960363246">@stevenbristol <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - he started it all !</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/12023-11-05T17:16:02Z2023-11-05T17:16:02ZUsing Firebug as a scalpel, yet not for web development<p>Needless to say, I’m an avid user of <a target="_blank" href="http://getfirebug.com/"> Firebug <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, let’s face it: without it, web development would suck big time, yes we do have other variants but firebug remains the status quo, for me at least. Yet this is not an article about how to develop web apps with Firebug, no, is an article about how one can use it to have a little fun and be more practical.</p>
<p>Everyone hates ads, well maybe <em>hate</em> is a bit too much, everyone dislikes ads, I know I do. In Firefox we have the <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/1865">AdBlock Plus <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> extension. Does the job pretty nicely, yet nicely, doesn’t fit my taste, why ? you may ask. Well firstly, its not that fast and breaks my development by taking me out of the <em>flow</em> (it does that by making Firefox and the pages I visit slow - this is an empirical observation, it’s been a while since I’ve used the extension) and secondly because</p>
<blockquote>
<p>on some sites I actually want to see the ads and maybe even click the darn things so I can show my support</p>
</blockquote>
<p>(and that’s a big chunk of the sites I visit daily).</p>
<p>Going back on track: today we use web apps for a considerable time: I open ad-supported web apps in the browser and keep them opened for the entire session (since I rarely close Firefox, that could mean a full day, or even more - I use hibernate). What I don’t like about them ? The ads of course, now this may come in conflict with the previous paragraph but I’ve got a good reason for killing them ads: most of the time they’re flash and they change at intervals of time, problem with that and Firefox in long sessions is that it memory leaks like crazy (it’s something related to the extensions, I reckon) and Flash and those ads seem to help a lot.</p>
<p>By now, it’s pretty obvious: I kill them with Firebug. How ? Pretty easily, firstly I find the node, the container for the iframes or whatever they use, and delete that node using Firebug since the node doesn’t exist anymore, gone are the ads. One may ask “But you do this every time ? Why don’t you use some extension like greasemonkey or something to do that for you ?” My answer: I have long sessions and I only do that for 1-2 sites that I keep opened all the time so it doesn’t bother me, also using <a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/748/">Greasemonkey <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> or something similar would add up to the resources that Firefox is using, probably getting me somewhere near the ad-block version.</p>
<p>In conclusion, Firebug can be useful for something else then web development.</p>
<p>Bibliography:</p>
<ul>
<li><a target="_blank" href="http://getfirebug.com/">Firebug <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - what I use</li>
<li><a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/1865">AdBlock Plus <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - what I used to use</li>
<li><a target="_blank" href="https://addons.mozilla.org/en-US/firefox/addon/748/">Greasemonkey <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - what I need to test some more</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/62023-11-05T17:16:02Z2023-11-05T17:16:02ZProgramatica 2010 after thoughts<p>Yes, I’ve attended one more conference <a target="_blank" href="http://www.agora.ro/conferinta/programatica-2010"><em>Programatica 2010</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>, this one was axed on programming. It started with some interesting to not so interesting presentations of the partners. What I’ve loved about them, was that they contrasted each-other pretty nicely to a point when it was actually funny.</p>
<p>I’ve observed something interesting about the big names, like IBM, Microsoft and Oracle: they’re starting to converge their developer tools to open-source inspired models. How ? Well, let’s take their presentations one by one: <a target="_blank" href="http://www.oracle.com/technetwork/developer-tools/adf/overview/index.html"><em>Oracle</em> ADF <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - this is an interesting framework for developing enterprise class applications, for what I’ve seen is a set of extensions to JavaEE in the vein of the <a target="_blank" href="http://www.springsource.org/">Spring Framework <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> this is nice and all that but I don’t really like uber-complex IDE’s (they might appear to save you time but you have to learn all the intricacies of how they work, also they might have bugs so my question is: Why spend time on finding solutions to the IDE bug when I could find solutions to the actual bugs in my application ?)</p>
<p>Next in line: IBM Jazz open-source platform that can integrate their well-known tools (like <em>RUP</em>) and all those nice pre-made processes for requirements, testing, developing, artifacts management and all that but with a nice open-source twist on them while also trying to make them flexible in an <a target="_blank" href="http://agilemanifesto.org/">Agile <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> way. The path here its obvious, again open-source is the root of the big change, it’s an adaptation.</p>
<p>And lastly but not last we have Microsoft with their <a target="_blank" href="http://www.microsoft.com/windowsazure/"><em>Azure</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> cloud platform (I kinda like it, should scale pretty well and its not that pricey compared to the rest, of course I haven’t tested it so all that might be just gibberish) - they support open-source development in <a target="_blank" href="http://www.codeplex.com/"><em>SourceForge</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> kind of way, all the community projects are hosted there - like PHP SDK for IIS.</p>
<p>On Azure you can pretty much run anything from java to ruby and of course their beloved .NET. The problem with it is that if you want to run a really small app, you don’t really have a plan for that (besides trials and a free limited to 25 machine hours version), they start at 59$ or something like that, but you get 20 instances which is nice for a big app, one might guess. Also nice, is that their platform is <em>mostly</em> complete and somehow <em>on par</em> with clouds like Rackspace or Heroku.</p>
<p>Ok, before finishing the post, I must write about <a target="_blank" href="http://lucadezmir.com/interviuri/adrian-amariei/">Andrian Amariei <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>’s speech about how programmers tend to see things and sometimes the whole world in a restricted dualistic way: black or white, 1 or 0,</p>
<blockquote>
<p>“We’re being held captive between the walls of our own mind”</p>
</blockquote>
<p>The thing is that the real world is made of shades of grey and not absolute truths, we must keep that in mind and wake up !</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/112023-11-05T17:16:02Z2023-11-05T17:16:02ZA few words on frontend performance optimizations<p>I love optimizing stuff, sometimes I even break the rule (when I have time) and optimize just for the sheer fun of it. I’ve been using on my blog <a target="_blank" href="http://requirejs.org/"><em>RequireJS</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> for some time but the last days I’ve rewritten the whole init script to use <a target="_blank" href="http://labjs.com/"><em>LABjs</em> <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a></p>
<blockquote>
<p>“Why would I do such heresy ?”</p>
</blockquote>
<p>Well, mostly because I din’t liked the way RequireJS works with jQuery (this might be a bit outdated): I was loading up a custom file with jQuery and RequireJS bundled together then I would load up other js files <em>normally</em>.</p>
<p>With LABjs I only have one js file loading, that being LABjs itself, after that I load jQuery and GA via <em>Google CDN</em>, which is pretty fast: the DOMContentLoaded event triggers a bit more quickly now. This is good stuff to know & use for a busy site with lots of js.</p>
<p>Hopefully at some point I will post some graphs with some benchmarking. The good stuff is that before jQuery 1.4, you couldn’t have the LABjs script first then load jQuery; that’s because of the way jQuery did the check if the DOM had loaded, yet now they’ve fixed that and all seems to play nicely. </p>
<p>Next step ? a failsafe if the CDN breaks or takes too long to serve the js files, I’ve researched the code a bit and it’s pretty easy, I shall test it soon.</p>
<p>Biography:</p>
<ul>
<li><a target="_blank" href="http://requirejs.org">RequireJS <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - before</li>
<li><a target="_blank" href="http://labjs.com">LABjs <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - now</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/272023-11-05T17:16:02Z2023-11-05T17:16:02ZThe frontend backend debacle<p>I’m really starting to get fed up with this useless separation. (<em>Warning</em>: strong personal opinions, based on arguments fallowing).</p>
<p>Ok, it’s not <em>useless</em>, I get the idea in a big team, separation of concerns, better productivity and all that. That’s good and I’m all for that, makes things faster (in the big picture at least). Anyway, what I don’t get is why people that do programming, need to bracket themselves into this kind of name spacing.</p>
<p>Whether you’re programming in JavaScript, php, ruby or java or even LOL-code in the end you are still a programmer. If you think that calling yourself a <em>frontend _, _backend</em> or <em>middle-end</em> developer makes you somehow better, I’ve got news for you: it doesn’t</p>
<blockquote>
<p>“It just shows that you can’t actually handle programming in a true sense”</p>
</blockquote>
<p>I’m not saying being a js developer is easy, no way! Actually starting to learn the concepts behind js made me a better programmer and helped me getting into more advanced stuff like ruby or clojure. Yes, we have the DOM model and all that stuff, but really, one can abstract that using a library and still write advanced UI’s with little or no performance problems. And don’t get me started on html and css, anyone can learn that, if you can write a hello world java program then, my friend, css and html is a piece of cake.</p>
<p>Baseline ? A true programmer should be able to code in almost any language. If in your team you work as a <em>backender</em> or <em>frontender</em>, that’s ok, but that doesn’t mean you should not know css, html or js or vice-versa, other programming languages and concepts.</p>
<p>You must know the basics and stay up to date, yes it’s not easy, so deal with it and lets stop hiding behind <em>name spaces</em> ok ?</p>
Marian Posăceanutag:marianposaceanu.com,2005:Article/222023-11-05T17:16:02Z2023-11-05T17:16:02ZHow to Web Conference, random thoughts, mostly live<p>Sadly, today I’ve arrived a bit late, where "a bit" means a lot; I’vevolatile and utopic place most of the time.</p>
<p>In very few domains you can take an idea and with small or no resources (<em>money</em>) and bring it alive and running. I mean, actually thinking about it, how can’t that be exciting ?! Having an idea and turning pure thoughts into something that can actually reach people and the real world... that’s just mind boggling.</p>
<p>I’ve stumbled over a new concept: "life style business", apparently you can have two kinds of businesses (assuming they will work): you can go big, invest a lot, get international and all that stuff or you can keep it small as a life-style, you live for your business you _burn _your thoughts making it better and better, I really like that idea, it’s inspiring.</p>
<blockquote>
<p>“Some heavily 37signals inspired ideas”</p>
</blockquote>
<p>Also another interesting concept: <em>bootstrapping</em>. More on that in another article (it’s problably going to be a Rails article)</p>
<p><em>And last update on how to web</em>: it was awesome and it’s not just about the conference it’s about the great people I’ve met or watched in full action, if they can do it then we can do it also, it’s all about passion and loving what you do and never taking yourself to seriously, self-irony from time to time its great, nobody is perfect, perfection is not the goal, accepting the imperfection and making the best of them is the key.</p>
<p>All in all, great experience, kudos !</p>
<p>Biography:</p>
<ul>
<li><a target="_blank" href="http://37signals.com/rework/">rework <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - this one is a must read</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/152023-11-05T17:16:02Z2023-11-05T17:16:02ZTomorrow is the first day of How to web 2010, this should be fun<p>Just got in Bucharest, tomorrow I’ll be at <a target="_blank" href="http://www.how-to-web.net/">How to Web 2010 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a>. Hope it’s going to be good, the presentations look juicy.</p>
<p>I hope I’ll meet some inspiring people and hopefully something to burst some new ideas or perspectives about the web. All in all, its not such a simple subject like: "oh, so you do web stuff ? isn’t that nice", the whole area is getting more and more complex by the day.</p>
<p>That’s not a bad thing of course, the problem is coping with all that change coming in small bits at high speed. Let’s look at this problem from a programmers perspective, firstly we have the basic stuff, algorithms, patterns, good problem solving skills, testing and all that, but new technologies emerge at a fast pace. How can we cope with all that change ?</p>
<blockquote>
<p>“oh, so you do web stuff ? isn’t that nice and simple...”</p>
</blockquote>
<p>Some time ago I was thinking that having a good/great understanding of the basics would suffice, well experience has proved me wrong. Yes, basics and everything I’ve enumerated are very important, but to actually be able to work into this environment you must be up to date (of course I’m not saying you should know all the HTML5 unfinished specifications, that’s just plain over-voltage).</p>
<p>Returning to the subject, conferences like this are good, they catch all those new emerging ideas and spread them in big chunks at a small speed so we can get a picture of the whole thing, it’s like a snapshot of the state of the web (too much ?); well the next conference its going to be more specific.</p>
<ul>
<li><a target="_blank" href="http://www.how-to-web.net">How to web <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - conference link</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/162023-11-05T17:16:02Z2023-11-05T17:16:02ZInstalling a rails mysql stack on my laptop was a bit tricky<p>I’ll keep this short: firstly I’ve downloaded the ruby windows installer from <a target="_blank" href="http://rubyinstaller.org/downloads/">here <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> , at the time of writing the version was _1.9.2-p0. _The problem with this one is that ruby crashes into oblivion from time to time (mostly after lots of page refreshes); after a googler search I’ve found out it’s a windows bug (yeah on *nix works like a charm) so not much really more to do except waiting for the next release, compilling myself the latest version or if you just want to be safe just get the 1.8.7 or .6 release, should work just fine (that’s what I have on my desktop with Rails 2.3.5 and works really great - for developing purposes.</p>
<p>Ok, time to install rails: _gem install rails -v=2.3.5 -no-rdoc -no-ri _(to be noted I’m using an older version you can skip the -v to install the latest Rails 3). The last two parameters should skip installing the offline documentation (I don’t really use that, so why bother installing all those small files...)</p>
<p>Next comes the mysql part, this was fun: the normal way to do it is to install <em>gem install mysql</em>, have your <em>mysql/bin</em> (that’s where <em>libmySQL.dll</em> resides) into windows path variable and hope everything works just fine. If it doesn’t, well you can try the classic hack of putting (and by that I mean copying that moving the file) libmySQL.dll intro <em>ruby/bin</em> folder. Needless to say, none worked on my setup.</p>
<p>My way: <em>gem install mysql2</em>, after I modified my database.yml to use the adapter: it worked ! Kudos to brianmario for coding that.</p>
<p>All done !</p>
<p>Biography:</p>
<ul>
<li><a target="_blank" href="http://rubyinstaller.org/downloads/">Ruby 1.9.2-p0 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - for windows</li>
<li><a target="_blank" href="http://github.com/brianmario/mysql2">mysql2 <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - source code on github, again kudos to brianmario</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/92023-11-05T17:16:02Z2023-11-05T17:16:02ZHow I speeded up my browsing experience by a really nice margin<p>From time to time I like to optimize a bit my Windows machine, yet mostly all I do is fine tunning, nothing really spectacular. This time while I was browsing the net and thinking about one of my old nags (browser performance loading several tabs, to more exact: Firefox loading up 20+ tabs) I realized something really simple.</p>
<p>Firstly though, let me explain the problem. When Firefox loads up with a lot of tabs opened since the last session (I leave tabs opened using SessionManager, I use them as a to do list for the next day) it takes very long (30-90seconds) to load them all up, mostly because firefox is reading unchanged files from its cache.</p>
<p>Back in the day, I’ve tried to solve this problem by saving the cache on a speedy USB stick (this way I would get much better random access time of small files but the sequential speed was really low).</p>
<p>As was I saying, while searching the interwebs I’ve stumbled on a nice little <a target="_blank" href="http://memory.dataram.com/products-and-services/software/ramdisk">utility <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> that can create RAM drives, needless to say my old idea just got better, what about a RAM drive especially for Firefox and IE cache ? It doesn’t need to be big (50Mb each would be enough) and I don’t really care about the safety of the date stored there (after all if the cache gets corrupted or lost, the browser will just redownload or a trusty CTRL+F5 would fix the problem).</p>
<blockquote>
<p>It was sitting at the back of my mind for too long</p>
</blockquote>
<p>Configured my Ram Drive, moved firefox and IE cache folders there and then reloaded my 20+ tabbed ff. Results ? Well, just next to amazing, everything runs snappy, but now I’ve found another bottleneck: my CPU.</p>
<p>Biography:</p>
<ul>
<li><a target="_blank" href="http://memory.dataram.com/products-and-services/software/ramdisk">Ram Drive <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - content management system</li>
</ul>
Marian Posăceanutag:marianposaceanu.com,2005:Article/172023-11-05T17:16:02Z2023-11-05T17:16:02ZBuilding a small blog cms in rails<p>Yes, building a blog cms in rails is apparently very simple, well to be true it’s simple if you want something really limited like a post model, a couple of static pages, controllers and one for the contact form and you’re settled. Actually for something like this one can use <a target="_blank" href="http://www.sinatrarb.com/">Sinatra <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> (not to say that Sinatra is better for small applications, but you really don’t need all the Rails stack, of course Rails 3 is more modular and everything, but still).</p>
<p>That’s why the cms (I really dislike this word) backing up my personal site it’s not going to be something trivial, I’ve actually based it on more general cms I’ve been using for projects I work on.</p>
<blockquote>
<p>“It is better to take many small steps in the right direction than to make a great leap forward only to stumble backward.”</p>
</blockquote>
<p>From the vanilla state, I’ve got <a target="_blank" href="http://en.wikipedia.org/wiki/Role-based_access_control">RBAC <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> implemented (keeping in mind that I’m the only one posting articles on the site it is a bit useless) - this will cost some _small _performance in the admin but having it online will let me test it and improuve it for actual usage in real world.</p>
<p>Biography:</p>
<ul>
<li><a target="_blank" href="http://fe.com/">CMS <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - content management system</li>
<li><a target="_blank" href="http://www.sinatrarb.com/">Sinatra <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - a DSL for quickly creating web applications in Ruby with minimal effort</li>
<li><a target="_blank" href="http://en.wikipedia.org/wiki/Role-based_access_control">RBAC <sup><svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="13" height="13" viewBox="0 0 13 13"><path fill="#f30600" d="M0.48 10.38q-0.132 0.12-0.228 0.12h-0.060q-0.192-0.048-0.192-0.228 0.096-2.58 1.656-4.056t4.344-1.464v-2.256q0-0.156 0.144-0.216 0.132-0.072 0.264 0.024l5.496 4.248q0.096 0.072 0.096 0.192t-0.096 0.204l-5.496 4.248q-0.060 0.060-0.156 0.060-0.036 0-0.108-0.036-0.144-0.060-0.144-0.216v-2.256q-1.956 0-3.408 0.408t-2.112 1.224z"></path></svg></sup></a> - Role Based Acces Control</li>
</ul>
Marian Posăceanu