TwinTechs

Dream, Create, Deliver…

Go: Google’s new language on a test drive.

November 12th, 2009 Written by: Jesse Dailey · Uncategorized

So, the folks at Google have been as busy as ever.  They just released a new language Go.  It has a loosely C-like syntax, compiles directly to native code, and is meant to be a low-level “systems” language.

I happened to be right in the middle of performance-tuning a FastCGI library in Python, with a focus on concurrent I/O problems.  This means I was also right in the middle of being frustrated with Python’s poor support for concurrency.

So, when I read about Go’s emphasis on concurrency without threads (a focus of my current efforts to use asyncore to avoid threads in Python), I couldn’t resist learning enough of the language to compare it’s network I/O performance with Python.

I wrote a quick Echo server (40 lines of code) this morning, and was impressed at how quickly it was going.   Then I looked at the executable, 850kB!  Ok, so, we will have to forgive them for having some unoptimized build tools for now.  At this point I was already not excited about the potential for getting a meaningful performance comparison, but I was still interested to learn more so I decided to get more coffee, and go ahead and do a quick and dirty implementation of FastCGI.

The server works by running one master loop that accepts connections, creates new “goroutines” to handle each connection, and since in FastCGI each connection can potentially multiplex requests over one connection, each of these handlers spawns a “goroutine” for each request.  I’m pretty sure that I am using a couple too many, or too few, channels, but it’s a working library in one day.

For a language that is not intended to be about coding productivity, I am quite impressed at how quickly I was able to do the things I needed.  The documentation is decent, and every documentation page links directly into the source code, so it encourages reading the source, which can be very helpful with something this young.

So far, I would describe the language as immature, but promising.  Other people have complained about the lack of generics, but for a “systems” language, I can understand why they aren’t a priority.

My biggest problem  is that their asynchronous implementation of network I/O is incomplete.  While all the main socket system calls like Read, Write, Listen, Connect, etc. are internally made safe for use by “goroutines”, the Close() system call exposes a race condition when one “goroutine” is creating sockets, and another is closing them.  Hopefully, this is just a growing pain that will be ironed out soon.

For now, my Go implementation doesn’t come close to my Python library (the Go is about 40% the speed of the Python)… but it’s nothing close to a fair fight yet.

→ No CommentsTags:

Suba: Fast text templates in Python 3.0

November 8th, 2009 Written by: Jesse Dailey · Technical, innovation

There are many template engines available for Python already; Mako, Tenjin, Evoque, Cheetah, etc.

Unfortunately, many of these do not support Py3k, and of the ones that do, none of them were building their template objects the way I felt it should be done: by using python’s AST [abstract syntax tree] objects directly.

So, I wrote Suba.

Any of the template engines worth their salt use the text template to create a python program, then compile that program to byte code.  The byte code is typically cached, and exec() is used to run it for each rendering request.  Outside this central theme are a few variations; some of the systems generate a module (instead of just a script) and then import it rather than exec(), some cache to disk, some to memory, etc.; but, none of them create an AST.

The difference in using the AST is that there is no initial text stage; the language objects are instatiated directly.

For instance, the following template in Suba:

Hello, %(name)!

Would produce the following AST tree (some arguments omitted for brevity):

FunctionDef(name='execute', ..., body=[
  Expr(value=Yield(value=Str(s='Hello, '))),
  Expr(value=Yield(value=Name(id='name')),
  Expr(value=Yield(value=Str(s='!')))])

When combined with a post-process walk of the AST, this  allows you to tune and manipulate the code generated from a template with precision that you can’t get when using code-strings.  (As an aside: the python-savvy have noticed that all templates become a  generator, the wiki has some discussion about why this works well).

For instance, suppose you want to filter whitespace from the output.  We could wrap the output in a whitespace filter,or, we can walk the AST tree and edit all the Str() nodes before the code even compiles.  So, when we cache the compiled bytecode, it doesn’t even contain the instructions that would emit the whitespace, meaning that we get this additional feature along with a reduction in run-time.  This is something that would be very difficult to do quickly and cleanly on a code-string using regex and string.replace().

This produces faster templates than the fastest competitor libraries (at the moment, the pool of Python 3.0 supporters is small enough for this to be true).

Here is an example, using Tenjin’s own benchmark templates and data:

tenjin_test: 2864.37 pages/sec (in 3.49 seconds)
suba_test: 5801.79 pages/sec (in 1.72 seconds)

→ 1 CommentTags: ···

The Value of Design Patterns

July 23rd, 2009 Written by: Jesse Dailey · RIA, innovation, user experience

Design Patterns have always made me bristle a little bit.  Maybe it’s just my inner contrariness but I believe that each problem has it’s nuances and that too much faith in Pattern will make you graft simple pre-made solutions on to complex real-life problems.  I’ve always felt that it’s necessary to know the patterns, to have them in your tool-belt as a starting point for ideas, but that to be insistent about, or dependent on, the Design Pattern, confuses Pattern with Solution; the Starting point with  the Finish line.

Sadly, I am not so articulate as this guy when it comes to this issue: http://blog.plover.com/2006/09/11/

On the face of it, his claim is that Design Patterns represent “signposts to the failures of the programming language”.

I think his larger claim is about the evolution of languages; that each language should be looked at as just the middle ground on a long uphill climb toward more expressive power, and that each Pattern codifies the frustrations of the programmers using it to do these often-needed things.  To drive innovation, he would say, one should always be looking for ways to take Design Patterns and co-opt their power by making them invisible.

I couldn’t agree more.

And the corollary of course is that Design Patterns should be bristled at, used grudgingly, and as the starting point for discussion.  Another way to say it might be, compliance with a Design Pattern is not a very good measure of Quality.

→ No CommentsTags: ···

Evaluating the Quality of Designs

July 21st, 2009 Written by: Jesse Dailey · RIA, writings

One of the most important tasks that an engineer or architect is asked to do is evaluate the quality of a potential design.

I’d like to present here an informal framework for reasoning about what makes a good design.  I think these rules apply to all human-facing products: software, architecture, etc.

So, without further ado, I think the rule for good design is: taking something non-trivial, and providing a trivial user interface.

This applies not only to software, but the design of anything useful.

Take for an example, a bridge.  Given the non-trivial task of getting something heavy (that doesn’t float) across a river, a bridge provides a trivial interface.

To better formalize this, I propose the following formula, the Quality Quotient:

Q = 1 – (triviality of new interface / triviality of old interface)

For simplicity’s sake, I will use a scale of 1-10, where 1 is very easy, and 10 is very hard.

In the bridge example, if you are on one shore in a heavy truck, and need to get to the other side and have no bridge, I’d call that a 10.

With a bridge in place, the use case is as trivial as it gets: keep moving forward. I give that a 1 on the scale of Moving Things Around.

So, Q(bridge) = 1 – (1/10) = .90 = 90% awesome design.

No wonder they have stuck around. It could only get better if somehow we instantly teleported across.

Now, my claim is that the process of making anything complex involves the iterative process of choosing between competing designs for the system as whole, and subsequently for each component. Successfully making something that works and is useful and usable, involves only allowing your self to make choices that score highly.

Another example, this one from the software world.  What makes some code libraries stick, and others fade away?  Take the javascript library jQuery as an example. The initial problem is two fold: dealing with the variations among browsers, and finding a natural way to deal with so much tree-like data in a procedural language. On the scale of software annoyances, I give this problem a 6.  It’s been done several times, so it’s very doable, but you still don’t want to do it yourself.

Jquery takes this non-trivial problem and wraps it up in a safe and simple package where not only are the browser-dependent features smoothed out, but the actual language syntax is flexed to its limit to provide for a more natural way of finding and mapping operations over sets of DOM nodes.  I give it a 2 on my made-up scale… there is maybe room for improvement, as real-life software is always evolving and improving, but they have succeeded in hiding the most cumbersome pieces.

Q(jquery) = 1 – (2/6) = 66% awesome.

If you aren’t using any javascript library, here is a successful one.

This reasoning on many individual levels becomes, on a macro level, the definition of success or failure for a code library, or product.  If you wanted to compete with Jquery you would have to either tackle more complexity (solve a bigger problem), or solve the same problem with a simpler interface, or some combination of the two.

Another example, this time from the mobile world, and this one comes with a prediction (like all good pseudo-science).

The WebKit rendering engine. WebKit is the rendering engine used in the iPhone, Android OS, and the Palm Pre. The problem faced here is one of rendering degenerate HTML into what the author intended, and it is one of the trickiest problems in web software development today.  It’s so hard in fact that no one does it correctly, or even the same, not even WebKit.  On a scale of software challenges, that makes it a 10 in my book.

Because WebKit is open-source and has a rich community and it supports such a broad range of contexts, it’sthe kind of thing that an experienced programmer can get to render html in relatively short order.  Orders of magnitude faster than trying to render it yourself.  But it certainly is not as easy as possible (I think in order to get a 1, you have to be functional with a couple of lines of code), so I give it a 2.

Q(webkit) = 1 – (2/10) = 80% awesome.

My prediction here is that WebKit and other’s ability to render degenerate HTML has crossed the threshold of good enough, and the barriers to success are now more heavily weighted on ease of implementation and flexibility of context.  Since WebKit scores so much higher in these areas than other browser options, I think WebKit is going to become the reference HTML renderer, on mobile platforms and elsewhere.  Probably not an earth-shattering prediction, but there it is.

So far, all our examples have been positive-valued successful examples, but there are two other ranges of scores that are very interesting: near 0, and less than 0.

Scores near zero mean that you are just wasting time.  The Auto Industry is a good example of this:

Cupholders; taking a pretty trivial initial problem, and giving it a trivial solution.  No surprise that few people really care.

Q(Cupholders) = 1 – (1.5/2) = 25%

Vehicle Diagnostic Computers; diagnosing and correcting vehicle components is difficult and nuanced at best, but after a generation of adding expensive maintenance computers, we’ve just shifted the complexity to learning how to operate, diagnose, and correct the diagnostic computers.

Q(Vehicle Diagnostic Computers) = 1 – (8/9) = 11%

From the average consumer point of view, practically nothing has changed in 25 years with regard to getting their car serviced.

The lowest range, less than zero, represents those times when people over-think a problem, or over-engineer solutions.

The early years of the web are a good source of such things.  Take the success of Google, which hinged in large part on their streamlined interface.

The problem a search engine faces is certainly not trivial, and it comes in two parts: specifying what you want, and then finding it.

In 1999, when Google came out, Yahoo and AltaVista were the search engines I remember, and I remember them both looking like this:
Yahoo.com circa 1999

Now, we are looking at just the part of this task where you specify what you want, and Yahoo decided that a Taxonomy of Everything was the best solution.  Their idea was very Renaissance in a way: that they could file everything neatly into these categories, and users would naturally understand the categories they made and use them to find what they want.  But, the last several hundred years have not been kind to this idea that taxonomy alone can tackle complexity.

So, Yahoo starts with a problem that to the user (inside his own head) is quite easy; I know what I want, in some internal language.  So, to me, this is one of the easier things that people do: communicate what they want, once they know.  It’s not the easiest thing in the world, since we mess it up all the time; and Natural Language, while wonderfully nuanced, is often not precise enough.  So, all in all, I give it a 3; not that hard, but sometimes subtle or tricky.

Yahoo takes this problem of getting what I want out of my head, and they decide they are going to try and tease it out of me by asking a whole lot of hierarchical questions: “Is it an Automotive thing you want? An Entertainment thing?  How about one of these Quick Links, maybe they would be Quicker?”.  Once I answer that question, it asks slightly more refined questions, “Is it Dining, or Music related? etc.”  This process, as anyone who remembers the web of 1999, could take hours to find what you want, and you might have to answer hundreds of little questions along the way.

If expressing what you want is a 3, Yahoo gave us a solution that’s a 5; its do-able, in fact it might often succeed, but it is a painful and arduous journey with more missteps available then correct ones.

Q(Yahoo 1999) = 1 – (5/3) = -66%

Now, this doesn’t mean that the world got worse when Yahoo came around, we are only looking at the first half of their problem; and for this one specific facet, they didn’t “bring the machine to me”, they tried to force me to think like a machine, to sub-divide and re-divide the world in a way that is very un-natural.  So they did make this process of identifying what I want harder than it was.

Along comes Google with the absolute simplest interface you could possibly create.  It’s so simple you can even skip the results page. You do the same thing you would always have to do: condense your inner language to relevant Natural Language keywords.  So, Google replaces a 3 with a 3.

Q(Google 1999) = 1 – (3/3) = 0%

You can see where this is going.  Google did not try to solve a bigger problem, they just presented the simplest possible interface to the one at hand.  They let the natural work, that my brain had to do anyway, fall directly out onto the interface.  Now, they can focus on the technologically difficult part, the second part of the problem: actually finding what you want.

You can also see from this how far we have to go. We are stuck in a primitive world of text, with limited keywords, and a poor grasp on the conceptual structure of most problems, except bridge-building.  We got that one down now, only after several millennia of small improvements.

Whenever you are evaluating designs, you must ask yourself these questions: “Am I tackling a non-trivial problem?”, and “Am I providing a trivial interface to that problem?”.  If the balance of these questions is not right, you must bravely return to the drawing board.

→ No CommentsTags: ···

Gzip compression errors on mobile webkit browsers

December 14th, 2008 Written by: Jesse Dailey · Uncategorized

Over the past several days we have been working hard on a mobile web application, and seeing a mysterious problem on the iPhone and Android web browsers.

Both claim to support gzip, they both send ‘Accept-Encoding: gzip, deflate’ with each request.  But, whenever I would try to return gzip data (along with ‘Content-Encoding: gzip’ headers), Safari would return “cannot decode raw data”, and Android would say that the “Web Site is unavailable.  The server failed to respond.”

After much hair pulling the problem turned out to be a rather subtle bit of socket play on the server.

The web application serving the compressed files uses FastCGI to talk to lighttpd, the webserver.  When the fastcgi request is launched (as a process), it’s stdout and stderr are redirected to lighttpd.  But, as I was returning the response by calling write() on stdout, I was also calling flush() all the time.  Even though this shouldn’t matter, the data should just build up on the other end (and in fact does do this properly in Firefox and Chrome), on iPhone and Android browsers, as soon as the flush() landed on a ‘\n’ (found randomly in the middle of the compressed stream), the browser would think the data was complete and try to decompress it, and fail with the above errors.

In my case, the solution was to make sure that I was consolidating the code down to a single call to write() followed by a single flush().

→ No CommentsTags:

How to Find What Function Is At a DLL Offset (without having debug symbols)

November 7th, 2008 Written by: Jesse Dailey · J2EE, LiveCycle

How to Find What Function Is At a DLL Offset (without having debug symbols):

This applies to all applications, but this specific example comes from Adobe LiveCycle.  The PDF Generator was crashing mysteriously, producing errors in the event log:

“Faulting application pdfgen.exe, version 1.0.0.1, faulting module ntdll.dll, version 5.2.3790.3959, fault address 0×0002eb5a”

This is a particularly annoying kind of error when its not in an application you control, since you don’t have any idea what 0×0002eb5a means without access to a build with debugging symbols.

To find out more, here’s what you need.

First you need a debugger.  The free option of choice for many people these days is OllyDbg (download here http://www.ollydbg.de/odbg110.zip)

It’s a simple applicaiton, so just extract it to a folder someplace and run it.

Once inside, File > Open, browse to the crashing dll, in this case, c:\windows\system32\ntdll.dll

It will ask if you want LOADLL.exe to load the dll for you, say Yes.

Once inside, note the starting offset.  It will vary based on the dll and the OS, but in my case the first address was 0×78001000, which means the base is at 0×78000000 (the trailing 1000 will be the same on all systems, its the first part you care about).

So, our application is crashing at offset 0×0002eb5a.  The reason its called an ‘offset’, is because it is ‘offset from the base’, so add 0×78000000 to 0×0002eb5a = 0×7802eb5a (Windows Calculator in Hex Mode can help you with this if your base is not an easy one like ours).

Scroll the debugging window to this address.

In OllyDbg, the beginning of each function is labeled with a $ sign.   The address we scrolled to should be in the middle of a function, so scroll up the start of the function (the first $ above it) and write down its starting address.  In this case, the function starts only a few bytes earlier, at 0×0002eb4e.

Open the menu: Debug > Call DLL Export.  On this window at the top there is a drop down labeled Export:, open this and scroll down to find the offset of the function you wrote down.

This should give you the textual name.  In my case, this name was ‘RtlLengthSid’, a quick google for this reveals it is a windows system call for computing the length of a security identifier.

From this, it was an easy leap to see that something in the LiveCycle environment was working with a user account it didn’t support.  This, ultimately, was enough for us to diagnose and fix our problem (by starting WebLogic’s NodeManager as Administrator, rather than Local System, the installation’s default).

→ No CommentsTags: ··

SP1 installation bug

November 4th, 2008 Written by: Jesse Dailey · LiveCycle

Adobe released SP1 for LiveCycle 8.2 last week, and in using it this week, we’ve run in to some issues.

The first issue is an actual bug in the installer, and has an easy workaround.

While running the LiveCycle SP1 installer, the install goes fine and all the files are copied over, but then at the last step of the install, when you select the ‘Launch Configuration Manager’ checkbox, and hit ‘Next’.

The following error appears:
‘Could not find the main class. Program will exit.’

This is the result of a bug in the installer: it assumes that you installed the JDK in the default location. (You can verify this in the patchinstalls.log file, where it writes out where it is looking).

If you installed somewhere else, or have re-configured to use an alternate JDK, you have to launch the Configuration Manager manually at this point.

You can do this with the file: …\LiveCycle 8.2\configurationManager\ConfigurationManager.bat

The second problem is more complex and still in the works.  But, if other people are seeing this error after the upgrade:

<An exception was thrown with name com.adobe.idp.dsc.pool.service.impl.ServicePoolAlreadyExistsException message:Pool for service id OutputService, major version 1 and minor version 1 already exists while invoking service OutputService and operation generatePDFOutput and no fault routes were found to be configured.>

Followed by a long series of ‘ServicePoolInstancesExhaustedException’… Stay tuned… I’ll have an update for this one soon.

→ 3 CommentsTags:

Upgrading LiveCycle 8.0 to LiveCycle 8.2

October 24th, 2008 Written by: Jesse Dailey · LiveCycle

While doing an upgrade for a client, from 8.0 to 8.2 of LiveCycle, we ran into a very strange problem that seems to have gone undocumented elsewhere.

Near the end of the upgrade, it hits the step: Migrate Data Essential to LiveCycle ES Operation

This loads a series of plugins, each that migrates its own pieces.

But right away, the Forms plugin dies…

[11:38] ALC-UPG-001-501: Executing [Forms] plugin …
[11:38] ALC-UPG-001-503: [Forms] plugin execution failed, error message from plugin is [While trying to lookup 'com.adobe.idp.config.remote.PreferencesSPIRemoteHome' didn't find subcontext 'com'. Resolved ''].  See LCM logs for details.

Seems that there is a classpath problem in the installer.

Engineers inside Adobe assure us that a fix is in the works… will post another update once we find out more.

→ 1 CommentTags:

SQLite Day of the Week for Trac

May 27th, 2008 Written by: Jesse Dailey · MySQL, Technical

SQLite is lacking a DAYOFWEEK equivalent. However, here is how to roll your own.

select case ((changetime / 86400) - 4) % 7
     when 0 then 'Mon.'
     when 1 then 'Tues.'
     when 2 then 'Wed.'
     when 3 then 'Thurs.'
     when 4 then 'Fri.'
     when 5 then 'Sat.'
     when 6 then 'Sun.'
     end as day_of_the_week
from ...

And yes, the epoch started on a Thursday.

→ 1 CommentTags:

PHP 5.2.5 Stored Procedure support

May 13th, 2008 Written by: Jesse Dailey · MySQL, Technical

After some hours of digging, it turns out that the mysqli module in PHP 5.2.5 has a critical bug if you want to use stored procedures. The fix is simple, but since it took me hours to find, I’ll post it here.

Basically, in 5.2.4 there was a change to the connect() code to always disable the CLIENT_MULTI_STATEMENTS option (passing this to connect is now ignored). But, implicitly under the hood, this option also enables CLIENT_MULTI_ROWS, and the mysqli module relied on this fact, never setting CLIENT_MULTI_ROWS directly itself. Unfortunately mysqli_multi_query() requires this option, and using CALL() in a sql statement requires multi_query().

So, this is fixed in CVS, but for those of us who need to run production systems compiled from otherwise stable source, a CVS tree is too wild, so here is the patch you need. Apply it to ext/mysqli/mysqli_api.c:

PHP mysqli Patch

→ No CommentsTags: