Wednesday, June 15, 2011

The Wheel of Time [2] The Great Hunt

This is Part 2 of my continuing series of blogs regarding what may possibly be my last re-read of The Wheel of Time, in anticipation of the 14th and final book releasing in 2012. Please see this blog post for an overview of the re-read and why I am blogging about it. Warning: CONTAINS SPOILERS FOR THE ENTIRE SERIES. The best way to approach this retrospective is via your own re-read. If you have not read the entire series yet, you may want to wait on reading this.




Book 2: The Great Hunt (1990)
In this second book of the series, we start off knowing who Rand is for sure.  I mean, we knew it in the first book – this archetypical fantasy story is generally predictable, some unknown person is actually a wizard or king and is destined for great things, yadda yadda – but now we know from the get go and frame the story in a different context.  In this book the world begins to expand, we travel from one end of the "Randland" continent to the other, the Seanchan are introduced, Mat's purpose in the series grows apparent and the females from the Two Rivers become major characters in their own right.

I like to think of the first three books in the series as the "setup trilogy."  Like the first act in a play.  They essentially do nothing but set the stage for the rest of the series, by educating the reader about the world and how it works and by introducing nearly all of the major players.  Robert Jordan has said that the ending of Book 3, The Dragon Reborn, was supposed to be the ending of the very first book when he originally planned the series out.  Obviously that didn't work out, as we all know how expansive and verbose Jordan can be.  But in reading so many fantasy and science fiction series in the past, more often than not a "Book 1" is usually chunky with setup, or is nothing more than a very long prologue to the rest of the action, and in this instance it got spread across three books.

Thoughts Then
I got this book not long after finishing The Eye of the World, but I don't recall where I got it or what I was doing then.  I probably just got it at the same place, Star Realm, along with the third book.  That or a place called Little Professor Books, which used to be in a shopping center near my high school in Nebraska.  Little Professor was actually a pretty crappy bookstore, as they were small and had a poor selection compared to the bigger players at the time like Waldenbooks... then mega stores like Borders and Barnes & Noble came along and many of the Little Professor stores went out of business.  It appears there are still a few left according to the internet, but none in Nebraska.


Before there was Borders... there was Little Professor.

Anyway, I do remember reading through this one much quicker than The Eye of the World.  The Hunt for the Horn was a good hook to pull the reader in, as Jordan was able to make it feel like a very important and revered item at the beginning of the book – something I've always been impressed with.  Usually in fantasy you get a few books worth of stories about some relic to build its mythology and mystique, then when it eventually appears in the story it seems that much more awesome.  The Eye of the World had very little of that leading up to finding the Horn of Valere at the Eye of the World.  But its discovery puts you firmly on the path of Tarmon Gai'don and there's no looking back.  The pace was swift and it didn't take me long to read through it, considering I read during much of my free time in high school.

I remember thinking at the time that the whole Seanchan invasion was strange, as they were driven away and eventually didn't return until the very end of Book 7, A Crown of Swords, which wasn't published for another 4 years (I was reading this for the first time in 1992).  There were hints in the intervening books that they might be back, but no one really knew and there weren't online communities or anything like that to discuss theories.  The internet as we know it now did not exist at the time and I only had a few friends in school that I could discuss the books with.  Other than that I was in my own little world.

Thoughts Now
Reading it now, I find I enjoy it more that The Eye of the World, but it still has those "forgotten" elements that disappear and rarely return later in the series, which is an inconsistency for me.  The Horn disappears from the series after this book, the Ways are rarely touched again, portal stones forgotten, etc.  Hurin, a major character in this book, vanishes soon after in the next book and doesn't return until way later in Book 12, The Gathering Storm.  I had actually forgotten about Hurin over the years.  I rather liked him and wish he had had a greater role throughout the series.


I haven't read this volume in many years, and even though I read the crap out of  it the first 6-7 years I was into the series, I had since totally forgotten about the whole sequence in Cairhien.  The Daes Dae'mar chapter is particularly well done, and is a great introduction to the kind of intrigue that proliferates throughout the series and what Rand has to deal with when he starts interacting with the different lands and leaders as the Dragon Reborn.

The reappearance of Thom Merrilin was one of my favorite parts of the book, as his interaction with Rand highlights how much different Rand is at this point vs. when they parted ways in Book 1.  The capture of Egwene by the Seanchan laid the foundation for the strong leader she eventually becomes, being ones of the "trials" she goes through to become one of the new generation of Aes Sedai.  When I think back on the series it's pretty amazing the trials she goes through – Seanchan damane, Aiel Wise One pupil, Amyrlin Seat of the rebels, prisoner of the White Tower.

The blowing of the Horn at the end of the book is one of the iconic moments of the series and anyone who has read the series knows it will happen again at the end, during the Last Battle, by Mat (unless something very unexpected happens in the final volume [Update 7/30/13: It is blown by another.  Mat's "death" in Book 5, The Fires of Heaven, severed his tie to the Horn.]).  This is another method of broadening the world for future volumes, as the Heroes of the Horn factor into the series later on, particularly with Birgitte Silverbow and Tel'aran'rhiod, the World of Dreams (we'll get into this in the next post for Book 3).  Having to wait so long to see the Horn blown again sucks, but that will only make it that much more awesome when it does finally happen next year.  [Update 7/30/13: And yes, it is very awesome.  One of great moments of the series.]

The Abysmal Cover
I know I didn't care for the cover during my first read, but I haven't really cared for any of them.  This is one of the worst ones, though... how anyone at Tor thought this was a decent and even-close-to-being-accurate cover is beyond me.  Loial is a joke, not even close to the descriptions.  I guess Darrell K. Sweet thought he could just paint a taller dude with pointy ears and a book in his hands and call it a day.  Selene (Lanfear) is ugly, not even close to the breathtakingly beautiful woman she is described as.


The best thing about this cover are the rocks.

And don't get me started on the Trollocs on the back cover... they are just humans with horned helmets on! Unbelievable. General displeasure over the covers of the series even prompted me to ask Robert Jordan about it, the one time I met him at a signing. More on that in the Book 11 post.

Sweet's covers are good for fantasy like Piers Anthony's Xanth, but The Wheel of Time has always deserved much more, something with a lot more realism.  Tor redeemed itself a little with the new eBook covers (which are used for the number icons at the top of this and other posts).  The new one for The Great Hunt is the same scene, but 5 billion times better.

So thank you, Kekai Kotaki, for painting a proper cover for The Great Hunt.

Damn, this is so much better.  The Trollocs look awesome.

Next:
Book 3 – The Dragon Reborn
 
Previous:
Book 1 – The Eye of the World

Retrospective Overview

Wednesday, June 8, 2011

Exploring Memory Allocation on an Android Launcher using ADB

I recently started getting into Android application development, and an annoying issue with the launcher on my Android phone provided me with a nice learning experience in regards to debugging the Android system using adb (Android Debug Bridge).  Considering how much searching I had to do on the internet to figure some of these things out, I figured I'd blog about it and post all relevant links and info for others to use.

ADW Launcher
I first got an Android phone last year, the Samsung Epic 4G on Sprint, with Android 2.1 (Éclair).  My brother has been raving about Android for a long while so I figured it was time to take the plunge, since I was tired of my Blackberry and had no plans to get an Apple product.  He suggested I use the ADW Launcher in place of the default launcher, as it is more customizable and cooler, etc etc.  So I downloaded it and it worked great.


However, recently Sprint pushed the Android 2.2 (Froyo) update to the Epic 4G and ever since then, I've occasionally had problems with the phone being sluggish when coming out of the lock screen or changing the orientation (rotating) when on the home screens.  Since other applications were not evincing any lag while rotating the phone, I narrowed it down to the launcher itself.  Over time, something was causing it to become sluggish, taking 2-3 seconds to respond to a command.

This became somewhat irritating when I started missing calls because it would lock up when I tried to answer them.  Since I already had the Android SDK and was delving into development, I decided to figure out how to debug my phone using ADB at my bro's suggestion.

adb
adb (Android Debug Bridge) is a tool that can be used to monitor and manage the state of the Android OS, either on a device or through an emulator.  It's a simple command line tool, though its output can also be viewed through the Eclipse IDE (used for development in the Android SDK).  There are a variety of commands you can issue to adb, but for this I'm primarily concerned with the logcat command, which is specific to debugging.


logcat prints system log info directly to the screen.  As the Android OS processes, pretty much everything it does can be displayed through the logcat function, each action appearing on a separate line.  It can be a very useful tool in determining where a particular application is getting hung up or suffering performance, especially when memory is involved, as you can see the log output while using the application itself.

In order to get adb working properly for my particular handset model (Samsung Epic 4G), I had to find the proper ADB Interface driver.  After much searching online I found it on the Samsung website itself.  I won't go into the installation and configuration itself, but here's a good overview of the process if you need it.  In any event, I got it installed and finally started looking at some logs.

Garbage Collection
What I noticed immediately upon running logcat while tilting the phone, was that a number of log entries like the following were appearing:


04-22 16:19:35.829 D/dalvikvm(32653): GC_FOR_MALLOC freed 11731 objects / 759624 bytes in 52ms

Every time I tilted the phone, I would see around 6-10 of these in a row.  I even made a video of it, for all to enjoy (watch on full screen if you want to actually read the logcat output):


So what do those lines mean?  We'll start with the actual action itself, GC_FOR_MALLOC.

I did more searching and found a succinct explanation on stackoverflow.com about it.  The Android OS actively manages memory on its own, and will free up memory as needed, depending on what types of activities you are performing.  Normally you will see logs of GC_EXPLICIT or GC_EXTERNAL_ALLOC, which are normal for OS memory management.  GC_FOR_MALLOC, however, is called when there's not enough memory on the heap for an allocation to be performed.  The system is forced to call it because memory is scarce – the application is not calling it explicitly as part of its internal memory management (that was coded into the application).

The next step was to make sure that the GC_FOR_MALLOC calls were related to the ADW Launcher itself, which I suspected, but hadn't confirmed.  So I had to do more investigating to decipher the entire log line.

Deciphering the logcat output
The first part of each logcat line is obvious: date and time.  I used the following command to specify that I wanted timestamp detail as part of the output:


adb logcat –v time

There are a variety of filters you can use at the command line (see the link in the adb section for more info on that), but I found that one the most useful for this particular exercise.  The next part of the line is a little more esoteric:

D/dalvikvm(32653)

The first letter is the priority of the log message.  Here are the different priorities (link in adb section):
  • V — Verbose (lowest priority)
  • D — Debug
  • I — Info
  • W — Warning
  • E — Error
  • F — Fatal
  • S — Silent (highest priority, on which nothing is ever printed)
The number is the PID (Process ID) of the application or process in question.  So the message says that the Dalvik VM (Virtual Machine), upon which the Android OS runs, has a Debug message for an application with a PID of 32653.  But how do you know what application is tied to the PID?

Unfortunately there is no simple way (that I could find) to get a list of all running services and applications with their PIDs.  PID may not be unique to a specific application and could be shared by more than one, which can make it even more confusing.  There is a command that could help, though:

adb shell ps

This command prints out a list of processes with their PIDs.  However, it doesn't print all of them... because when I did it, PID 32653 did not appear on the list.  Here is an example of the output:

USER     PID   PPID  VSIZE  RSS     WCHAN    PC         NAME
root      8393  2     0      0     ffffffff 00000000 S loop2
root      8396  2     0      0     ffffffff 00000000 S kdmflush
root      8397  2     0      0     ffffffff 00000000 S kcryptd_io
root      8398  2     0      0     ffffffff 00000000 S kcryptd
radio     13305 2351  206764 13108 ffffffff 00000000 S com.samsung.phoneinfo
app_15    26629 2351  255896 28732 ffffffff 00000000 S com.google.android.gm
system    29346 2351  217088 17828 ffffffff 00000000 S com.android.settings


What to do?  I did a search in the log output for PID 32653, looking for the first time it appeared, and I found this:

I/ActivityManager(2453): Start proc android.process.acore for activity org.adw.launcher/.Launcher: pid=32653 uid=10088 gids={1015}

This clearly shows ADW Launcher activity (an activity in Android is basically a program, or a thread) starting, with a PID of 32653.  So it's confirmed that that is the culprit!  Apparently the launcher is using a lot of memory and when you rotate the phone, Android actually kills and recreates the view on the screen each time (this is how the OS works), so at some point there doesn't seem to be enough memory to help the launcher recreate the home view each time.  So it's forced to garbage collect.

The Solution and Other Observations
In the end, it appears to be some kind of incompatibility between ADW Launcher and the Froyo version of Android.  Launchers are memory hogs, I've discovered, and depending on how many home screens, widgets and shortcuts you have, performance can vary.  I found two solutions to the problem, one for rooted phones (mine is not), and one for non-rooted phones (which merely involves changing some of the settings for the launcher).


For rooted phones, follow the instructions I found here, on a Launcher Pro forum.  That process fixes the launcher in memory, so it's never lost and the OS is not forced to recreate it when you rotate the handset.

For non-rooted phones, try playing with the launcher settings.  This post on droidforums.net specifies exactly what settings to focus on.  I changed those and I have not had half as many problems with lag as before.  Occasionally it gets slow, but not as bad as it was before (as demonstrated in my video).