Showing posts with label computerscience. Show all posts
Showing posts with label computerscience. Show all posts

Monday, January 27, 2020

Maintaining Software For A Long Time

On and off for a few weeks, I've been removing a good chunk of legacy support from some software I maintain (FreeIPMI). It's always hard to know exactly how much legacy support is ok to remove and possibly break users, so I decided somewhat randomly "if it's older than 10 years, it's ok to remove it".

It immediately lead to two somewhat orthogonal thoughts:

A slightly negative, "Have I really been maintaining this stuff for 10 years" feeling.  There's the tiny part of me thinking, "Damn, that's a lot of hours spent maintaining this over a long period of time."

A mostly positive, "People are still using my stuff after 10 years" feeling.  The reality is that so much software is not maintained well, so eventually people just stop using it.  So it does make me feel good knowing people still use it.  And everyonce in awhile, I answer a question on Stackoverflow or Serverfault about it, so I know people are definitely still using it.

Tuesday, November 6, 2018

IBM acquisition of Redhat

True story, my wife and I were watching TV when my wife asked, "What's Redhat?".  I then explained that Redhat was a company that (loosely) packaged open source software together and sold support for it.  Because my wife was familiar with Cloudera, I told her that it was the Cloudera of the Linux operating system world.

Then she blew me away by then asking, "Why would IBM want to buy them for $30 billion dollars?"

As a software developer that has worked almost exclusively on Linux in his career, it was a huge announcement.

After sitting back and pondering it for awhile, I was beginning to think about the move and it was a good move by IBM.

In my opinion, it is a great move for IBM.  But the probability of it being a success is low.

In one article I read, a Redhat engineer said: "I can't imagine a bigger culture clash."  I think that pretty much sums up the thoughts of myself and many other engineers.

Here were some differences I thought about after the sale was announced:
  • IBM engineers are typically told to be wary of the GPL to avoid potential code pollution, Redhat engineers work with the GPL all of the time
  • IBM often requires signed license agreements for code contributions to their code base, Redhat works with the open source community on tons of things as is
  • IBM legal likes to get their hands into the middle of many things
This of course doesn't even get into the fact that Redhat & IBM have different competing technologies.

I read a tweet (which I'm having trouble finding), but it said something to the effect:
  • IBM just paid 30% of their market cap for Redhat
  • Redhat's headcount is only 3% of IBM's
  • Unlike IBM, Redhat does not really have much intellectual property (IIRC, IBM has the largest patent portfolio of any US company)
  • Unlike IBM, Redhat does not really have much capital assets
and I'm going to add
  • Unlike IBM, Redhat gives away its product for free
  • Unlike IBM, Redhat employees can leave Redhat and take leadership of their product with them
It's a huge culture clash.





Monday, August 29, 2016

Renaming "Master/Slave" architecture to other terms

I learned of an interesting trend in software circles today. There has been a move to rename "master/slave" architecture into other terms, such as "master/worker", "leader/follower", etc. in an effort to remove the word "slaves" from code, docs, etc. I first noticed it done in Hadoop 3.0.  But it got a lot more attention when Django made the change and Mozilla donated 15K to BuildBot to fund similar work. Googling around, it seems Jenkins, Drupal, and Mesos also did the change in the last few years.  I'm sure there are more that I missed and am just not searching the right terms.

As you might imagine, this has lead to quite politicized discussions on bug/issue trackers.  Are we going "too politically correct"?  Couldn't engineer hours be used more effectively?  You can imagine all of the discussions that could follow.

But I found this comment from the Django issue tracker on this subject to be quite enlightening.

"I'm very glad for this change because as a PoC I felt very uncomfortable seeing and using this terminology in my code"

We can choose to be more inclusive and welcoming to all people that may code.  Or we can choose to stick to the past terms based on a somewhat arbitrarily chosen naming from eons ago.  As a group, I think we should try to make programming more "inclusive" than "exclusive".  I wrote about this a bit awhile back regarding the use of 0xB16B00B5 (i.e. "Big Boobs") in the Linux kernel and how such language can make programming seem like something for boys instead of girls.

I know there are those who think it shouldn't be changed due to it's large legacy meaning/usage and the fact that it's clearly not related to human slavery.  I'm sure there are others that feel that such as a change is just "being too politically correct."
 
I was trying to think of an example in software history that would serve as a good illustration of how it's a good idea to change these terms, even though they become nearly defacto terminology.

I couldn't think of one.  Some of it just might be because software is too "new" of a thing still.

I did end up thinking of one in medical history related to Down Syndrome.

According to the wikipedia page, Doctor John Langdon Down first characterized Down Syndrome in the 1860s and initially called people with it "mongoloids" because he considered the facial features to be similar to those of "Mongolians".  It wasn't until the 1960s that the term was official changed to "Down Syndrome", named after the doctor that characterized it.

I hope to most readers here that the reason for the change is obvious.  The term "mongoloid" was often used as a pejorative for people of Asian descent.  It was simply embarrassing to continue to use such an outdated/racist word to describe a genetic disorder going into the 1900s.  According to Wikipedia, it wasn't really until the 1970s that the term really disappeared.

I can't help but think, it took about 100 years for the term to be officially changed from it's original naming to the modern one.  That's a long time.  So that's a lot of medical history that had to be changed.  I believe that the change was due to the realization that while the original name was widely used in the medical community, times do change.  And as times change, it's perhaps best to move on and adapt to that change.

So I think the software community can change too.  So I decided to make the changes in Magpie.  While I can't do it everywhere, as some tools such as Spark and Hbase still rely on the term, perhaps this is the beginning of the change throughout.  Once projects like Spark and Hbase migrate, I can propagate it further.








Wednesday, July 13, 2016

Oddities in HBO's Silicon Valley

I recently began watching HBO's Silicon Valley.  Once in awhile I see a technical and/or conceptual oddity that I can't help but ponder over and think "uhhh no".  These are the ones that I noticed and bothered me.

I'm not going over any specific misuse of technical terms or over exaggerated elements for Hollywood humor.

Needless to say there are ***SPOILERS*** below if you haven't watched the show.

Season 1 - Episode 1

Richard is an employee at Hooli, but is also in a startup incubator launching Pied Piper.  Later in the episode Hooli CEO Gavin Belson tries to purchase Pied Piper.

Shouldn't Hooli have an intellectual property claim on Pied Piper, given that Richard is still an employee at Hooli?

Now I can't speak for the IP rights contracts that every company in the world has, and there are obvious exceptions (some companies you can sign documents to indicate you have some outside business interests that are independent of your job), but this seemed odd to me.

(They eventually delve into this in Season 2.)

Season 1 - Episode 6

In this episode, elite programmer "The Carver" is hired to help get Pied Piper towards its deadline.  In a somewhat cliche plot, he messes up some code and the team has to spend a lot of time fixing his mistake.

I couldn't help but think, "You guys don't have a code revision repository of any sort?"  The kind of thing that could be backed out within a minute or two? Later in the episode, they are distinctly comparing lines of code on two screens, so it strongly suggests they don't have a code repo.

But this isn't what gets me.  Later on, they also ran and passed regression tests to know they fixed the bugs/mistakes.  Regression tests suggest that you have different versions of software.  After all, what's the point of regression tests if you're not trying to catch old bugs/mistakes?  So they have different versions of software, but no code repo to manage the different versions of code?

Season 2 - Episode 10

During the trial, Erlich mentions that Big Head's code for "Nip Alert" was so bad that it crashed Richard's laptop and Richard had to take it to the Apple store to fix and it was "in the shop" for three days.

Now "crash" is ambiguous, but I interpreted the dialogue context to mean this caused a hardware problem.  It wouldn't have to be "in the shop" for three days otherwise.  It would be very hard, if not impossible, for a web based application (let alone a normal installed application) to destroy a laptop's hardware.  I can see potential theoretical ways, but it's hard to imagine a general application doing this. [1]  Add in the fact that Big Head is generally regarded as incompetent, it's hard to believe he could have done anything that advanced.

If "crash" caused a software based problem, such as a process foolishly running amok and deleting valuable system software (again, shouldn't really be happening for a userspace non-privileged process and shouldn't be happening with such a dumb application), this one is perhaps a bit more believable.  But a simple software reinstall and update from backup is all you need.  No need to bring it into the shop.

Season 3 - Episode 6

In this episode Richard is shown to be a lover of tab indentation in code.  He meets a girl named Winnie who codes uses spaces instead of tabs.

In one scene Richard and Winnie are sitting on the couch both coding and Winnie is programming and constantly smashing the spacebar to indent her code.  It's loud and annoying and eventually Richard can't handle it.  Hilarity ensues.

The "tabs" vs "spaces" debate is endless, but what I found interesting was the fact that Winnie repeatedly hit the spacebar to indent her code.  Today, almost every editor will automatically convert a "tab" to the appropriate number of spaces.  So there is no need to ever hit the space bar over and over again.  Even those who prefer spaces to tabs don't actually hit the spacebar over and over again, they use the tab key.

[1] - While writing this I Googled "can you program software to damage hardware" and there are some write ups with theoretical ideas that seem to confirm my suspicions.

Thursday, June 30, 2016

Reflecting on a moment of personal growth a long time ago

After writing my prior blog post about remembering how I started programming, I recalled something from about 17 years ago.  Looking back, it was a great "personal growth" moment in my (then young) career.

I was at my first internship after starting college.  The company was a startup that worked predominantly on Unix/Solaris.  Very early on in the internship (I think the first week), I realized I knew alot less about Unix than the other interns and at times was really lost in what was going on during training.  I became worried about my ability to actually be able to do the job.  To be honest, it may have been the most lost I've ever felt at any point in my life.

As an example of how little I knew at the time, I recall that while I had setup my personal website using instructions I found, I did not actually know what things like "chmod 744" actually did.  At the time it was just something I knew you did to get things working.  I remember I didn't know the grep command.  I remember at one point asking another intern what a daemon was. 

So this was my knowledge of Unix and I was supposed to be doing Unix programming for this internship.

Now, I should mention that this was before the time of Google's dominance.  It was the time before Wikipedia and blogs.  There was no stackoverflow.

However, at the same time, I was much younger in my career.  I'm sure there were elements of "how to learn" that were not quite yet cemented in my mind.

Now, I could have done one of several things once realizing I didn't know anywhere near as much as I hoped (or should have).  I could have faked I did know what I was doing and continue on.  I could have shut my mouth and just see what happens.  On the extreme end I could have quit thinking I wouldn't be able to cut it there.  I've certainly known people who did those things like this in their lives.

I ended up going to my boss towards the end of the first week, telling him about my concern for this and how I felt really lost.  I don't think I'd ever been so worried over a conversation in my life.  But he was very calm and caring, telling me thanks for admitting it.  He got me some books from some of the engineers to take home and catch up on.  So I did read them starting that weekend.

The end result after that summer?  I ended up learning a lot more.  Became comfortable in Unix environments.  I got more accomplished that summer.  I like to think I proved I was a good employee, as I was invited back to work part time during the school year.

So I have looked back at this event and considered it an important moment in my personal growth when I was younger.  The formula for succeeding on projects/work isn't magical.  Ping others for help/pointers (today "others" can be Google), read stuff, put in hours, try things out, and eventually you can figure it out.  As I look back on my career, this exact formula is the method by which I had success on many projects despite feeling extremely lost/confused in the beginning.

Wednesday, June 22, 2016

Remembering How I Started with Programming

As I've said on this blog before, sometimes I can't help but feel dumb at times as I see so much brilliant code being written out there.

But at the same time, I have to remember that it takes years to master certain skills and knowledge.  I like to think people have looked at my code and think it's pretty nifty too :-)

Just the other day I was writing a simple python script for some personal use at home.  I wanted it to do a few different things in it and at some point it occurred to me that I've never parsed command line options in a Python script before.  I guess up to this point I'd only written Python scripts to do one simple thing or modified much larger bodies of code that others had started (i.e. I probably cut & pasted prior argument parsing code to add the option(s) I wanted).

I went online and started reading through the Python argparse documentation.

I suddenly paused and realized something.

About 17 years ago I was in my first internship in college.  I was writing tools/commands in C to execute test code.  I still remember reading the getopt manpage at one point because I had never actually done argument parsing in C before.  The first time you see a string like "hVa:b:", it can be quite confusing.

About 14 years ago, in my first month of my first fulltime job after college, I was working on Genders.  I remember reading about getopt_long because I had never dealt with long options in C before.

So I actually sat back and paused, realizing that I've learned a lot over the last 16 or so years.  And sometimes when you feel dumb that you aren't an expert in one particular subject, you have to remember that the things you are more of an expert in, you had to read that documentation for the very first time at some point too.




Sunday, May 29, 2016

The Mendoza Line In Programming

For those who are unaware, there is a concept called "The Mendoza Line" in baseball.

Short description, there was a baseball player named Mario Mendoza, who (to put it frankly) wasn't a very good baseball player.  Now, making it to the major leagues is an accomplishment itself, and Mario Mendoza was able to scrape together a 9 year career mostly as a utility player.  He represented the minimum level one had to perform at to play and have a career in baseball.  Thus the term the "Mendoza Line" was coined.  If you fell below the line, you couldn't be a major league player.

I've wondered at times what is the "Mendoza Line" for a programmer?  I have a suggestion for the line.

Lets say there is some manual activity that will take you time X to complete. For this example, lets say there are similar typos in a lot config files.

If time X is really small, like a minute, we'll probably just do it manually.  This is perhaps the case when the typo is only in a small number (e.g. 1-2) of config files.

Lets consider if time X is a reasonable size and non-trivial.

If it would take you > time X to write a script to do the manual activity, you still might do it manually.  In my example above, perhaps the typo is in 5-8 config files.  Perhaps the config files and typos aren't similar enough to warrant figuring out the right regex.  So even if it's annoying, you still do it manually.

If you can develop a script faster than time X, obviously you should develop a script to do this manual activity.  Using my config file example, perhaps the typos are in over 500 config files.  Now finding the right regex is worth the time and energy so you don't have to do this task manually.

Now, we all have to do some manual activities in our day to day lives on a computer.  Some of these things are automatable (sp?), but we continue to do the manual activity b/c the effort to automate just isn't worth it (e.g. most don't script hitting the brew button on a coffee maker).

I like to think of this as the "Mendoza Line" for programming.  If you can recognize some manual activity is taking up some time X, can you recognize a script can do it faster, and write the script in less than time X.  If you can do this, you probably can have a career as a programmer.

Now I do want to say that the variable "X" does depend on a number of factors.  It can include job function, experience, and skill set.

I know very talented system administrators that can pump out very nifty sed/awk lines to do things in just a minute.  This makes sense.  There are probably many manual things that they have to do in their jobs so they have found it worthwhile to learn and commit to memory all the advanced parsing that sed/awk can do.  I personally have not b/c I don't do it enough in my day to day life.  So "X" for a task might be small for an advanced system administrator (lets say ~5 minutes) while it'll be larger for me (lets say ~15 minutes) for some setup/config activity.

Another variable to X is how often you might repeat it.  If you don't believe you'll ever have to do the manual activity again (b/c it's not your job and you're doing it as a favor to someone else) perhaps time X is viewed as small only because it's a one time activity.  But if your job function involves doing the activity many times, the potential cost is much larger.

There are perhaps other factors that affect "X", but hopefully the point is understood

Saturday, May 28, 2016

I'm really good at fixing typos!

I have a joke amongst colleagues that I am "only good at fixing typos in open source projects."

Why?

Whenever I submit a code patch for some bug and/or feature in a open source project, it can often go ignored.  Why?  Because project maintainers are busy and they don't have time to look at every patch that comes in.  If the patch solves some specific problem they are looking at, then you're in luck.  But more than often I'm fixing something that isn't on their current radar.  Eventually, the patch gets lost amongst the other patches in their review pile and is forgotten.

Why do I know that patches will be forgotten or ignored for long periods of time?  It's because I do the same thing! :-)  It's normal and reality with open source projects.

But what happens when I submit a patch that just fixes a typo in comments or a typo in documentation?  This takes almost no effort to look through and review, so the patch is accepted immediately.

I do the same thing in projects I maintain.

As time goes on, there are a few projects that I suddenly feel like the only thing I can contribute is typo fixes.

Thus, I'm really good at fixing typos :-)

c'est la vie

Friday, May 27, 2016

At what point am I a "Googler" and not a programmer?

Just the other day what should have been about 15-30 minutes of fixes to a Perl script took me atleast an hour because of constant "I can't remember how to do this in Perl" Google searches:

"perl elif or elsif" - I remembered enough that "else if" wasn't the correct syntax in Perl, but couldn't remember which of the common alternates it was.

"perl conditional string compare" - I couldn't remember if it was "eq" or "-eq".

"perl string concatentation" - I actually had bugs in my script because I thought "+" was supported in Perl.  Whoops, it's "." in Perl.

"perl break continue" - Script errors informed me that I was using the wrong syntax.  Had to out right Google the answer b/c I couldn't remember it (in Perl it's "last" and "next").

There might have been a few more searches.

Needless to say, Perl is not my bread and butter language.  It's something I use once in awhile because I need to script something of some complexity just beyond a shell script.  When you jump between languages, the exact syntax of what you should be using can become a blur.

So it lead me to this question I think about once in awhile "Am I a professional Googler?"  There are times I spend way more time Googling than I would like to or think I should be.

First, is Googling an answer bad?  Admittedly, it is something that just feels bad.  A large part of this is because when you can't recall things from memory, you tend to think of yourself as stupid.  In some ways, it makes you feel lazy.  That perhaps reading a book would be wiser or finding the answer in a book would be the "smarter" thing to do.

IMO, this isn't the case.  You can't remember everything.  Many things I've done professionally in my career I haven't done from memory.  Significant portions of programming knowledge came from books.  When I needed a piece of information I developed a mental index of where to look in my mountains of books for specific answers.  In fact, I distinctly remember having to go to my Perl book to look up "What's the perl equivalent of break & continue" in the past because I couldn't remember it then.

Eventually that mental index simply turned into Google.  Various blogs, technical documentation, and StackOverflow have turned into the books on my shelf.

So I do not believe there isn't inherently anything wrong with Googling various answers and it doesn't make you any less smart.

But ...

Using Google to recall syntax nuances is one thing.  I think there is a mental line one crosses to begin to wonder, "Am I really Googling too much?"  At some point are you barely even programing?

I like to think of a recent project I worked on called Magpie.

Originally, I had more grandiose Big Data goals related to Big Data on HPC.  But as things sometimes go, a far more humble solution using just Bash scripts was found to be just as much, if not more, useful than many of the original project ideas.

These Bash scripts were initially hacked up because they were meant to be "support" for my actual work.  When we determined that the support-ish Bash scripts were what people found to be the most useful product of the work, did we turn it into a more polished product.

I never sat down and actually learned Bash scripting syntax at any point in my life.  Basics such as conditionals and loops were cut and pasted from online guides when I've had to develop small scripts before.  More nuanced things were gleened from more Googling and cut and pasting.  There were many searches for "bash" + "sed|awk" + "some pattern" because I never learned many of the advanced features of sed or awk or any of the advanced Bash-isms.

I've cut and pasted my share of code before.  Whenever I've needed a function that I deemed reasonably common and didn't want to write on my own, I was able to find one online.  But this was different.  I felt that I cut and pasted an entire solution together from stuff on StackOverflow.  To be honest, if I was given simple interview programming questions and asked to do it in Bash, I doubt I'd be able to do it.

In contrast, I think of how I originally learned to program in C.  I took a small C programming class in highschool.  In college it was in a few of my classes.  I read about half of the famous Stevens network programming book in college and the rest once I began my career.  There were other books too.  My programming expertise in C was hardened through many homework assignments, work assignments, and bugs.

Granted, C is a far different beast than Bash, but when I learned C the web was just in its infancy.  A few not-great search engines like Excite and AltaVista existed.  Google was just coming online.  There was no Stackoverflow or blogs with help on individual niche topics.  So learning it primarily meant you had to learn from scratch.  So C programming is simply backed into my brain.

I wonder if things would have been the same if StackOverflow was around when I was first coding in C?  Would I have not ever read the Stevens networking books and coded through StackOverflow?  Is this what people do in college now doing their assignments?

It's something I've pondered.  But getting back to the original question ... Am I a professional Googler?

I eventually realize the answer is no.

In actuality, it takes years to get the point that you can become proficient enough to actually understand what it is you are looking for so you can cut and paste off the internet.  When you find the piece of cut & paste that is correct, you know it and you can use it.

What I have to remember is yes, I did cut & paste off the internet for much of Magpie.  Perhaps it does make you feel lazy.  But it was individual lines of syntax, not an entire solution.  The real meat of Magpie is all of the Hadoop, Spark, etc. knowledge in Magpie within the scripts.  I just needed bits of code to piece it together.

It's no different then when you cut & paste from your personal library of code.  The first time you need to program something tricky, you really figure it out.  But everytime you need it later, you cut & paste (or if it's a library, just call it, etc.).  But eventually, you probably forget all the subtle details you put into making it robust and solid in the first place.  Do I remember all the details of how to make a portable non-blocking connect call?  Absolutely not.  But after I wrote it the first time, I used it several more times over.

While writing this blog post, I had almost forgotten something.  While I was developing Magpie, I did write many 5-10 line scripts off to the side to figure out "is this how the syntax works?" or "is this what I'm looking for?"  I had completely forgotten this reality.  So I didn't actually blindly cut and paste all of the time.  And of course I did eventually learn some things.

And ultimately, at the end of the day, one tends to invest time in those things they think worthwhile.  Do I consider Magpie to be of some complexity that it requires my attention to learn all Bash syntax in depth?  The answer is no.  So I didn't bother to.





Friday, April 1, 2016

Beginners Guide to Hbase with Python & Thrift

I recently wanted to play around with Hbase and Python, which subsequently lead me to use Thrift.

I know there are tons of guides on the web, but a number I found were outdated or based on downloaded versions of things instead of packaged distro versions.   I eventually had to piece together information from several sources.  So I thought I'd put it altogether on this page for anyone looking for simple "cut and paste" instructions to begin with.  I'm not going to go through the basics of Hbase and Thrift, as there are many guides out there, but I'll give updated instructions based on the following versions I used.

Hortonworks 2.2.6.0-2800
Hbase 0.98.4
Redhat 6.7

As an aside, there may be newer interfaces (such as happybase) that are now more popular.  I may look into those later, but these are just my notes on this particular subject.

As another aside, my Hbase has already been populated with data, so there's no need to create/insert data, so I'm skipping that.

The two primary Hbase + Python + Thrift sources I used for this were:

Using Facebook’s Thrift with Python and HBase (posted July 2008)

and

How-to: Use the HBase Thrift Interface, Part 1 and Part 2 and Part 3 (posted September 2013)

So lets start.

First up, I downloaded thrift 0.9.3 and did the normal configure and make, but this didn't compile for me.

src/thrift/qt/moc_TQTcpServer.cpp:14:2: error: #error "This file was generated using the moc from 4.8.1. It"
src/thrift/qt/moc_TQTcpServer.cpp:15:2: error: #error "cannot be used with the include files from this version of Qt."
src/thrift/qt/moc_TQTcpServer.cpp:16:2: error: #error "(The moc has changed too much.)"

this was also the case with thrift 0.9.2, 0.9.1, and 0.9.0.

I went to thrift 0.8.0 and hit other build errors.  These were maybe solvable, but being lazy I just downloaded 0.7.0 to try it, and it compiled fine.  So I ended up using thrift 0.7.0.

Since this compiled, I need to install it somewhere.  I'm going to install into a non-privileged directory, so set all of these prefixes appropriately when you configure and make install.  If you're root and you can install anywhere, you can probably ignore all of this.  Adjust appropriately if you use bash instead of tcsh.

setenv PY_PREFIX /yourprefix/thriftpy/
setenv JAVA_PREFIX /yourprefix/thriftpy/
setenv RUBY_PREFIX /yourprefix/thriftpy/
setenv PHP_PREFIX /yourprefix/thriftpy/
setenv PHP_CONFIG_PREFIX /yourprefix/thriftpy/
setenv PERL_PREFIX /yourprefix/thriftpy/
./configure --prefix=/yourprefix/thriftpy --exec-prefix=/yourprefix/thriftpy
make install


After that, you should hopefully have thrift installed into your appropriate path and /yourprefix/thriftpy/bin/thrift should be available to run.

Now run thrift to generate Python files for Hbase

> /yourprefix/thriftpy/bin/thrift --gen py /usr/hdp/current/hbase-client/include/thrift/hbase1.thrift

Now if you're wondering why hbase1.thrift instead of hbase2.thrift, it's because there is now a newer thrift interface available compared to the original.  I use hbase1.thrift just to begin with.


Now there should be a "gen-py" sub-directory where you ran this.

Now we need to start the thrift server.  With HDP you can do:

/usr/bin/hbase thrift start

I started this in another window so I can control+C is later on.

Ok, onto code.  I started with code sort of from both the sites above and put together:

#!/usr/bin/env python                                                                                                                                 
import sys

sys.path.append('../gen-py/')
sys.path.append('../thriftpy/lib64/python2.6/site-packages/')

from thrift import Thrift
from thrift.transport import TSocket
from thrift.transport import TTransport
from thrift.protocol import TBinaryProtocol

from hbase import Hbase

# Make socket                                                                                                                                         
transport = TSocket.TSocket('localhost', 9090)

# Buffering is critical. Raw sockets are very slow                                                                                                    
transport = TTransport.TBufferedTransport(transport)

# Wrap in a protocol                                                                                                                                  
protocol = TBinaryProtocol.TBinaryProtocol(transport)

client = Hbase.Client(protocol)

transport.open()

tablenames = client.getTableNames()

print "table names are: " + ",".join(tablenames) 

You'll notice a few sys.path.append calls to add paths to my local dirs with libraries in them.  You may need to adjust accordingly for your installed things.

Hopefully, you should just be able to run this and there will be no problems (unless you've never created tables in Hbase, which you should create some).

Ok, now to read some data.  Again, pasting together some code from the above resources, this will get a single row of data.

rows = client.getRow('mytable', 'myrowkey')
 
for row in rows:
    message = row.columns.get('mycolumnfamily:mycolumnname').value
    print "message = " + message
    rowKey = row.row
    print "rowkey = " + rowKey


This didn't work for me and I got an error of

TypeError: getRow() takes exactly 4 arguments (3 given)

Hmmm.  Now, if you look in the file hbase1.thrift from before, you can see what the interface for getRow looks like.

  /**
   * Get all the data for the specified table and row at the latest
   * timestamp. Returns an empty list if the row does not exist.
   *
   * @return TRowResult containing the row and map of columns to TCells
   */
  list getRow(
    /** name of table */
    1:Text tableName,

    /** row key */
    2:Text row,

    /** Get attributes */
    3:map attributes
  ) throws (1:IOError io)


Hmmm, it seems there is a new attributes argument.  I couldn't figure out what this did by searching online.  I didn't want to dig into the code too much at this point so I just passed in None to the getRow call like so:

rows = client.getRow('mytable', 'myrowkey', None)
 
for row in rows:
    message = row.columns.get('mycolumnfamily:mycolumnname').value
    print "message = " + message
    rowKey = row.row
    print "rowkey = " + rowKey


And lucky for me it worked.

Now getting one row of data is boring, we actually want to do scans.  So I started with the following.

scan = Hbase.TScan(startRow="someStartPrefix", stopRow="someStopPrefix")
scannerId = client.scannerOpenWithScan(desiredtable, scan)

rowList = client.scannerGetList(scannerId, 5)

while rowList:
    for row in rowList:
        mydata = row.columns.get("mycolumnfamily:mycolumnname").value
        rowKey = row.row
        print "rowKey = " + rowKey + ", mydata = " + mydata
    rowList = client.scannerGetList(scannerId, 5)


Again, I hit

TypeError: scannerOpenWithScan() takes exactly 4 arguments (3 given)

Just like getRow, there is a similar attributes argument I don't know what to do with. So I add a None argument to scannerOpenWithScan like so.

scannerId = client.scannerOpenWithScan(desiredtable, scan, None)

And this works and I get results.

Now, getting data with Hbase with start & stop rows is boring.  It's far more interesting to do filters.  How can we pass filters in Python?  Again, looking at the hbase1.thrift again, I can see what arguments TScan can take.

/**
 * A Scan object is used to specify scanner parameters when opening a scanner.
 */
struct TScan {
  1:optional Text startRow,
  2:optional Text stopRow,
  3:optional i64 timestamp,
  4:optional list columns,
  5:optional i32 caching,
  6:optional Text filterString,
  7:optional i32 batchSize,
  8:optional bool sortColumns
}


Hmmm, this filterString argument looks interesting.  But what to fill it with?  After I some Googling, I figure out it can be filled with functions you can find in the Hbase thrift documentation.

So here's some examples.

scan = Hbase.TScan(filterString="RowFilter(>=, 'binary:FOO')")

this is functionally identical to

scan = Hbase.TScan(startRow="FOO")

You can AND/OR things together.  So for example:

scan = Hbase.TScan(filterString="(RowFilter(>=, 'binary:STARTPREFIX') AND RowFilter(<=, 'binary:ENDPREFIX')) AND (RowFilter(=, 'substring:FOO') OR RowFilter(=, 'substring:BAR'))

Would find rows with the substring FOO or BAR within a range of STARTPREFIX and ENDPREFIX.

Well, that's as far as I've gotten.  There were a few gotcha points, so I hope that this helps somebody out there.

Friday, August 28, 2015

Looking back at "The Anatomy of a Large-Scale Hypertextual Web Search Engine"

I recently read the famous paper "The Anatomy of a Large-Scale Hypertextual Web Search Engine".  It's a paper written by the Google co-founders Larry Page and Sergey Brin circa 1997/1998 about their web search engine research while they were students at Stanford.  The very first sentence of the paper summarizes its contents quite well, "In this paper, we present Google, a prototype of a large-scale search engine ...".

The paper is very interesting looking back on it 17-18 years after it was published.  I thought I'd comment on some of the fun things I read.

Improved Search Quality

November 1997, only one of the top four commercial search engines finds itself (returns its own search page in response to its name in the top ten results)
If the above is true, it is truly comical by today's standards of web search quality.

Major Data Structures

Throughout this section, Brin & Page continually do "bit stuffing" to save storage space.  Typically only done by those dealing with firmware, I find it a little ironic that they had to go to such lengths.  Given the amount of data they had to deal and the amount of hardware resources they had, it was obviously justified.  But it's sort of funny to think about it given today's data sizes and hardware resources that Google, Facebook, Yahoo, Bing, etc. have.

Servers to Crawl the Web

The original Google used a single URL server to serve lists to 3 web crawlers.  Insanely tiny by today's standards.  Of course, it was a much tinier web in the 1990s.

Social Consequences to Web Crawling

Perhaps the best part of the paper, Brin & Page talk of the social consequences of their crawler.  Most notably, some website owners were confused at what a web crawler was and why they were looking at their page.  Some would e-mail them asking questions ... some even called them.

Storage Requirements

Apparently the original Google had a compressed repository of just 53GB of data.  Insanely puny by today's standards.

System Performance

In addition, it took only 9 days to download all of the data on the web at the time.  It's not clear how many machines were at their disposal, but it did not appear to be more than maybe a dozen (as said above, they only used 3 for web crawling, and they note they used 4 for sorting the index).

"Advertising and Mixed Motives"

In this appendix section Brin & Page talk about the conflict of interest that search engines have when advertising is involved.  They specifically site the search of "cellular phone" as a keyword and say

It is clear that a search engine which was taking money for showing cellular phone ads would have difficulty justifying the page that our system returned to its paying advertisers. For this type of reason and historical experience with other media [Bagdikian 83], we expect that advertising funded search engines will be inherently biased towards the advertisers and away from the needs of the consumers.
It's ironic of course, b/c this is nearly the exact opposite of modern day Google.  A search for "cellular phone" on the site returned for me (in order)

  • An iPhone ad on apple.com
  • An ad for cell phones off a retailer site
  • An ad for Sprint
  • A Google Maps result for several retailers that sell cell phones
  • The Wikipedia article for "Mobile Phone"
This doesn't count all of the ads that are on the right hand column.

Saturday, July 11, 2015

HPC Clusters vs Big Data Clusters: Two Different Worlds

Recently, I was thinking about why it's so hard for "HPC" cluster users to understand why "Big Data" cluster users do what they do, and vice versa. 

I wrote down this chart with a comparison of the software sometimes/often used on each:


Software HPC Clustering Big Data Clustering
Schedulers/Resource Managers Moab, Slurm, LSF, Torque, PBS YARN, Mesos
File Systems Lustre, GPFS, pNFS, PVFS HDFS
API "Framework" MPI, OpenMP MapReduce
Main Programming Languages C/C++, Fortran Java, Scala
Interconnect Infiniband, Myrinet, ... GigE
Higher Level Scripting ??? Pig, Hive


I could probably go on, but hopefully you get the gist of things.

Basically, everything listed under the "HPC Clustering" column isn't used on the "Big Data Clustering" column, and vice versa.

Here in lies the issue why the users of both don't understand each other.

I believe HPC cluster users look at the list on the right and immediately think things like:

  • "Why would you use HDFS, it's not a Posix file system."
  • "Why would you use Java, it's so slow."
  • "Why use GigE, that's so slow."
  • "Why did you write a whole new scheduler, why not use the schedulers HPC users developed years ago."
 In contrast, Big Data cluster users think nearly the opposite:

  • "Why would you use a Posix file system, that API/interface is ancient."
  • "Why would you use a networked file system, it's so slow."
  • "Why waste money on Infiniband, it's completely unnecessary to spend money on unused bandwidth."
  • "Why use MPI, the API is so complex, you can't develop programs quickly."
  • "Why use C or C++, the programming language is so complex, you can't develop programs quickly."

The problems users face are so different, that neither side can really understand why the other user would even bother to use the software/hardware that they are actually using.


So what happens when users in one world want to run in the other world?  I think what often happens is you hear "Can you port your code/application to work here?"  The answer is likely "No, that's not reasonable."  I believe you get these answers because most don't understand the difference between these two worlds because they don't understand the chart above.

So for those who are trying to mix environments, I think the most important thing to do is to try and accept the differences listed above and work for solutions that bridge the two worlds.

To some extent, that is part of my goal when developing Magpie (github).  Accept that the traditional HPC world isn't going to change and the Big Data world will not change either.  Better to try and get the Big Data world into HPC clusters with as little change as possible.

Update: See "Big Data vs HPC" follow up.

Sunday, June 14, 2015

The Best Interview Answer I Ever Heard

There's been much written online about the best way to interview, the best candidates to look for, the qualities of top engineering talent, etc.

There is one singular quality I look for in any candidate, regardless if they are a system administrator, software engineer, or any technical position.  It's the ability to research and learn.

I was interviewing a system administration candidate for another group and the classic question I ask is, "When moving from administrating a few machines to 1000s of machines, what difficulties do you imagine you'll come upon?"

This particular candidate had actually setup and administered a small 16ish node cluster before and said something along the following:

When I setup this cluster, I realized FOO was running really slow.  I went online to see how other people solved the problem.  I found someone else who used pdsh to make FOO run better.  So I downloaded pdsh, set it up and FOO was working better.

I can't even remember what FOO was, but it was really irrelevant.  The candidate:

A) Realized something was running poorly or sub-optimal

B) Researched online a mechanism that would be better

C) Set it up/implemented the solution

D) The solution was deemed much better than the prior situation

Because my group had developed pdsh that was sort of bonus points for the candidate, but I absolutely loved this candidate's answer.  It was so simple and basic, yet illustrates exactly the quality that you want in an engineer.  Going online to research, learn, figure new things out, and find better solutions.  It's actually a quality that is often difficult to find in many candidates.

Thursday, February 5, 2015

Hadoop Job Submission Errors

Ugh, for the life of me I couldn't figure this out today until the "Duh ... I didn't do ..".  We all have those days.  Hopefully this will help someone out there a little quicker.

I couldn't submit a small Hadoop job today and was repeatedly getting errors like this:


Error: java.lang.RuntimeException: java.lang.ClassNotFoundException: Class FOOCLASS not found
        at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1961)
        at org.apache.hadoop.mapreduce.task.JobContextImpl.getMapperClass(JobContextImpl.java:186)
        at org.apache.hadoop.mapred.MapTask.runNewMapper(MapTask.java:722)
        at org.apache.hadoop.mapred.MapTask.run(MapTask.java:340)
        at org.apache.hadoop.mapred.YarnChild$2.run(YarnChild.java:168)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:415)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1594)
        at org.apache.hadoop.mapred.YarnChild.main(YarnChild.java:163)
Caused by: java.lang.ClassNotFoundException: Class WordCount$WordMapper not found
        at org.apache.hadoop.conf.Configuration.getClassByName(Configuration.java:1867)
        at org.apache.hadoop.conf.Configuration.getClass(Configuration.java:1959)
        ... 8 more 

The key line of error output was:

WARN mapreduce.JobSubmitter: No job jar file set. User classes may not be found. See Job or Job#setJar(String).

After Googling I tried all the normal expectations.

1)

Make sure the jar has all the classes in it that it's supposed to have.

2)

Make sure you're calling job.setJarByClass() in your code.

3)

Make sure the permissions on the jar file are correct.

But still couldn't get it to work.  Then a stackoverflow post suggested calling job.setJar() to manually set the jar by it's full path.

This worked.  Why?

Duh ... Hadoop couldn't find the jar submitted in question.  So step 4 to try.

4)

Make sure your jar can be found in the environment variable HADOOP_CLASSPATH.

An alternate option may be to ensure your jar is the classpath of   yarn.application.classpath.  But I didn't try this.

Thursday, May 29, 2014

Big Data vs. HPC

I wrote a blog post awhile back on "HDFS vs. Lustre".

The primary point of that post was that it was not reasonable to compare HDFS to Lustre.  Although I have never worked with other networked file systems like GPFS, Panasas, and pNFS, I believe the same argument can be applied to them as well.  Those networked file systems serve such completely different purposes and have completely different architectures that doing an apples to apples comparison is difficult if not impossible.

So I saw this article recently on Datanami, "Making Hadoop Relevant to HPC".

I felt the need to discuss many of the comments discussed in this article.

Lockwood argues, is that Hadoop “reinvents a lot of functionality that has existed in HPC for decades, and it does so very poorly.”

I can agree that Hadoop reinvents some functionality.  Most notably job scheduling and resource management is something HPC has done for a long time.  However, to my knowledge, HPC has not had a scheduler/resource manager that tightly integrated the filesystem with the job/task scheduling itself.  Therefore the need for the Hadoop community to make their own resource manager.  If you want to criticize the Hadoop community for not using the currently available open source resource managers and writing a plugin?  Ok, that's decently fair.
For example, he said a single Hadoop cluster could support only three concurrent jobs simultaneously. Beyond that, performance suffers.
I'm not really sure where the "three concurrent jobs" comes from.  This makes no sense to me.  I suppose it's possible that Hadoop's default scheduler elects to give priority to jobs differently than what is expected from a traditional HPC scheduler, but that's easily rectified through some mods to the priority queue algorithm.

I can believe that performance may suffer as you add more and more users.  After all, HDFS daemons sit on each node and may get busier and busier as you have more users.  However, I could make the same argument of traditional HPC file systems.  The more and more users you add to them, the busier the file system gets.  At the end of the day, you can only pump so much data through a network link.
Lockwood maintains that Hadoop does not support scalable network topologies like multidimensional meshes.
While technically true,  Big Data applications are programmed and designed in a completely different way.  They may not necessarily benefit from such advanced network topologies.  It's possible Lockwood has some specific applications he's thinking of that could benefit, but I would disagree with this statement for the general problems being handled.
Add to that, the Hadoop Distributed File System (HDFS) “is very slow and very obtuse” when compared with common HPC parallel file systems like Lustre and the General Parallel File System.
Now this comment I'm going to take a little more time to discuss.  Reiterating some of my points from my earlier "HDFS vs. Lustre" post, this is comparing apples to oranges.

The correct comparison is "MapReduce over HDFS/Local Disks vs. MapReduce over Lustre."  This is the real comparison.

MapReduce creates many small files during it's shuffle phase.  Does Lustre/GPFS perform well with small files compared to local disk

MapReduce performs many random-like seeks/reads during its shuffle phase.  Does Lustre/GPFS perform well with random reads compared to local disk?

When your data problem exceeds system memory and you need to spill contents to disk temporarily, will temporary scratch spills be faster to local disk or a networked file system?

I could go on and on and on with this argument.

The point is, is HDFS not as flexible as Lustre or GPFS?  Yes.  But does it serve its purpose better than Lustre/GPFS?  I think the answer is yes it does.

Hopefully in the near future I will be able to point to online published results illustrating this fact.

Thursday, February 13, 2014

HDFS vs Lustre

There's been discussion out there about comparing the HDFS filesystem to a traditional parallel filesystem like Lustre.  The problem is it's really difficult to compare apples to apples.

As an example, I saw a white paper awhile back (sorry, I can't find it online) that compared HDFS to Lustre.  HDFS beat Lustre in this person's performance tests by a good margin.  After digging into the paper I saw why.  This fellow ran Lustre over a 1 GigE ethernet network. 

Is this a fair test?  On the one hand it isn't because Lustre is a network based filesystem.  If you simple choose to bottleneck Lustre, of course it will lose.   On the other hand, it's a fair test, because it uses the same hardware most use with HDFS.

So lets say we replaced the GigE with Infiniband.  Would it now be a fair test?  Perhaps its slightly fairer, but HDFS people can say HDFS wasn't designed for more expensive hardware and therefore doesn't take advantage of it.  In the case of Infiniband, HDFS isn't using RDMA during replication.

I don't know the right comparison.  However, HDFS vs Lustre may not be the correct comparison to think about.  At the end of the day, I could probably concoct an HDFS setup that will always beat a Lustre setup and vice versa.

I believe thinking about this as HDFS vs Lustre isn't the right approach.  It's really Hadoop Cluster vs HPC Cluster.  At the end of the day, while Hadoop is famous for handling large data, the reality is because of shuffle/sorting/scheduling/etc. in Hadoop, it also reads/writes tons of small files.  The memory for a Hadoop Cluster vs HPC cluster may also be different.  That affects spilling of data, page cache, etc.

Update: See "Big Data vs HPC" follow up.
Update: See "HPC vs Big Data" follow up.

Update 6/2/15:

Not so long ago I was talking to someone about the HDFS vs Lustre comparison.

Many people have done HDFS vs "Some Networked Filesystem" experiments.

However, I think these experiments are inherently flawed.  The experiments always look something like this.

Datanodes
8 nodes
4 SATA disks
8 core
32G RAM

Networked Storage
4 nodes
8 SATA disks
8 core each
32G RAM

with additional hardware details beyond this.

The comparison will be HDFS using the Datanodes for data & map reduce.  Then it'll be a comparison to the Networked Storage, also using the Datanodes as the computation facility.

Do you see the inherent problem in the above comparison?

.
.

It's staring you right in the eyes.

.
.
.

It's an 8 node test vs a 12 node test.

It's a 256G RAM test vs a 384G RAM test.

This isn't to say that the comparison is poorly done.  But this is part of the inherent problem of comparing HDFS vs Networked File systems.  What is a fair comparison?



Wednesday, February 12, 2014

Big Data vs. HPC/Supercomputing

There's been a lot of articles about what is "Big Data" and how does it compare to traditional Supercomputing and High Performance Computing.  I thought about it, and devolved it into a simple mathematical statement.

In Supercomputing / HPC

Computation Time >> IO Time

and in Big Data

IO Time >> Computation Time

The architecture of the hardware, the networking solutions, the software you use, how you design your software, etc. etc. is centered around this simple statement.

Friday, December 13, 2013

Why bother to have specifications ...

Ugh ... a very annoying e-mail thread from earlier this week.  For the record, I'm not attacking the other fellow on the other end of this thread.  They're just doing their job too.

Company: We noticed in your open-source software that you output X incorrectly.  Please look at this other open-source software Y to see how it should be output.

Me: Please look at standard Z.  According to standard Z, I'm doing things correctly.  Here's the code snippets to show it.

Company: Hmm, you're right.  I guess a number of vendors are not properly sending the data in the right format.  Unfortunately, we can't get all those vendors to change the format.

Me: Well, how about I add a workaround option on the command line.  Those who are knowledgeable of this subject matter can specify it if they want to.

Company: We tried out your workaround option and it's almost correct.  A few bytes were flipped in the output.

Me: Huh, that's strange.  The first few fields are sent little-endian, but the latter few fields are sent big-endian.  This is really weird.

Company: For legacy reasons, it appears large company A has been doing this, so I guess vendors have followed suit.

Thursday, November 7, 2013

The Baseball Scheduling Problem

Came upon this ESPN video at random the other day.

http://www.grantland.com/story/_/id/9930115/our-latest-30-30-documentary-short-tells-story-how-husband-wife-ended-creating-schedule-mlb

For years I had assumed that baseball (and all professional sports) had used computers to determine their season schedules, but apparently the scheduling problem was so difficult and so complex, human beings did Major League Baseball's schedule by hand until 2004.  The couple highlighted in the video did it for about 20 years.  Apparently multiple companies and research universities (MIT, Stanford, Carnegie Mellon, IBM are mentioned) failed to come up w/ schedules in the 80s and 90s.  In some cases, it was not failed to come up with "good schedules", but apparently failed to come up with a schedule at all.

The scheduling problem seems mighty complex.  The scheduling conditions below are from the video and my own knowledge of baseball.

  • 30 baseball teams, each plays 162 games (2430 games total)
  • The schedule is unbalanced, teams in the NL or AL play within their league more often than the other (15 teams per league).
  • Teams within divisions play each other more often than other divisions in the league (5 teams per division).
  • Teams cannot play any other team in the other leagues (interleague play) but only specific ones in certain divisions.
  • Cities w/ two teams (Chicago, NY, etc.) must not be in the city at the same time on specific days (especially weekends and such)
  • Special games are scheduled in for specific rivalries.  e.g. New York Yankees and New York Mets will play each other each year no matter what.
  • For ratings/ticket sales, specific rivalries (intra division or otherwise) must be scheduled at specific times. e.g. intra-division battles almost always must be scheduled at the end of the year in September.  e.g. Boston vs NY or St. Louis vs Chicago games should almost always be on weekends.
  • A specific number of rest days are mandated for each team.  They must be distributed evenly throughout the year (i.e. not back to back).
  • Rest days must be scheduled in when long travel occurs (e.g. west coast teams going to east coast).
  • Traveling must not be unbearable (e.g. you can't schedule team to play in NY, then LA, then Miami back to back to back).
  • Each team has special requests to be home/away on certain dates b/c of special occasions or city specific events.  For example the SF Giants may not want to be in town during Fleet Week.
  • Scheduling must be fair and equitable for holidays.  For example, it would be unfair to never allow a team to have a home game during the July 4th weekend.  In addition, you must handle Canadian holidays.
  • Some teams may share their stadium with other professional sports teams, so that must be handled.  Although this constraint certainly existed in the past, it may not exist anymore (off the top of my head, St. Louis, San Diego, San Francisco, and Houston used to share their stadiums but no longer do).  Although I'm sure special case handling probably still exists (e.g. state championships, conventions, etc.).
I'm sure there are even more constraints that they don't mention and I can't think of.