<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>eyt* Blog</title>
<description>eyt*'s Thoughts, Experiences, and Readings</description>
<link>https://www.eyt.ca/blog/</link>
<generator>eyt.ca Blog</generator>
<copyright>Copyright 2004-2023 by Eric Y. Theriault. All Rights Reserved</copyright>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/145/</guid><title>IBM Think 2023</title><link>https://www.eyt.ca/blog/145/</link><category>Software</category><pubDate>Mon, 22 May 2023 03:08:50 GMT</pubDate><description>&lt;p&gt;In early May, I had the opportunity to attend IBM Think in Orlando. This is the first conference I attended in a while and wanted to share a couple thoughts. This blog post is mostly based on my Mastodon thread..&lt;/p&gt;&lt;p&gt;I think the three announcements that was showcased is:&lt;/p&gt;&lt;ul class=&apos;para&apos;&gt;&lt;li&gt;Hybrid Cloud is the defacto standard now &amp;#8212; you can no longer live in one cloud and they have tools to help, including &lt;a href=&apos;https://www.ibm.com/products/hybrid-cloud-mesh&apos;&gt;Hybrid Cloud Mesh&lt;/a&gt; which was unvieled.&lt;/li&gt;&lt;li&gt;We have just crossed a new era in AI with generative models and &lt;a href=&apos;https://watsonx.ai&apos;&gt;watsonx.ai&lt;/a&gt; is IBM&amp;#8217;s approach to this, separating out the Data, AI, and Governance.&lt;/li&gt;&lt;li&gt;And Quantum computers are coming &amp;#8212; you need to start to prepare now!&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;For me personally, there are a few things I learned or was re-emphasized:&lt;/p&gt;&lt;ul class=&apos;para&apos;&gt;&lt;li&gt;10% of all energy consumption is for data centers &amp;#8212; I didn&amp;#8217;t know this stat before, but definitely something we can work to bring down and and have more sustainable data centers and nnew laws in EU that will be similar to GDPR will require organizations to start reporting on this, both for their own consumption, but their partners. This seems like a huge undertaking, and while this is a great improve what gets measured, this will be a huge effort (and opportunity) for startups.&lt;/li&gt;&lt;li&gt;I have been hearing about quantum computers coming since I was a kid &amp;#8212; IBM has about 20 of them now and they are expected to really be available for purchase in 2030. That&amp;#8217;s cool &amp;#8212; but the part that makes that scary is that cracking our current encryption codes from years to hours, and so in addition to threats of real-time attacks, the real threat is the store-and-decrypt-when-Quantum-is-ready. There&amp;#8217;s some new Quantum safe encryption is coming &amp;#8212; ready yourselves for the next Y2K-type rush!&lt;/li&gt;&lt;li&gt;I really enjoyed the talk by &lt;a href=&apos;https://en.wikipedia.org/wiki/Megan_Smith&apos;&gt;Megan Smith&lt;/a&gt;, particularly her comment on how people are getting coded out of society because of bad AI. There&amp;#8217;s a lot of things she covered in this talk, but the bigger take aways for me was the DEI ones, particularly with AI models getting formed &amp;#8212; we must teach them to not have biases and to not infer &amp;#8220;facts&amp;#8221; based on a lack of data.&lt;/li&gt;&lt;li&gt;And for my HPC friends, IBM also talked about &lt;a href=&apos;https://research.ibm.com/blog/AI-supercomputer-Vela-GPU-cluster&apos;&gt;IBM Vela&lt;/a&gt; &amp;#8212; I still miss playing with the SGI Onyx!&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;And that&amp;#8217;s my quick summary of what piqued my interests the most at IBM Think &amp;#8212; hope you find some value in this post.&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/144/</guid><title>Digital Music Shops</title><link>https://www.eyt.ca/blog/144/</link><category>Music</category><pubDate>Fri, 31 Mar 2023 22:18:31 GMT</pubDate><description>&lt;p&gt;I have been super quiet in the last several years on this blog and social media, but trying to make a little time this year to do a few blog posts. I have a backlog of things I want to do, but first, I thought I would start with a non-engineering topic.&lt;/p&gt; &lt;p&gt;I have played piano since I was 8 but took a break after my kids were born until a few years ago. While I love acoustic pianos, being a software engineer, I&amp;#8217;ve always loved blending in technology, staying with my old Cakewalk and Yamaha PSR-500 configuration from the mid-90s.&lt;/p&gt; &lt;p&gt;Now that I&amp;#8217;m back, there are a ton of things that have changed in technology, but the key one for me is sheet music &amp;mdash; I no longer need to have a ton of books and flip through them like a madman or have a bunch of individual sheets and find creative ways to keep it together. Not only do you have tons of options for viewing sheet music, but you also have many options for organizing that music and annotating it.&lt;/p&gt; &lt;p&gt;Today, I&amp;#8217;ll walk you through my current setup and how I get my sheet music. In case it matters, I play mostly classical and various music I like throughout the ages &amp;mdash; it&amp;#8217;s sometimes an &amp;#8220;interesting&amp;#8221; mix. In future blogs, I&amp;#8217;ll discuss how I organize my music in my current setup. I&amp;#8217;ve noticed in many of my piano circles that my setup is more tech-focused than the paper solutions, so hoping that my take will help with this.&lt;/p&gt; &lt;h2&gt;Current Setup&lt;/h2&gt; &lt;p&gt;I currently have an &lt;a href=&quot;https://www.apple.com/ipad-pro/&quot;&gt;Apple iPad Pro 12.9-inch&lt;/a&gt; , which is a bit smaller than books, but not by much. It has a long battery life, is very stable (it won&amp;#8217;t crash during your performances), and carries a lot of music in a small package.&lt;/p&gt; &lt;p&gt;I use the iPad in portrait mode, which provides a larger view of the music, but you could use landscape mode and show two sheets of music. I just find it&amp;#8217;s too small to be useful. Some technology is being worked on to extend that iPad screen onto two iPads which can help this &amp;mdash; but really, I think what is more valuable is a pedal which, while isn&amp;#8217;t the same as having more music in front of you, does fit most of the same purpose. I use the &lt;a href=&quot;https://www.airturn.com/products/airturn-duo-500&quot;&gt;AirTurn Duo&lt;/a&gt;, which is quick to configure, and you can quickly turn pages &amp;mdash; assuming you aren&amp;#8217;t using the Una Corda and sustain pedal concurrently!&lt;/p&gt; &lt;p&gt;I recommend the &lt;a href=&quot;https://www.apple.com/apple-pencil/&quot;&gt;Apple Pencil&lt;/a&gt; so that you can annotate your scores just like you would with your paper copies, although I actually find the color and erasing options better than the paper alternatives.&lt;/p&gt; &lt;p&gt;In terms of software, I use &lt;a href=&quot;https://forscore.co&quot;&gt;forScore&lt;/a&gt;. This allows me to use the same library on my Mac, iPad, and iPhone &amp;mdash; yes, you read that right, the iPhone. I only do organization on my iPhone, but you can play music from it. This is super powerful, very usable for free, and you can unlock some additional features for a super affordable $9.99 a year. If anything, I would like to give them more money…&lt;/p&gt; &lt;p&gt;Before forScore, I used the Musicnotes app for about a year, which is good if most of your music is purchased from it, but it has a lot of limitations beyond that discussed below.&lt;/p&gt; &lt;p&gt;Before moving on to the next section, I will say that picking an app is the most critical part here, especially once you start to have a lot of music (reorganizing it in the new app is a pain!), and the hardest one is really the annotations! Once you have started using annotations extensively in many pieces, it&amp;#8217;s hard to switch. &lt;a href=&quot;https://newzik.com/en/&quot;&gt;Newzik&lt;/a&gt; is one that I have considered trying a few times, but outside of the more expensive subscription and relatively few differentiating features, the time to redo the folders and, more importantly, the annotations is just not worth it.&lt;/p&gt; &lt;h2&gt;Musicnotes&lt;/h2&gt; &lt;p&gt;The vast majority of my music is purchased via &lt;a href=&quot;https://www.musicnotes.com/&quot;&gt;Musicnotes&lt;/a&gt;. It has a good selection and is easy to use. When first using it, I would make sure that you look at many copies of the same piece of music before you buy one &amp;mdash; for example, I am not a fan of their Singer Pro versions, but that is my preference.&lt;/p&gt; &lt;p&gt;They offer a subscription, which I recommend if you plan to make regular purchases with them. In addition to some other capabilities, it gives you 15% off purchases and you can purchase Pro Credits. When not on sale, Pro Credits are about $4 per piece, and whereas most of your pieces after your discount are just under $5, so a better value &amp;mdash; this, of course, assumes you are purchasing them on the web; the app store is generally more as Apple has to take their cut…&lt;/p&gt; &lt;p&gt;In terms of the subscription, they have a Pro Premium plan, which for the first year makes sense, but after that, it feels expensive. Of note, in addition to 12 Pro Credits, it also gives you 12 free &amp;#8220;Musicnote Editions&amp;#8221;; this sounds great, but the selection of those is limited and, to me, not as interesting.&lt;/p&gt; &lt;p&gt;If you are into Concertos and longer pieces, I don&amp;#8217;t find Musicnotes as great for this. They usually only offer the theme or the individual movements or something that will add up quickly. &lt;/p&gt; &lt;p&gt;I started using Musicnotes way before I had an iPad, and I want to mention this because most pieces you can print out. So your investment is still worthwhile even if you decide to return to paper later. I&amp;#8217;d probably recommend saving the PDFs and printing a copy of the PDF, as some pieces have restrictions on how many times you can print them.&lt;/p&gt; &lt;p&gt;Lastly, they do offer a great IOS app. I used it for about a year and generally liked it. If most of your music is purchased from Musicnotes, it makes sense to use it. While it can import PDFs, it does not preserve those, so if you decide to change iPads in the future or use the Web app, you can&amp;#8217;t get to these anymore &amp;mdash; and even if you re-import them, they are not preserved in playlists. When I talk about my organization in a future blog post, this may make more sense.&lt;/p&gt; &lt;p&gt;That said, forScore has direct integration with Musicnotes, and once you&amp;#8217;ve connected it, new purchases can automatically download.&lt;/p&gt; &lt;h2&gt;Virtual Sheet Music&lt;/h2&gt; &lt;p&gt;My next place to shop for music is &lt;a href=&quot;https://www.virtualsheetmusic.com/&quot;&gt;Virtual Sheet Music&lt;/a&gt; (or VSM). It has a good selection, but you need to know how to find it, as its entire interface feels like a late &amp;#8217;90s website. They provide you with all kinds of pieces &amp;mdash; it has the concertos and longer works that Musicnotes doesn&amp;#8217;t have and is beautifully printed, and sometimes has versions of things that are better than Musicnotes in my experience, and pricing is better in many cases.&lt;/p&gt; &lt;p&gt;Virtual Sheet Music also has a subscription&amp;mdash;like Musicnotes, it offers you discounts, and I would recommend it if you purchase things regularly from the site.&lt;/p&gt; &lt;p&gt;I wouldn&amp;#8217;t recommend their app. Instead, forScore has a direct integration with it, and it is also super easy to export PDFs from VSM and get them to where you need them to be.&lt;/p&gt; &lt;h2&gt;Sheet Music Direct&lt;/h2&gt; &lt;p&gt;I find &lt;a href=&quot;https://www.sheetmusicdirect.com/en-US/&quot;&gt;Sheet Music Direct&lt;/a&gt; very similar to the content of Musicnotes or Virtual Sheet Music; however, it does have some content that the other two don&amp;#8217;t. For example, when I wanted the PDF version of &lt;a href=&quot;https://www.amazon.com/gp/product/0634069985/ref=ppx_od_dt_b_asin_title_s01?ie=UTF8&amp;amp;psc=1&amp;_encoding=UTF8&amp;tag=eyt0b-20&amp;linkCode=ur2&amp;linkId=0c57aa6e62e37f1621d378dc0426dc36&amp;camp=1789&amp;creative=9325&quot;&gt;Schirmer&amp;#8217;s Chopin Ballades&lt;/a&gt;, Sheet Music Direct was my only choice for this particular copy.&lt;/p&gt; &lt;p&gt;While forScore does not have an integration with it, the PDFs exported from SheetMusicDirect slipped into forScore like a glove and required no metadata editing. I really loved this experience.&lt;/p&gt; &lt;p&gt;One of the things that SheetMusicDirect has is a subscription model where you can get all of the music you want without purchasing it. This sounds great, but I feel it is more expensive over time. I have no data here, but daily, I tend to play the same 4 things every day that I am working on for the last year, and if I still have time (that&amp;#8217;s a big if), I&amp;#8217;ll pick up a couple other things.&lt;/p&gt; &lt;h2&gt;Henle Library&lt;/h2&gt; &lt;p&gt;Another app and store I love is the Henle Verlag Music Library app. There are two things I love about this app. First, it is more like when you purchase the book; it will include the information around the piece, such as the reception of the work, notes, sources, editions, etc.&lt;/p&gt; &lt;p&gt;Second, I love the customization it provides. Some pieces will have a couple different options for fingerings, and you can pick which one you want or none if you are a power pianist. You can change the background color, customize the staff spacing, etc. And then, once you have it just like you like, you can also export it as a PDF into other apps like forScore.&lt;/p&gt; &lt;p&gt;Classical Music Repositories&lt;/p&gt;&#xa;&lt;p&gt;Let&amp;#8217;s face it: lots of classical music is (or should be) in the public domain, so some of it you can get for free or at super low prices.&lt;/p&gt; &lt;p&gt;The first one I&amp;#8217;ll mention is &lt;a href=&quot;https://imslp.org/&quot;&gt;IMSLP.org&lt;/a&gt; which has a bunch of recordings and PDFs of various pieces. I&amp;#8217;m not a lawyer, so I will leave it to you to read the fine print to ensure it is legal, but I have used some copies from here. The quality generally varies; some are personally scanned versions with hand-written notes, while others are professional copies.&lt;/p&gt; &lt;p&gt;The next one is &lt;a href=&quot;https://www.pianostreet.com/&quot;&gt;pianostreet.com&lt;/a&gt; which, if you have a subscription, you can access their sheet music library. I have found a couple pieces here, but I&amp;#8217;ve not used them enough to justify the subscription.&lt;/p&gt; &lt;h2&gt;Finding other Music&lt;/h2&gt; &lt;p&gt;If you are not finding what you are looking for in one of the above places, take it to your favorite search engine and start looking for the piece. I have found a couple pieces on &lt;a  href=&quot;https://www.noteflight.com/&quot;&gt;Noteflight.com&lt;/a&gt; or &lt;a href=&quot;https://musescore.com/&quot;&gt;MuseScore.com&lt;/a&gt;, but your mileage will vary.&lt;/p&gt; &lt;p&gt;If you do not find it there, take a look at &lt;a href=&quot;https://play.google.com/books&quot;&gt;Google Play Books&lt;/a&gt; and see if they have a version. You can either use the Google Play Book App on your iPad or, with care, you can export the PDF from a desktop computer. Note that many of the copies of the books I&amp;#8217;ve seen on Google Play have issues in their rendering; you can file a ticket with Google, and well, I&amp;#8217;ll let you know if they resolve these eventually.&lt;/p&gt; &lt;h2&gt;Importing the Physical&lt;/h2&gt; &lt;p&gt;I much prefer importing a PDF from one of the other mechanisms in this article; however, if you have a book you love or can&amp;#8217;t find it online, you can scan it.&lt;/p&gt; &lt;p&gt;ForScore can scan in music, but I&amp;#8217;ve never used it. I use &lt;a href=&quot;https://www.timperlabs.com/keyscore/&quot;&gt;KeyScore&lt;/a&gt; instead. You point your camera at a piece of music, which will automatically line up most of your music, and you can even play a sample of the piece! Once you are happy with your importing, I export it to a PDF and bring it into ForScore.&lt;/p&gt; &lt;p&gt;If you subscribe to &lt;a href=&quot;https://www.pianistmagazine.com/&quot;&gt;Pianist&lt;/a&gt; or similar publications with sheet music in their app, I take screenshots of the music and use &lt;a href=&quot;https://sheetmusicscanner.com/&quot;&gt;Sheet Music Scanner&lt;/a&gt; to assemble those images into a PDF. Once you load the app, tap Import, select Photos, and import each page individually. When you are done, export it into a PDF.&lt;/p&gt; &lt;h2&gt;Other forScore Integrations&lt;/h2&gt; &lt;p&gt;&lt;a href=&quot;https://forscore.co/content-providers/&quot;&gt;ForScore integrates&lt;/a&gt; with a few other services that I do not use. To save you the time of searching for what types of music you love, I&amp;#8217;ve put together this list:&lt;/p&gt; &lt;table class=&quot;table&quot;&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://www.brileemusic.com/&quot;&gt;BriLee Music&lt;/a&gt;&lt;/th&gt;&lt;td&gt;Choral Music&lt;/td&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://www.presser.com/&quot;&gt;Presser&lt;/a&gt;&lt;/th&gt;&lt;td&gt;Classical Solos, similar to Musicnotes or VSM in my experience&lt;/td&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://www.carlfischer.com/&quot;&gt;Carl Fischer&lt;/a&gt;&lt;/th&gt;&lt;td&gt;Orchestral Music&lt;/td&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://www.noteflight.com/music&quot;&gt;Noteflight&lt;/a&gt;&lt;/th&gt;&lt;td&gt;I use it more for online notation (which doesn&apos;t integrate) but it has a music store that I have used in the past&lt;/td&lt;/tr&gt; &lt;/table&gt; &lt;p&gt;Other options include:&lt;/p&gt; &lt;table class=&quot;table&quot;&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://www.universaledition.com/&quot;&gt;Universal Edition&lt;/a&gt;&lt;/th&gt;&lt;td&gt;A variety of calssical pieces, but unfortunately, they do not yet have my favorite &lt;a href=&quot;https://www.universaledition.com/24-preludes-for-piano-chopin-frederic-ut50005&quot;&gt;Chopin Preludes book&lt;/a&gt; as a digital download yet...&lt;/td&lt;/tr&gt; &lt;tr&gt;&lt;th&gt;&lt;a href=&quot;https://webshop.donemus.com/&quot;&gt;Donemus&lt;/a&gt;&lt;/th&gt;&lt;td&gt;Publisher of Dutch composer pieces&lt;/td/&gt;&lt;/tr&gt; &lt;/table&gt; &lt;p&gt;There are other providers such as &lt;a href=&quot;https://www.halleonard.com/digitalbook/&quot;&gt;Hal Leonard&lt;/a&gt; which also have digital libraries but these are not in PDF or formats that allow for general usage, so I would recommend against these.&lt;/p&gt; &lt;h2&gt;Closing thoughts&lt;/h2&gt;&lt;p&gt;This post was longer than I anticipated, but as with most things, there are countless apps, music stores, and opinions, so I&amp;#8217;m just sharing my two cents. I hope some of you will find it helpful.&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/143/</guid><title>Moved off of bBlog</title><link>https://www.eyt.ca/blog/143/</link><category>bBlog</category><pubDate>Mon, 6 Mar 2023 20:56:30 GMT</pubDate><description>&lt;p&gt;I have finally moved off of bBlog. It has been on my TODO list for years now, however, there has always been something else higher priority, but with my latest upgrade to Ubuntu 22.04 which comes with MySQL 8 by default, getting it to work again was more work than scrapping it. It seems strange that nothing in PHP has been updated to handle the &amp;#8220;new&amp;#8221; credentials added in MySQL 5.7.&lt;/p&gt;&lt;p&gt;As part of this project, I have removed a bunch of links which makes some of the posts a bit harder to read but with the dead link, it arguably is not much better than clicking on bad links. That said, it was a trip down memory lane with CUJ, Dr. DOBBS, and other great resources no longer being published or available! If you notice any other link problems, please let me know.&lt;/p&gt;&lt;p&gt;Anyhow, my current move is just to use static files directly extracted by from the database. If it helps anyone, just reach out.&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/142/</guid><title>Don&amp;#8217;t return from within finally</title><link>https://www.eyt.ca/blog/142/</link><category>Software Development</category><pubDate>Thu, 9 Aug 2012 03:26:34 GMT</pubDate><description>&lt;p&gt;Earlier today, I was debugging some seemed to be some pretty straight-forward code. The code effectively was the following function. What would you expect the output of this class to be?&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; public static void main( String [] args ) { &lt;/li&gt; &lt;li&gt; &amp;nbsp; System.out.println( foo() ); &lt;/li&gt; &lt;li&gt; } &lt;/li&gt; &lt;li&gt; public int foo() { &lt;/li&gt; &lt;li&gt; &amp;nbsp; try { &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; throw new RuntimeException(); &lt;/li&gt; &lt;li&gt; &amp;nbsp; } catch ( RuntimeException e ) { &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; System.err.println( &quot;Caught&quot; ); &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; throw e; &lt;/li&gt; &lt;li&gt; &amp;nbsp; } finally { &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; System.err.println(  &quot;Finally&quot; ); &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; return 1; &lt;/li&gt; &lt;li&gt; &amp;nbsp; } &lt;/li&gt; &lt;li&gt; } &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;If you expected an exception to be percolated out as I was, you are wrong. It actually turns out that the above returns 1 and ignores the exception that was just raised. Just something subtle to keep an eye out for.&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/141/</guid><title>How do you quickly sort 84 million unique Integers?</title><link>https://www.eyt.ca/blog/141/</link><category>Software Development</category><pubDate>Sun, 8 Apr 2012 03:21:21 GMT</pubDate><description>&lt;p&gt;For the last few weeks, I&amp;#8217;ve been working on increasing the performance of various areas at work and one of the areas that kept on hitting my profiles has been sorting integers. All of us with a Computer Science degree have sorted integers before and we know how to cost algorithms with Big-O notation, but most of the time, the default sort in Java, C#, and other languages is &amp;#8220;good enough&amp;#8221; that we don&amp;#8217;t really think of it.&lt;/p&gt; &lt;p&gt;When it starts to show up on a profile though, sometimes that is time to start thinking about it. As with many things, algorithms based on N usually perform well when N is reasonably sized, so you do not always notice the issue until N becomes interesting or the number of times you call the algorithm increases.&lt;/p&gt; &lt;p&gt;Whenever diagnosing performance problems, it is important to characterize whether it is one or more big calls to the method that causes the entire time sink or whether it is the sheer number of calls to that method. In either of these problems, I think a reasonable first thing to ask is whether that call is really necessary or is it at the right location? More specifically, if you are not running binary searches or other algorithms or use-cases which require the values to be sorted, why sort them at all? If for no other reason, this causes you to think through how to code is or could be used and sometimes leads to a different solution.&lt;/p&gt; &lt;p&gt;In my particular case, there were a few large sorts that were taking all the time.  Each of these sorts were sorting approximately 84 million integers via the JDK standard &lt;a href=&quot;https://docs.oracle.com/javase/6/docs/api/java/util/Arrays.html&quot;&gt;Arrays.sort()&lt;/a&gt; or the &lt;a href=&quot;https://dst.lbl.gov/ACSSoftware/colt/api/cern/colt/list/IntArrayList.html&quot;&gt;Colt IntArrayList.sort()&lt;/a&gt; method and taking approximately 10 seconds per sort. Depending on your background, 10 seconds may be an eternity or a dream, so suffice it to say that the entire processing required for this component had to be less than 3 seconds, approximately half of that had already been accounted for.&lt;/p&gt; &lt;p&gt;So assuming it is required, how do you sort faster? An obvious approach to server engineers is to multithread this operation, such as sorting chunks of that memory in parallel and then merging them together, or perhaps a multi-threaded version of quick-sort, and I am sure that my team expected me to go hide in a corner for a while and code up one of these approaches...&lt;/p&gt; &lt;p&gt;But I didn&amp;#8217;t. You see, there&amp;#8217;s something particularly interesting about the integers we were sorting. First, they are all positive, and second, there aren&amp;#8217;t any duplicate integers. So instead of sorting them, can we do anything else with them that we can infer the sort and have more memory locality?&lt;/p&gt; &lt;p&gt;Well, one way to do it would be to use a set of bits.  Say that the largest number in the array was 200 million, you can allocate 200 million bits and then sort the numbers using an algorithm like this:&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; for each N in array &lt;/li&gt; &lt;li&gt; &amp;nbsp; set bit N &lt;/li&gt; &lt;li&gt; while more bits &lt;/li&gt; &lt;li&gt; &amp;nbsp; find next set bit &lt;/li&gt; &lt;li&gt; &amp;nbsp; set array[i] to that bit &lt;/li&gt; &lt;li&gt; &amp;nbsp; increment i &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Before we go further, you will note that the above algorithm goes through the array twice, and that may seem bad to you, however, there is another thing to keep in mind when assessing this algorithm, which is memory locality, and the fact that especially in the second loop, you are effectively iterating sequentially through two arrays which are probably in the L1 or L2 cache already, potentially making a big performance improvement if you have performance-grade processors.&lt;/p&gt; &lt;p&gt;The following sample code implements this in Java using the &lt;a href=&quot;https://docs.oracle.com/javase/6/docs/api/java/util/BitSet.html&quot;&gt;BitSet&lt;/a&gt; class. I&amp;#8217;ve personally not gone through the code to see if it is the most optimal implementation for what I am doing with it, but after this change, the performance was in the acceptable range.&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; // Code available &lt;a href=&quot;https://www.eyt.ca/CORBA/Java/src/ca/eyt/sorting/IntegerSorting.java&quot;&gt;here&lt;/a&gt; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; BitSet bits = new BitSet();&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; for ( int i = 0; i &lt; array.length; ++ i ) &lt;/li&gt; { &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bits.set( array[i] ); &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/li&gt; &lt;li&gt; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; int lastBit = 0; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; int i = 0; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; while ( true ) { &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; lastBit = bits.nextSetBit( lastBit ); &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if ( lastBit == -1 ) { &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; break; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; array[i] = lastBit; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ++ lastBit; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ++ i; &lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; } &lt;/li&gt; &lt;li&gt; &amp;nbsp; } &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Performance across machines will vary. On my work servers with the latest Xeons, it averages around 800ms per sort, compared to an average of 10 seconds. On my home server, it is a little slower but averages around 9 seconds, verses 23 seconds for the QuickSort algorithm.&lt;/p&gt; &lt;p&gt;Now the above algorithm is not optimal for all sizes. In my tests, the magical point was somewhere around one million rows where the performance of the default Arrays.sort() and the above crossed over, so we do a quick size check and either go to the standard QuickSort or to the BitSet-based sorting.&lt;/p&gt; &lt;p&gt;Those familiar with the BitSet API may mention that I could gain better performance by telling the BitSet algorithm the number of bits I am interested in using and allowing it to pre-allocate the memory for that. Unfortunately though, I did not have that information available for most areas in the code and it was not feasible to guess in this area of the code. What was super interesting though is that doing a pre-scan of the entire array to find the maximum number did not change the runtime of the algorithm significantly.  In fact, the TP99 of the two were off by around 100 milliseconds in my test. This could definitely be an area to improve the above algorithm going forward.&lt;/p&gt; &lt;p&gt;If the above algorithm was not fast enough for you still, there is still room for improvement. First, you can look at pre-allocating the array. Second, the second loop of the algorithm is easily parallelizable and perhaps the BitSet implementation for this use-case could be simplified.&lt;/p&gt; &lt;p&gt;As I mentioned above, the algorithm only works for unique, positive integers.  If you have negative numbers, you could possibly use a second BitSet object for the absolute value of the negative numbers and iterate it in reverse (applying the sign obviously) which would also work. Duplicates obviously don&amp;#8217;t work though, and if you have that problem, ask yourself if you really need the sort at all or whether you need the duplicates, and if you do, consider a parallel sorting algorithm.&lt;/p&gt; &lt;p&gt;Now off to another interesting problem. &lt;a href=&quot;https://www.apptio.com/about-us/careers/index.php&quot;&gt;Wanna help?&lt;/a&gt;&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/140/</guid><title>Rounding numbers with Java&amp;#8217;s NumberFormat...</title><link>https://www.eyt.ca/blog/140/</link><category>Software Development</category><pubDate>Sat, 3 Dec 2011 22:16:29 GMT</pubDate><description>&lt;p&gt;Take a look at the following numbers and round them to the nearest whole number:&lt;/p&gt; &lt;ol&gt; &lt;li&gt; 2 &lt;/li&gt; &lt;li&gt; 2.1 &lt;/li&gt; &lt;li&gt; 2.2 &lt;/li&gt; &lt;li&gt; 2.3 &lt;/li&gt; &lt;li&gt; 2.4 &lt;/li&gt; &lt;li&gt; 2.49 &lt;/li&gt; &lt;li&gt; 2.5 &lt;/li&gt; &lt;li&gt; 2.51 &lt;/li&gt; &lt;li&gt; 2.6 &lt;/li&gt; &lt;li&gt; 2.7 &lt;/li&gt; &lt;li&gt; 2.8 &lt;/li&gt; &lt;li&gt; 2.9 &lt;/li&gt; &lt;li&gt; 3 &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;I&amp;#8217;m pretty confident that you will get the same answers as my 4&lt;sup&gt;th&lt;/sup&gt; grader, which is that the numbers from 1-6 result in a 2 and 7 onwards results in 3, right? Well, given the following code though, you&amp;#8217;d be surprised:&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt;import java.text.DecimalFormat;&lt;/li&gt; &lt;li&gt;import java.text.NumberFormat;&lt;/li&gt; &lt;li&gt;&lt;/li&gt; &lt;li&gt;public class test {&lt;/li&gt; &lt;li&gt; &amp;nbsp; public static void main( String [] args ) {&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;double [] values = new double[] { 2, 2.1, 2.2, 2.3, 2.4, 2.49, 2.5, 2.51, 2.6, 2.7, 2.8, 2.9, 3.0 };&lt;/li&gt; &lt;li&gt;&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;final NumberFormat format = new DecimalFormat( &quot;#&quot; );&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;for ( double d : values ) {&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; System.out.println( d + &quot;: &quot; + format.format( d ) );&lt;/li&gt; &lt;li&gt; &amp;nbsp; &amp;nbsp; &amp;nbsp;}&lt;/li&gt; &lt;li&gt; &amp;nbsp; }&lt;/li&gt; &lt;li&gt;}&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Your surprise would come from the fact that the 2.5 rounds down to 2. Why? Well, reading the &lt;a href=&quot;https://docs.oracle.com/javase/6/docs/api/java/text/DecimalFormat.html&quot;&gt;DecimalFormat javadocs&lt;/a&gt; closely, you will notice that the default rounding policy is &lt;a href=&quot;https://docs.oracle.com/javase/6/docs/api/java/math/RoundingMode.html#HALF_EVEN&quot;&gt;HALF_EVEN&lt;/a&gt;, in which the above behaviour is explained. To change that, simply use &lt;code&gt;format.setRoundingMode( RoundingMode.HALF_UP );&lt;/code&gt; or one of the other policies available in the rounding mode.&lt;/p&gt; &lt;p&gt;Why this is the default behaviour is puzzling to me, but I&amp;#8217;ll just add it to the list, which includes the &lt;a href=&quot;https://www.eyt.ca/blog/138/&quot;&gt;Math.abs() handling of Integer.MIN_VALUE&lt;/a&gt; and non-thread-safe SimpleDateFormat [Link removed] (which, for the record, I do not believe that the code suggested in that blog post is guaranteed to be thread-safe either... since the DateFormat class is declared to be non-threadsafe also).&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/139/</guid><title>Internet Explorer 8 Compatibility Mode...</title><link>https://www.eyt.ca/blog/139/</link><category>Web Technology</category><pubDate>Tue, 14 Jun 2011 18:00:19 GMT</pubDate><description>&lt;p&gt;Earlier today, &lt;a href=&quot;https://www.myscenicdrives.com&quot;&gt;myscenicdrives.com&lt;/a&gt; released our &lt;a href=&quot;https://www.myscenicdrives.com/road-trip-planner&quot;&gt;road trip planner&lt;/a&gt; which I am really excited about. There are several more features that I want to build into it, but this was a really nice time to release it and get some feedback from real users.&lt;/p&gt; &lt;p&gt;For the last week, we have been doing some usability testing, optimizations, cross browser testing, and polishing it all up before the press release earlier today. With the final push going out the door late last night, we did our final round of testing and under Internet Explorer 8, I got that dreaded, &amp;#8220;A problem displaying [site] caused internet explorer to refresh the webpage using compatibility view.&amp;#8221; This resulted in a huge effort to figure out where that message from coming from.&lt;/p&gt; &lt;p&gt;The majority of the testing was done in the latest version of all browsers, which I was really pleasantly surprised at how standards compliant Internet Explorer 9 is. While I had to do a few tweaks specifically for it, it was relatively easy and no more than what I had to do for other browsers. When I cracked up Internet Explorer 8 (via Microsoft&amp;#8217;s &lt;a href=&quot;https://www.microsoft.com/downloads/en/details.aspx?FamilyID=21eabb90-958f-4b64-b5f1-73d0a413c8ef&amp;displaylang=en&quot;&gt;virtual machine image&lt;/a&gt;), it required a lot more tweaks but in the end, it seemed good.&lt;/p&gt; &lt;p&gt;This is why I was really surprised when I loaded up the page last night and saw the compatibility view message. Unfortunately, that message does not provide any insight into what the problem might be. The Microsoft documentation on the matter states that your pages must have a DOCTYPE and validate, but they also hint that there are other undocumented reasons &amp;#8212; this makes finding the root of the problem orders of magnitude more frustrating.&lt;/p&gt; &lt;p&gt;After changing things I thought might be suspect, endless googles for any hints, and etc., I started commenting out various chunks of code trying to make it go. At the end, I had a simple empty page with nothing between the opening body tag and the closing body tag, and it was still happening! But this was illuminating because right above where the body tag came out was one little optimization we had done recently.&lt;/p&gt; &lt;p&gt;When usability testing, we noticed that there was a lag in images being displayed which was not user-friendly. To help prevent that problem, we looked into image prefetching techniques, and fell upon the CSS technique:&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; body:after { &lt;/li&gt; &lt;li&gt; content:url(image.png); &lt;/li&gt; &lt;li&gt; display:none; &lt;/li&gt; &lt;li&gt; } &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;This made a world of a difference in testing.  According to my research, this technique is suppose to be ignored by browsers that do not support the &lt;tt&gt;:after&lt;/tt&gt; clause and so it felt safe. Since the images in question were very specific to the application being developed and the page in question is not intended to be read by search engines, we decided to inline this code on the page.&lt;/p&gt; &lt;p&gt;Could this be the cause? Well, in trying to narrow it down further, I did comment out the entire &lt;tt&gt;style&lt;/tt&gt;-tag and sure enough, my page did not go into compatibility mode.&lt;/p&gt; &lt;p&gt;This fixed my compatibility-mode problem and hopefully it may help someone else out there.&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/138/</guid><title>Math.abs has an edge case...</title><link>https://www.eyt.ca/blog/138/</link><category>Software Development</category><pubDate>Thu, 18 Sep 2008 04:55:58 GMT</pubDate><description>&lt;p&gt;Consider the following Java code:&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; &amp;nbsp; int ai = Math.abs( i ); &lt;/li&gt; &lt;li&gt; &amp;nbsp; assert ai &gt;= 0; &lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Will the assert ever fire?&lt;/p&gt; &lt;p&gt;Yes, it turns out that it can fire if &lt;code&gt;i = Integer.MIN_VALUE&lt;/code&gt;, and you have been warned about this in the &lt;a href=&quot;https://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Math.html#abs(int)&quot; rel=&quot;nofollow&quot;&gt;Math.abs javadoc&lt;/a&gt;, which states &amp;ldquo;&lt;i&gt;Note that if the argument is equal to the value of Integer.MIN_VALUE, the most negative representable int value, the result is that same value, which is negative.&lt;/i&gt;&amp;rsquo;&lt;/p&gt; &lt;p&gt;Keep this in mind when looking at such innocent looking code...&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/137/</guid><title>Java Mail: Make sure the mail.smtp.auth property&apos;s value is a String...</title><link>https://www.eyt.ca/blog/137/</link><category>Software Development</category><pubDate>Fri, 12 Sep 2008 04:38:54 GMT</pubDate><description>&lt;p&gt;If you are using the &lt;a href=&quot;https://www.oracle.com/java/technologies/javamail-api.html/&quot; rel=&quot;nofollow&quot;&gt;JavaMail API&lt;/a&gt; to send out e-mail via an e-mail server that requires authentication and are getting an error like &lt;code&gt;com.sun.mail.smtp.SMTPSendFailedException: 550 You must authenticate&lt;/code&gt;, make sure the &lt;tt&gt;mail.smtp.auth&lt;/tt&gt; property is assigned as a String, like this:&lt;/p&gt; &lt;ol class=&quot;code&quot;&gt; &lt;li&gt; &amp;nbsp; properties.put( &quot;mail.smtp.auth&quot;, &quot;true&quot; );&lt;/li&gt; &lt;/ol&gt; &lt;p&gt;Not exactly the most obvious bug to find...&lt;/p&gt;</description></item>
<item>
<guid isPermaLink="true">https://www.eyt.ca/blog/136/</guid><title>Using Ant with Cygwin</title><link>https://www.eyt.ca/blog/136/</link><category>Software Development</category><pubDate>Sat, 24 May 2008 04:29:12 GMT</pubDate><description>&lt;p&gt;If you have ever tried building something with &lt;kbd&gt;ant&lt;/kbd&gt; under Cygwin, you probably have noticed an error such as the following:&lt;/p&gt; &lt;p&gt;&lt;tt&gt;build.xml:35: c:\cygdrive\c\Progra~1\java/SunAppServer\jdk\lib\J2EE.jar&lt;/tt&gt;&lt;/p&gt; &lt;p&gt;The current &lt;a href=&quot;https://ant.apache.org/manual/platform.html&quot; rel=&quot;nofollow&quot;&gt;Ant documentation&lt;/a&gt; suggests that you should change your build.xml to wrap all such environment labels and class paths with code that executes &lt;kbd&gt;cygpath&lt;/kbd&gt;, but this turns out to create some ugly code, especially if your build scripts use a lot of environment labels.&lt;/p&gt; &lt;p&gt;An alternative scheme that I have just come up with is to use a layer of indication.  You can create an ant shell script that translates all of your necessary Cygwin environment labels using cygpath, and then call the ant.bat to do the actual build.  The advantage of this approach is that more build.xml files are cross-platform out of the box and require very few, if any, tweaks.&lt;/p&gt; &lt;p&gt;The following file is an example of my approach:&lt;/p&gt; &lt;p class=&quot;code&quot;&gt; #!/bin/sh&lt;br /&gt; # OS-Specific Stuff&lt;br /&gt; export PATH=`/usr/bin/cygpath --path --windows $PATH`&lt;br /&gt; export TEMP=`/usr/bin/cygpath --path --windows $TEMP`&lt;br /&gt; export TMP=`/usr/bin/cygpath --path --windows $TMP`&lt;br /&gt; &lt;br /&gt; # Java Specific Stuff&lt;br /&gt; export JAVA_HOME=`/usr/bin/cygpath --windows $JAVA_HOME`&lt;br /&gt; export J2EE_HOME=`/usr/bin/cygpath --windows $J2EE_HOME`&lt;br /&gt; export TOMCAT_HOME=`/usr/bin/cygpath --path --windows $TOMCAT_HOME`&lt;br /&gt; export CLASSPATH=`/usr/bin/cygpath --path --windows $CLASSPATH`&lt;br /&gt; &lt;br /&gt; # Ant Specific Stuff&lt;br /&gt; ORIGINAL_ANT_HOME=$ANT_HOME&lt;br /&gt; export ANT_HOME=`/usr/bin/cygpath --path --windows $ANT_HOME`&lt;br /&gt; &lt;br /&gt; # Project-Specific Stuff&lt;br /&gt; export WHATEVER_YOU_NEED=`/usr/bin/cygpath --windows $WHATEVER_YOU_NEED`&lt;br /&gt; &lt;br /&gt; # Invoke the ANT.BAT via the original ANT_HOME value&lt;br /&gt; $ORIGINAL_ANT_HOME/bin/ant.bat $1 $2 $3 $4 $5 $6 $7 $8 $9 &lt;/p&gt; &lt;p&gt;Of course, this technique can be generally applied to other applications that use environment labels.  Hope that helps.&lt;/p&gt;</description></item>
</channel>
</rss>
