Musing on Advertising

So I’ve been giving some thought about advertising in general. After all, for the past three years I’ve been peripherally associated with advertising of one form or another — and all of it that particular breed of advertising called local advertising. (Anything that tells you what’s going on around you is a type of advertising — so I count Geodelic as a form of advertising, though it was only handling the presentation part, not the monitization of the presentation part.)

And it’s interesting. Interesting in the sense that there is a real psychology to advertising particular to certain categories of advertisers — and that psychology is, in my opinion, not being captured in the “one size fits all” form of advertising being offered through the Internet. I contend that, in the Internet’s rush to better slice and dice the customers, to create better focused advertising for those customers based on previous purchase patterns and demographics through automated matching algorithms, the quality of the advertising offered on the Internet has become more generic and less focused on the advertiser.

In other words, in concentrating on the customer the Internet is forgetting the message.

Just sitting here at my desk, I can think of three different types of advertisers.

The first, such as restaurants, toothpaste manufacturers and providers of services we use every day, would be more interested in getting people to remember who they are so we’re more likely to buy their products when the time comes (once a week at the grocery store, or every day as we walk out of the office building to get lunch) to think of them as we make our decision. Advertisers like that are probably less concerned with things like individual conversions based on click through rates through Google — because the profit for a conversion is practically non-existant. (Do you think an ice cream store will willingly pay $20 for a single conversion — a single customer purchase based on a click through from Google — for a $5 large scoop, which nets perhaps $4 gross profit and perhaps 50 cents net?)

That type of advertiser wants repeat customers. They can’t justify a $20 conversion if that conversion only results in a single sale — they need an ongoing and constant repeat customer base.

A second type of advertiser is an advertiser who provides a service that you’re probably not going to constantly use or repeatedly call. Unless you’re a rich asshole, you’re probably not going to be a repeat customer to a divorce lawyer. Unless you’re a building contractor, you’re probably not going to need a plumber on call. Many services like this are services you don’t even think about needing until you need it: you probably aren’t going to be on first name basis with your auto mechanic — unless you either have an old car and he’s a friend, or you’re into cars and need someone constantly on call to help with your new finds.

These people are ideal targets for something like a Google SEM campaign or a Yellow Pages ad: you don’t know you need them until you need them — and when you do, you’ll explicitly search for one. Car broke down? Google “auto mechanic los angeles” and start calling.

A third type of advertiser is an advertiser who is selling an aspirational good. By “aspirational good” I mean a product which is a major purchase, but which you’re not going to immediately impulse buy. Refrigerators for a new house, a toilet for a remodeled bathroom, a car, a new computer, a new expensive watch: all these things are goods which you’ll probably do a lot of research deciding if you want to buy that good. Factors such as “am I a Toyota driver or a Honda driver, or maybe I can squeeze into a BMW” — that is, does the good match who you see yourself being — come into play. You’ll probably ask friends or muse over the purchase. Me: I tend to seem impulsive when I buy something expensive, such as an iPad or a new computer — but trust me: I only seem impulsive because I don’t share my internal thought processes. The iPad purchase only seemed impulsive because I didn’t share the fact that I was reading every rumor, every scrap of information, and scouring the iPhone OS documentation and header files for every scrap of information for a year prior to making a purchase.

When I bought my current car, I mused over that purchase for two years. Remodeling the deck? About 18 months. And so forth.

There is a real psychology to aspirational goods, by the way. Entire magazines (such as GQ or Esquire for men, or Cosmopolitan for women) exist which are essentially curated ads for various products. (GQ, for example, runs entire articles on the best watch for men to wear.) These curated magazines essentially tell people what sort of people wear what sort of products — essentially helping to define the aspiration that may cause someone to spend $2,000 on a watch or $350 on shoes. It used to be that other types of products were also advertised as aspirational products — such as air travel, with their beautiful air stewardesses in short skirts, or (in an earlier age) train travel being enjoyed by the rich and famous of their era. All BMW advertising is aspirational advertising, for example: “The Ultimate Driving Machine” is well positioned as something a wealthy but secret sports car driver wants to drive.

And aspirational advertising also serves to remind the people who already purchased their product that the purchase was a smart one by reinforcing the aspirational stereotypes associated with the product. They help confirm the purchase, and make you feel good so that, perhaps 3, 5 or 10 years from now, when the lease is up or the old car is done, you buy a newer model of the same car.

Aspirational advertising is not restricted to just a $2,000 watch or a $60,000 car, however: cooking magazines apply the same logic (aspiring to be a better cook) towards $30 cooking pans and $5 egg timers. There is a reason why a store like Sur La Table will carry things like $12 mango slicers that almost no-one will buy: it reminds us that there is a gadget for aspirational cooks that perhaps costs only a couple of dollars but which handles the single dedicated task of slicing the pit out of a mango.

Aspirational advertising can also apply to some services as well: high end restaurants can also use aspirational advertising to advertise their services. A restaurant which attempts to position itself as an expensive restaurant perhaps does not make much more money per seat/hour (dinner may cost more, but you spend more time eating it, taking up the seat during that time), but it’s simply a positioning strategy: fewer but higher-end customers. The profits are the same, but the message becomes aspirational rather than just utilitarian: you eat there because it’s a fine restaurant, not just because you’re hungry.

I don’t think Internet advertising captures any of this.

Personally I blame Google. I honestly do: Google made the ability to find something the thing that is “top of mind” for most advertising executives on the Internet. We don’t care what the message is that we send; we only care that we shove it in front of your eyeballs. The landing page that we construct for you is exactly the same if you’re a restaurant (who is struggling with your positioning: are you an aspirational restaurant or a quick eatery restaurant?), or a plumber or lawyer or a jewelry store.

If you’re a sophisticated advertiser you probably already have your own web site which reflects what you want to advertise — but, um, if you’re a sophisticated advertiser you probably don’t need help advertising.

But I blame Google because Google has a habit of reducing everything to statistics and numbers. Their designs are all data driven — is the coupon on the landing page sufficiently large enough to capture the eyes and is sufficiently related to the keywords to represent a sufficient “call to action”? Is the phone number easy to find, and routed through a call tracking service so we can capture the efficiency of the call combination? Do we have a properly located blurb, and is the uploaded video presentation well positioned for playback? Is it the right shade of blue? Let’s sample 8,000 shades to statistically determine the right shade of blue.

Google’s UIs are crap. Landing pages built based on a statistical model attempting to represent a singular call to action associated with the keywords that maximizes the ROI by maximizing the conversion rate tends to be ugly little critters that do no-one any service — except perhaps for someone who needs a plumber in a hurry because there is crap backflowing onto their pretty rugs, and they will overlook a bad color choice or a blink tag on a coupon presentation.

Of course to some extent Google search works for helping customers find the things they want. For needs-based services — for finding a plumber in a hurry — the current Internet model of impressions converting to clicks converting to conversions via calls to action works: if I need to unclog a toilet now and the guy is nearby, the model works very well, and who gives a damn that the shade of blue in the border was #0000CE instead of #020FE0.

And Google search, so long as it isn’t completely trashed by SEO campaigners who are looking to spam the Internet with useless “reviews” in order to backload the search results and skew the information we’re searching for, works for aspirational purchases: they help us define what it is we’re buying and narrow down our product choices by understanding the range of features provided on that next car, refrigerator, or laptop computer.

As a mechanism for aspirational advertising, though, the current Internet model sucks hard. At best it’s informational, not aspirational: where is the store located? What are their hours? No sense of “is this a place for a good lunch” or “will I be catered to and pampered as I drop $10k on jewelry” or “do they have affordable shoes.” A map, some text, a description about how they’ve been around since 1960 and a blinking coupon promising me 5% off on my next purchase if I mention some magic code does not work to define aspiration.

Google is not an aspirational company. Sure, for a software developer, developers aspire to work there — but that’s because Google, ironically enough, has done a fantastic job understanding the mind of developers and presenting themselves as the ideal place to work. But the developer-engineer model of looking at the world, while it works for developers and engineers, doesn’t work for everyone else. And Google is only in first place because we think “I’ll google this” instead of “I’ll search for this on the Internet” — and because, up until now, the Google search bar is the default search bar in the toolbar of most browsers.

I think if the Internet is going to improve it’s ROI for Internet advertisers, the model has to change.

Specifically we have to start understanding the advertiser message more, rather than focus on the computational processes surrounding matching consumers to advertisers — a process which is intrinsically flawed to begin with. (Even Amazon, who is supposed to be king of this process, screws up royally when it offers to sell me a second safe after buying a first one: how many blasted safes do I need in my house? Can’t someone at Amazon just add a single bit to their taxonomy to indicate categories of goods which have a low probability of repeat purchases?)

Ironically by focusing on the advertisers more and on the type of advertiser (volume business, aspirational business, or service provider), we could conceivably also better target the customers they’re trying to reach.

The lowly string concatenation operator.

So the other day I encountered the following code. (I’ve rewritten this to protect the innocent.)

        HashMap<String,String> map = ...;

        for (int i = 0; i < 20; ++i) {
            if (check(map.get("label" + i))) break;
            
            String thing = map.get("thing" + i);
            String other = map.get("other" + i);
            
            doOperation(thing,other);
        }

Now for most applications, this is perfectly fine. I like idioms which are clear, even if they are slightly more computationally expensive. However, for a high performance application, it’s surprising how much stuff is going on behind the rather innocuous statement map.get(“label” + i);.

According to the Java spec, string concatenation is a shortcut for using a StringBuilder class. So map.get(“label” + i) becomes:

    StringBuilder tmp = new StringBuffer();
    tmp.append("label");
    tmp.append(i);
    map.get(tmp.toString());

And the append(int i) call is translated into a call to Integer.toString():

    StringBuilder tmp = new StringBuffer();
    tmp.append("label");
    String tmp2 = Integer.toString(i);
    tmp.append(tmp2);
    map.get(tmp.toString());

But wait, it gets worse! The StringBuilder.append() routine has to (a) check to see if there is enough buffer space allocated to store the string, growing the array (and copying the contents using System.arraycopy() to copy the memory across if not), and (b) use System.arraycopy() to copy the contents at the end of the buffer.

So each tmp.append() call involves a call to System.arraycopy() and an array length compare.

Then the tmp.toString() call allocates another buffer, copying the internal StringBuilder copy into the string buffer. (The internal source for String is permitted to simply copy a reference to the internal array in StringBuilder over rather than copying the bytes, but it doesn’t appear to do this.)

And I haven’t even gotten started!

Then we pass tmp to the map.get() method, which does a lookup, calling into the string’s hashCode() and equals() call. And because we have a brand-new string, hashCode() has to iterate through the entire array of characters, doing a math operation on each character, accumulating the results into a hash code.

Every time we go through this routine.

The answer, of course, if you’re writing a high performance application, is not to repeatedly do the same thing over and over again, especially if you can store away the results in memory.

In our above case, it would be easy enough to pre-populate an array of strings. Thus:

        /* Do this initialization once */
        String[] labels = new String[20];
        String[] things = new String[20];
        String[] others = new String[20];
        for (int i = 0; i < 20; ++i) {
            labels[i] = "label" + i;
            things[i] = "label" + i;
            others[i] = "label" + i;
        }

This pre-populates an array of strings with the labels we’ll be checking against. Then:

        
        /* Then do this a lot */
        for (int i = 0; i < 20; ++i) {
            if (check(map.get(labels[i]))) break;
            
            String thing = map.get(things[i]);
            String other = map.get(others[i]);
            
            doOperation(thing,other);
        }

Now each time we pass through the loop, instead of creating a StringBuilder object, allocating two character arrays (or more, if our key string is too big to fit in the StringBuilder’s default buffer) for each call to get() above, which winds up allocating 60 StringBuilder objects and 120 arrays, along with 60 calls to hashMap() each time through, instead we move those internal allocations into an initializer.

And each time we go through our loop, we’ve replaced 60 StringBuilder allocations and 120 array allocations with 60 array lookups–which is a hell of a lot faster.

Simple things: volatile

I’ve been watching some posts go by discussing the volatile keyword.

Two observations.

(1) In C and Java, the volatile keyword means “make sure changes to this variable are read and written out from the actual variable.”

I’ve seen people suggest what this means is that if you don’t mark a variable volatile, then its value is only accessible to the thread writing that variable, or some such nonsense.

Not quote.

Volatile is essentially a hint to the optimizer, indicating that once the code point hits a statement to either read or write to the specified variable, the memory holding that variable should be accessed rather than optimizing out the read or write access.

For example, suppose I have the following bit of code:

public class A
{
    int x;
    
    public void test()
    {
        for (x = 0; x < 10; ++x) {
            System.out.println("Item " + x);
        }
    }
}

(Yes, this is a dumb, contrived example.)

A reasonable optimizer could write out the following (equivalent) instructions:

public class A
{
    int x;
    
    public void test()
    {
        for (int _tmp = 0; _tmp < 10; ++_tmp) {
            System.out.println("Item " + _tmp);
        }
        x = 10;
    }
}

In other words, rather than go through the hassle of generating a global access every time we look into ‘x’ (which is a relatively expensive operation), we could simply use a local stack variable (whose access is significantly faster), iterate through the loop, then slam the global variable x to 10 at the end of the routine.

What volatile says, however, is “don’t skip read/write access for this variable; it could change independently of the current instructions being executed in this thread.” In our example above, if we were to declare ‘x’ volatile:

public class A
{
    volatile int x;
    
    public void test()
    {
        for (int x = 0; x < 10; ++x) {
            System.out.println("Item " + x);
        }
    }
}

Then we’re telling the compiler on every access of the variable: when we set it to 0 at the start of the loop, when we increment it, and when we test to see if it is less then 10, and when we print it out–each time we should always go directly to the global variable. No fair using a local variable to speed things up. The optimization above, in other words, is illegal when x is marked volatile.

Of course this is a completely contrived example; in the real world you wouldn’t use a field for a for loop. But you may want to access a class variable and use it in a rather complex way while guaranteeing that within your method access to that variable isn’t optimized out for whatever reason–and volatile guarantees that for you.

(2) Java 5 and greater also adds an additional semantic to volatile: reads and writes to the variable are guaranteed to be atomic. What this means is simple: suppose you’re writing a long integer:

	long i = 5;

The underlying processor may be a 32-bit processor, which means that the underlying CPU must actually do something like:

	int i_0 = 0;		// the first 4 bytes
	int i_1 = 5;		// the last 4 bytes

In other words, the assignment ‘i = 5’ actually requires two processor memory write operations.

Now suppose we have a task swap take place between the first write and the second. Then what happens is that only half of our long integer has been updated, and the other half may contain garbage. So in the following contrived example:

	long i = -1;
	// some time later...
	i = 0;

A read from the variable i could, in theory, return more than just -1 and 0: it may also return 0xFFFFFFFF00000000 or it could return 0x00000000FFFFFFFF, depending on the order the 32-bit words are written.

If i is only allowed to be -1 or 0, well, you can see how you could have a problem.

By guaranteeing that the reads and writes are atomic, however, Java guarantees that both words are written before we attempt to read either. In other words, by declaring i volatile we do the equivalent of:

    synchronized(_semaphore) {
        int i_0 = high_word;
        int i_1 = low_word;
    }

(Though the semaphore Java uses is significantly faster.)

This means we’ll never see 0xFFFFFFFF00000000 or 0x00000000FFFFFFFF in our contrived example, if we only declare i as volatile, with Java 5 or later. (Java 1.4 or earlier, however, does not guarantee atomic read/write semantics, which means you must wrap the variable in a semaphore.)

It’s important to be aware of these issues and carefully craft your code with a full understanding of the ramifications of your code. Otherwise you may wind up with a multi-tasking application which, on a very rare (and damned hard to find occasion) just randomly fail for no good reason.

I think part of the problem with CS educations today is the overuse of design patterns.

Okay, I know that probably irked a few people. But hear me out.

A “design pattern” really is really just a common solution to a problem, right? I mean, if you have a problem like “how should I handle percolating events up a hierarchy of potential listeners”, then Chain of responsibility is not a bad way to go.

And I think it’s reasonable to study different design patterns as solutions to different commonly encountered problems.

But when people start seeking a design pattern without understanding what the problem is, it’s putting the cart before the horse. It leads to what I’ve been calling “voodoo programming”, where you shake a stick hoping that the magic stick will magically resolve the problem. That sort of magic thinking inevitably leads to the lavaflow anti-pattern, where layers of misunderstood code is piled on top of older, misunderstood code–and ultimately leads to a bloated, slow system which is hard to maintain.

Couple with the other things that programmers do which are counterproductive, and the real question is not “why is it only 32% of projects complete on time and in budget, while 24% of all IT projects are canceled,” but “how the hell is that 32% number so high?”

Makes me wonder if, at the end of the day, a number of projects in the “completed on-time and in budget” bucket factored in the additional costs of “voodoo programming”, and the actual failure rate (that is, where the time to deliver is longer than optimal) is closer to 90%.

Things I think about when starting a new project that, surprisingly, many people appear not to.

I switched projects at work and now I’m going through the struggle of trying to figure out how to build other people’s projects. It’s always a struggle, of course: a lack of familiarity always makes things harder than they should.

But there are some common things that I realized that don’t seem to be as universal as they should be.

So here are some things I think about when I start work on a brand new project, that I wish other people would also prioritize.

How will you debug the project?

Seems weird to put this at the top of the list. But there are quite a few web applications being built where, in the list of things people worry about, “debugability” isn’t even in the top 5. Oh, sure; they think about configurability (how will I configure the tool dynamically?), and logging (how will I get information about problems off a server that is locked down from me?), and management (how will I remotely manage something that has elements of it locked down from me?). But for whatever reason, the simple ability to reach up in the toolbar, and press the ‘debug’ button and have their product (in one automated process) build, locally deploy, launch, and stop on a locally set breakpoint doesn’t even appear in the top 10 of things people seem to worry about.

All too often debugging a web application seems to be “oh, sure; just kick off Maven with some magic combination of things, then copy this file there, and run that script–oh, and connect your debugger to the running process.” Some of those steps, of course, are more lore than they are documented processes. And it’s a terrible substitute for just checking out the project, and hitting the “debug” button.

I’m a huge fan of spending a few days and figuring out which integrated tools you need to allow for one-button debugging within Eclipse, my personal favorite IDE. Remote debugging should only be used as a last resort, in order to attach to a running remote process, in order to diagnose a problem with a deployed application. But ideally all debugging should be done by just hitting the little bug icon.

In fact, I’d suggest this is the first thing that should be done when setting up a project, before figuring out how you’re going to deploy the project, before figuring out how you’re going to package the project, or before you figure out which libraries you intend to use. And this should be the first thing on the top of your mind as you incorporate new technologies.

Because, in my opinion, if you check out a project onto a brand new computer, and it doesn’t just get sucked into the IDE, ready to be debugged in one step by pressing the debug button, your build is broken.

How will you bring new team members up to speed or replace them?

In part this is a technical question, and it has to do with documenting your processes. How does a new team member check out the sources from the source repository? Which tools does he need to install in his IDE in order to run your project? Where can he get the latest documentation?

If you’ve made sure that, once the IDE is installed, checking out the source from the source repository simply “works” (see the step above), then you’ve saved yourself a lot of documentation time.

But any document is also a product that must be debugged and maintained. So who will maintain that document? Who will debug the document (run through the steps to make sure they’re clear and correct)?

And if you’re in a shop which supports multiple IDEs, then you have an extra step you must perform: first, figure out how you will allow multiple IDEs to co-exist and operate on the same source base. And second, maintain the projects across different IDEs. Now that could be as simple as having a culture of constant communications when new files are incorporated into a project. But it does mean the project files will need to be maintained as well as the sources–and it does mean the documentation will also need to be maintained as the project evolves.

How will you distribute the resulting product?

For whatever reason, in the three web shops I’ve worked for, web distribution was always treated a bit cavalierly: since we maintain the severs, naturally we don’t need to give as much thought towards distributing the resulting product as we do if we’re distributing a CD-based product or an App Store distributed product.

And while this is true on the surface, every web shop I worked for also has an operations team and a support team who are expecting a “run book” or other documentation on how to install the product and how to maintain the product.

In other words, they’re asking for a software user’s manual.

Just like the ones we used to print for a CD distributed product.

So you can’t escape the following questions, even if you work for a web shop.

How will you distribute your product? What installer will you use to install the product? What are the distribution products, and who will maintain those distribution products? What about the documentation; who will maintain it? Who will test the installation process? Who will make sure that on first boot it’s obvious what to do?

And how will you alert the user when things go wrong, and how will you tell the user what to do when things go wrong–and when to call you for support, and when to handle things themselves?

How will you get diagnostic information back when things go wrong? And what form will that diagnostic information take? Is it sufficient to help you pinpoint the failure?

It’s surprising to me how little thought seems to be given to these basic questions. What’s even more interesting to me are the number of developers who treat these questions with disdain: I know a few who are proud of the fact that their “IDE” is vi and their debug process is printf(). Okay, if that is what chimes your bells–but most of us are more interested in tightening the edit/compile/debug cycle and in making the project more manageable for real human beings.

Nondeterministic Maven

Understanding Maven Dependency Mediation (Part 1)

The important thing is the version number. It is stated “as is” without any extra additions (I’ll come back to this in a follow-up post). If you define version numbers in this syntax, Maven treats it as a recommended version. So what you’re actually doing is to tell Maven “I would prefer V1.2.11 of Log4J, but hey, I can live with any other version, too”.

This represents the biggest problem I have with Maven. It just feels non-deterministic to me. In solving one problem (“how can we integrate against a large number of jar files from a centralized location and administrate that repository”), we’ve introduced fragility in the resulting build product–we’re not entirely sure what jar files may be loaded and used to build our product.

Now of course this wouldn’t matter if jar files rigorously adhered to a proper API design methodology: proper versioning announcements (like the old Macintosh “Gestalt” manager) or guaranteed a proper and steady evolution of the API calls (similar to what Microsoft does with it’s COM interfaces does with things like IClassFactory and IClassFactory2), along with proper abstraction of the interfaces into higher level operations. Then it wouldn’t matter if you used version 1.0, 1.1 or 8.5 of a particular jar file. And if the API is designed with the principle of Graceful Degradation in mind, it wouldn’t even really matter if you found yourself using version 0.9.

But all this depends on proper documentation, proper design, and knowing the design patterns used by API developers to guarantee that your code will work regardless of what version of the API you’re calling–and when there is an API break, that break is properly announced in a major revision change and how the break will affect you in their documentation set.

But many jar file developers working on smaller projects (especially internal corporate projects) don’t do this–which is why sometimes you can find your code failing as you switch from version 1.1.4 (build 16) and version 1.1.4 (build 18).

Worse, this problem is compounded by the literally dozens of jar files that seem to be sucked in by things like Apache Commons and the Spring framework. If all the moving parts were designed correctly, again this wouldn’t be a problem. But how many people building APIs for common jar files even have any experience designing properly working, properly tested and properly supported APIs? And how many of the potentially thousands of possible combinations are even tested?

It just feels fragile to me.

And when you’re talking about the final build product of your team, after countless months of work trying to get your product solid and stable, fragile is bad.

Answering the question “what environment variables are available on the iPhone”

Just wrote a simple program to use NSProcessInfo to dump the environment variables on my iPhone. And I found the iPhone running my app standalone predefines the following environment variables:

SHELL = /bin/sh
CFFIXED_USER_HOME = /private/var/mobile/Applications/[UUID]
PATH = /usr/bin:/bin:/user/sbin:/sbin
TMPDIR = /private/var/mobile/Applications/[UUID]/tmp
__CF_USER_TEXT_ENCODING = 0x1F5:0:0
USER = mobile
LOGNAME = mobile
HOME = /private/var/mobile/Applications/[UUID]

The [UUID] is the UUID for your application, to differentiate the directory for your application from the directory used by other applications.


I find it interesting because it means that if you have some Unix C code that attempts (for example) to find the location of a file without using the various search methods available in iOS Cocoa, you can do it. For example, you can change the working directory to the documents folder by writing:

chdir(getenv("HOME"));
chdir("Documents");

(The standard iPhone directories are documented here: The Application Runtime Environment, under “The File System”.)

That can be quite useful…

Just look at the hardware specs.

Gizmodo is running a piece: Why Nobody Can Match the iPad’s Price

They have several theories. First, they theorize that because Apple sells most of their units through their own retail outlets, Apple can sell for a lower margin. But then, those retail outlets are not cheap. Then they theorize that Apple controls the hardware and the software–but then chalk it to Apple being willing to take lower profit margins on the pieces of the components.

But no-one looks at the design of the iOS operating system.

Apple created an operating system that is quite usable without multitasking, with an API which encourages fast switching applications in and out of memory. Because they don’t encourage the use of interpreted languages, and because they make heavy integrated use of the on-board GPU, they don’t need as much computing power to run most typical applications. The API also encourages the use of callbacks in a single-threaded event loop, which allows quickly idling the CPU when needed. And the OS runs in a very small memory footprint.

What this means is that the Apple iPad can run very well with very few resources: the Apple iPad uses only 256mb of RAM (as opposed to the Motorola Xoom’s 1gb of RAM–and God help you if you try to run Windows in that memory footprint), and the base model ships with only 16gb of flash memory: the same amount of flash in a cheap keyring flash drive.

Because Apple controls the software and because they control the hardware, they can also use a more integrated approach to reducing the part count in their iPads: my guess is that they are perhaps even looking at putting the RAM into the same wafer as the Apple A4 CPU. Never underestimate the cost savings of reducing chip count, as Steve Wozniak knew. Each chip that has to be mounted is an additional cost during design and manufacturing, and an additional chip that consumes energy and releases heat.

Apple’s iPad hardware is perfect for Apple’s iOS operating system and development environment. But if you were to try to run Android or Windows on a similar memory footprint, you’d have something that is sluggish and slow–Windows wants to run multiple processes and Android wants to kick off threads like crazy, which explains the hiccups you see when you try to run either on a Netbook computer.

For someone to compete with Apple, they would need to design an operating system which makes the compromises necessary to run on an inexpensive operating system–including enforcing development policies (such as no multi-process multi-tasking) that allow those compromises. That would allow them to reduce the chip count, memory requirements and CPU requirements that would allow them to create a much more inexpensive motherboard and reduce the battery size while maintaining battery longevity.

And unfortunately there is no-one currently out there who even sees the problem, much less is striving to find the solution to these problems.

If I were Google, I’d hire some CPU people and some CPU fabrication time, and figure out how to put the Davlik instruction set on a chip. Then I’d license the CPU design to anyone who wants to build a low power, but fast, Android phone.

*sigh*

How long before Facebook is back? I use Facebook for more personal posts and politically oriented stuff, and I use this blog for more technical-oriented topics. So clearly, Facebook is now down for my account, especially when I have a long winded politically oriented post I want to write. (*sigh*)

C++ Things To Remember

Sometimes I have to remind myself of things I used to know but forgot over the intervening years.

With C++ it’s two things.

First, when playing with a complex algorithm (such as the polygon manipulation algorithms I’ve been playing with, or with earlier algorithms on computational algebra), it’s important to understand the algorithm enough to properly design the data structures.

In a language such as Lisp or Java (both which have properly functioning garbage collectors), you can concentrate on the algorithm design and not worry too much about the data structure design: after all, if things just get ‘dropped’ or not handled correctly, the garbage collector will clean up after you. You can focus, in other words, on tinkering with the algorithm without worrying too much about the data structures–and adjust the data structures as you go along to match.

In a language such as C++, however, you have to worry about memory allocation. So it’s important to get the data structures right. And what that means is:

Who owns the data?

For a polygon mesh merge algorithm, the instinct is just to toss all the rings representing the mesh into an ArrayList, and call it a day. But then, ownership of the records (the edges, the half-edges, the inner rings, the points) is implicit in the references off the rings in the list.

But in C++, all of the records associated with the mesh need a single owner. (Or you could build a reference counting scheme, but that gets pretty messy pretty quick, even if you use Templates and create a smart pointer object.) So ideally your merge algorithm is passed a single unitary Object which owns all of the components (points, rings, edges, etc) in the polygon mesh, and has responsibility for managing ownership. Of course that object also manages the relationships between the different records.

The same can be said about a computational algebra system: who owns the representation of the formula being processed? Ideally there is a single object which owns everything, that you can use to track the records associated with that object.

Second, don’t be seduced by templates. After using Java for a while my poor brain thinks of templates as essentially an inline way of writing Java-like code in C++. But the C++ template system is essentially a very powerful preprocessor that rewrites C++ code so that template parameters (and parameter values) can be used to drive how the underlying C++ code is generated.

Instead, write the underlying code first, then go to templates if needed to simplify understanding of the code. And in some tricky situations (such as how one would pass a template compare operator to a class that uses a compare mechanism, guaranteeing the class type the template operates on is the class type passed to the compare mechanism), feel free to refer to the STL library for examples on how to solve those problems, rather than bang about trying to figure it out on my own. (Yes, I know; there are people at this point who will advocate learning templates right–but for me, the goal is to have functioning code, not to learn the subtleties of obscure magical invocations. And for templates I’ve found no “hook”, no conceptual model (aside from a complex rewrite language imposed on top of C++) to explain templates concisely.)

I want to use templates as a way to achieve generics declarations, but templates don’t quite work like Java generics. And I keep forgetting that, and I keep slamming up against the differences.