Nov
19

Book Release: Learning Processing

Learning Processing

I’m pleased to announce that my new programming with Processing book will be released this August (by the end of the month). You can pre-order the book from Amazon, download a sample chapter from the web site, and, yes, even become a fan of the book on facebook (since that’s what all the 35 year olds are doing these days.)

A few things I’d like to say about the book:

My goal for “Learning Processing” was to write something for the complete and total programming beginner. If you’ve never written a line of code before in your life, but want to get started creating your own digital media tools then I wrote this book for you. There are several other wonderful Processing books out there and I hope mine will complement them nicely. A special thanks to Casey, Ben, and Ira who kept encouraging and inspiring me as their books were being published.

The book is also geared towards the teacher. It’s not my belief that such a person will necessarily learn any new skills from the book (assuming they have a programming background), however, my hope is that the book will encourage and help facilitate the teaching of programming. It is structured with 10 lessons (complete with examples and exercises) and can act as a ready-made syllabus for a beginner interactive media / programming class. In fact, the book is modeled exactly on ITP’s Introduction to Computational Media course.

The first half of the book is all fundamentals: pixels, variables, conditionals, loops, functions, objects, arrays. The second half is an introduction to select advanced topics: 3D, images, video, data, sound, etc. (download full table of contents). And although the web site is currently just a splash page, it’s my intention to make available all the examples (and exercise answers) at the site. The full site should launch in the next few weeks (a big thanks to Rich Hauck who is helping to build the site.)

If anyone is interested in teaching with the book come this fall, please feel free to drop me a line and I’d be happy to answer any questions. It’s also my hope that this book can teach programming to high school students, however, I don’t have as much experience in this area. . . but if anyone is looking to try it out with younger students, please let me know and I would love to help.

Nov
18

Analog clock service for web apps

I’m nowadays working in an international company which has offices in multiple countries. I was looking for a way to get our Confluence, Enterprise Wiki, to display current time in all of our offices in one page. I didn’t find any simple solutions as lots of services just provided me a chunk of HTML that I could add to my page to create a dynamic clock but wiki syntax doesn’t really let me do that.

I’m a great fan of Google Charts API. Developers at Google have developed a really nice URL based API for the charting purposes. This was inspiration for me when I created Clock Service API for my own needs.

Clock Service is a simple servlet implementation that generates an image with the specified parameters. API can be used to define image size (s=100), timezone (tz=zone), title (t=Helsinki) and 12h/24h format (f=24). With this I can use the following URLs to produce three different clock images for three different timezones.

/clockservice/clock?tz=America/New_York&s=150&t=Atlanta&f=12
/clockservice/clock?tz=Europe/Helsinki&s=150&t=Helsinki&f=12
/clockservice/clock?tz=Australia/Sydney&s=150&t=Sydney&f=12

If you use those URLs in IMG tags then the result would look like this:

Clock (Atlanta)Clock (Helsinki)Clock (Sydney)

The images above aren’t created dynamically as I don’t have any public servlet container available.

The code behind the service is really quite simple. There are only two classes ClockServlet and Clock. Servlet implementation is only used for parsing the parameters from the request and writing the bytes from Clock.getImageData(..) to the web response.

Timezones are handled using the Java’s Calendar and TimeZone classes like this:

  1. TimeZone tz = TimeZone.getTimeZone(“Europe/Helsinki”);
  2. Calendar cal = Calendar.getInstance(tz);
  3. int hour = cal.get(Calendar.HOUR);
  4. int minute = cal.get(Calendar.MINUTE);

You can find the source code and compiled WAR package from the application page, here. Application is distributed under the Apache License v2.0.

Nov
14

Dependency Injection is not only about compile time dependencies

Tinou complains that dependency Injection was broken. I want to add some points to his / hers statements:

The problem I’ve always had with DI frameworks, be it Spring or Guice, is they create this nasty dependency tree. If you don’t want to use GlobalApplicationContext.getBean() or Injector.getInstance() then you’ll need to inject all your dependencies at the root. It annoys the crap out of me, but I suppose there’s just no way around it…
Except if the language had a mechanism to realize interfaces and abstract classes at runtime, either built-in or through some extension.
[…]The fundamental problem with all dependency injection tools is they are trying to do what language should be doing (instantiating objects that implement some interface[!]).

These toughts might be correct if you reduce dependency injection to “instanciate a class that implement this or that inferface”. But I understand dependency injection as a tool for inversion of control and decoupling of implementations. Dependency injection shall enable the developer to reconfigure the application without compilation of the compontents that depend on eachother.

Yes, at some point you will have to decide which implementation of a certain interface shall be used, and one can argue where this “wiring information” should be placed: Spring uses an XML file, PicoContainers can be composed hierachically, guice can use annotations. But if you have only one implementation of the interface you can do without a dependency injection framework at all.

Updates

  • Fixed typos
  • As pointed out by Paul Hammant PicoContainer of course can be configured with XML as well as with Groovy, Python, Beanshell and Ruby. I’m sure one can add Yaml and Json easily as well. Furthermore I think this is possible to some extend for Spring and Guice as well and the Qi4J developers would be able to add something to this, too. What I wanted to make clear is that one can argue about when, where and how to wire the components; the different ways the mentioned frameworks offer emphasize this.

If found this content useful consider “buying me a beer” with PayPal (Suggested 2,50 € for a Beer).

Nov
11

Java How to Program 7th Edition

Java How to Program 7th Edition

The Deitels’ groundbreaking How to Program series offers unparalleled breadth and depth of object-oriented programming concepts and intermediate-level topics for further study. The Seventh Edition has been extensively fine-tuned and is completely up-to-date with Sun Microsystems, Inc.’s latest Java release - Java Standard Edition 6 (”Mustang”) and several Java Enterprise Edition 5 topics. Contains an extensive OOD/UML 2 case study on developing an automated teller machine. Takes a new tools-based approach to Web application development that uses Netbeans 5.5 and Java Studio Creator 2 to create and consume Web Services. Features new AJAX-enabled, Web applications built with JavaServer Faces (JSF), Java Studio Creator 2 and the Java Blueprints AJAX Components. Includes new topics throughout, such as JDBC 4, SwingWorker for multithreaded GUIs, GroupLayout, Java Desktop Integration Components (JDIC), and much more. A valuable reference for programmers and anyone interested in learning the Java programming language.

* MySQL(R) 5.0 Community Server / v5.0.27
* MySQL(R) Connector/J Version 5.0.4
* Sun(R) Java(TM) Studio Creator 2 Update 1
* NetBeans(TM) IDE Version 5.5 with Java EE Application Server 9.0 U1 Bundle

User Ratings and Reviews

5 Stars Excellent text to learn the challenging concepts of Java!
I purchased this text for my class on Java Programming. I never had experience with any Object Oriented Programming (OOP) languages such as C++, C# and Java before. I love the way that this text introduces the concepts “Object” and “UML” and tries to familiarize you with complex terminology and structure of Java. Sometimes you feel confused with terms such as method, class, argument, identifier adn etc., but the way that this text presents and gives the examples for each of them is excellent. Case Study examples are complete with thorough explanations and are “oriented to objects”.

No doubt that I am confident in giving 5 stars to this text. However, I must mention couple cons I encountered in the text and I hope Authors will take’m into consideration in future editions:

1) “Error Prevention”, “Good Programming Practice” and other tips occur in the middle of the text quite frequently and therefore are sometimes a bit distracting when you read the text. However, sometimes they do contain very important concepts and definitions for terminologies which are very pricy to ignore or skip (sometimes I did so in order to focus on the main text:-( ). Therefore I would urge the authors to incorporate those tips into the text so that readers would neither skip those concepts nor be distracted by frequent occurance of the tips.

2) I personally had difficulty in installing the JDK and JRE’s latest versions and the directions in the text are not user friendly.

3) The “Examples” folder in CD does not have Appendix M.

Nonehteless, these cons do not affect the overall quality of the text, and again, it is highly recommended to own one!

2 Stars Boring and trite
I bought this book for a sophomore computer science class on OO and web-design. This was one of the worst textbooks I’ve come across. The examples are old. (Who really wants another Employee class example?). The text is full of ‘helpful’ facts that are often obscure and distracting. This book never really explained the most important topics of OO (such as polymorphism) in a way that I understood.

Computer Science textbooks should not be sold based on weight but on content. Do yourself a favor and purchase Head First Java.

5 Stars Great Introductory Book
Used this book for a hybrid Introduction to Java Program Course. Didn’t need to e-mail the professor at all for help on assignments or online tests. I recommend either jGrasp or Netbeans for your compiler. Used both and they were both extremely helpful.

5 Stars The best book to start programming with Java
There is no other book which is so complete and student oriented like this. It is worth any penny of its price. It covers programming from the basics and it takes you to an intermediate level of knowledge. The presentation of the ULM stuff in combination with OOD/OOP is super.

If you want to learn Java from scratch this is the book!

5 Stars Great Java book
I purchased this book after I had taken a Java class that used the Head First Java book as a textbook. I could not stand trying to use that book, so I purchased the Deitel book. It is a great book to learn java and to use as a reference. I have continued to use this book in every java class I have had and even purchased another Deitel book (C#) because they are so informative and easy to use.

Buy/More Info

Nov
10

Introducing Java2Script’s Simple Pipe

Communications between server and browser are essential things in AJAX world.

Basic Knowledge

Each HTTP connection is forked by browser. And one HTTP connection may serve multiple sessions in HTTP 1.1 but server only one session in HTTP 1.0. There is no time limit or data transfer limit on each HTTP connection. This is basic knowledge of HTTP connections.

An HTML web page, may contains lots of resources, images, style sheets or JavaScript files, and each resources requires an HTTP session. And according technologies called AJAX, browser can load resources at any specific time.

What is Simple Pipe?

Simple Pipe is a kind of data transformation from server to browser. Once browser open up an HTTP connection to the server, the server keep the connection open. And whenever the server get data, it will flush data through the HTTP connection to browser. The data transfered through the connection is serialized and deserialized in SimpleSerializable format.

How to Setup a Simple Pipe?

Simple Pipe is currently designed for Java language. There is a class named “com.java2script.ajax.pipe.SimplePipeRequest” with a static method named “pipeRequest” which accept a parameter in type of “com.java2script.ajax.pipe.SimplePipeRunnable”. The SimplePipeRunnable is will accept parameters from browser side, and then be passed to server side (Tomcat or other Servlet containers), and its action will be executed. In most cases, an other-type connection is created, and listeners are added to the connections for up-coming events. And the connection will be registered with a generated pipe key. And the pipe key will be sent back to browser side. Browser side will create another connection to the server with the given pipe key. Server will check the pipe key, and hold the HTTP connection, and flush any data from previous registered connection to browser side in format of SimpleSerializable. Browser will use IFRAME to accept the data, and return back to object instances. In keeping the HTTP connection, browser will send a notifying signal (HTTP connection) to server to make sure that browser is keeping the connection live. If browser likes to close the pipe, it will send another Simple RPC call the server to notify server that pipe should be closed. If it happens that browser exit without notifying closing pipe, server will close the pipe in a minute or so, as there is no such signals for the pipe to be kept alive.

As Simple Pipe is a subset of Java2Script library API, Simple Pipe may only be used in Java language. But after being converted to JavaScript by Java2Script compiler, Simple Pipe technology can be used in JavaScript language. And JavaScript demo of Google Talk is an example of Simple Pipe.

Code Snippets

SimplePipeSWTRequest#swtPipe usage:

SimplePipeSWTRequest.swtPipe(new LoginRunnable() {

@Override
public void ajaxIn() {
username = userNameText.getText().trim();
password = passwordText.getText();
}

@Override
public void ajaxOut() {
if (failed) {
MessageBox messageBox = new MessageBox(MainWindow.this, SWT.ICON_ERROR);
// notify error
return;
}
setData(“ConnectionKey”, key);
setData(“PipeKey”, pipeKey);
// continue to login
}

@Override
public void ajaxFail() {
MessageBox messageBox = new MessageBox(MainWindow.this, SWT.ICON_ERROR);
// .. notify errors
}

public void deal(PresenceSerializable ps) {
// Data received from pipe! To update presence status
}

@Override
public void deal(final MessageSerializable ms) {
// Data received from pipe! To popup chatting dialog…
}

@Override
public void deal(RosterSerializable rs) {
// Data received from pipe! To update roster entries…
}

});

LoginRunnable

public class LoginRunnable extends SimplePipeRunnable {

public static class PresenceSerializable extends SimpleSerializable {
public String name;
public String email;
public String status;
public String type;
public String mode;
}

public static class MessageSerializable extends SimpleSerializable {
public String from;
public String body;
public String to;
}

public static class RosterSerializable extends SimpleSerializable {
public String from;
}

public String username;

public String password;

public String host;

public int port;

public String service;

public String key;

public boolean failed;

@Override
public String getHttpURL() {
return TalkRunnble.TALK_URL_BASE + “simplerpc”;
}

@Override
public String getPipeURL() {
return TalkRunnble.TALK_URL_BASE + “simplepipe”;
}

/**
* TODO: {@link #pipeSetup()} should be ignored by Java2Script compiler
* by default.
* @j2sIgnore
*/

@Override
public void pipeSetup() {
failed = false;
JabberHelper instance = JabberHelper.getInstance();
key = instance.login(username, password, host, port, service);
if (key == null) {
failed = true;
return;
}
new Thread(new Runnable() {

public void run() {
while (true) {
try {
Thread.sleep(30000);
} catch (InterruptedException e) {
//e.printStackTrace();
}
if (!isPipeLive()) {
pipeDestroy();
break;
}
}
}

}, “Jabber Connection Monitor”).start();

XMPPConnection conn = instance.getConnectionByKey(key);

Presence presence = new Presence(Presence.Type.available);
conn.sendPacket(presence);

//XMPPConnection conn = JabberHelper.getInstance().getConnectionByKey(key);
conn.addPacketListener(new PacketListener() {

public void processPacket(Packet packet) {
pipeThrough(packet);
}

}, null);
}

/**
* @j2sIgnore
*/

@Override
public boolean isPipeLive() {
JabberHelper instance = JabberHelper.getInstance();
XMPPConnection conn = instance.getConnectionByKey(key);
return super.isPipeLive() && conn != null && conn.isConnected()
&& !instance.isConnectionLost(key);
}

/**
* @j2sIgnore
*/

@Override
public void pipeDestroy() {
JabberHelper instance = JabberHelper.getInstance();
instance.logout(key); // try to logout
}

/**
* @j2sIgnore
*/

@Override
public void keepPipeLive() {
JabberHelper instance = JabberHelper.getInstance();
instance.update(key);
}

/**
* TODO: {@link #through(Object…)} should be ignored by Java2Script
* compiler by default.
* @j2sIgnore
*/

public SimpleSerializable[] through(Object… args) {
if (args != null && args.length > 0) {
Packet packet = (Packet) args[0];
SimpleSerializable[] ss = new SimpleSerializable[1];
if (packet instanceof Presence) {
Presence presence = (Presence) packet;
PresenceSerializable ps = new PresenceSerializable();
ps.email = presence.getFrom();
Mode mode = presence.getMode();
ps.mode = mode == null ? null : mode.name();
Type type = presence.getType();
ps.type = type == null ? null : type.name();
ps.status = presence.getStatus();
ss[0] = ps;
return ss;
} else if (packet instanceof Message) {
Message message = (Message) packet;
MessageSerializable ms = new MessageSerializable();
ms.from = message.getFrom();
ms.body = message.getBody();
ms.to = message.getTo();
ss[0] = ms;
return ss;
} else if (packet instanceof RosterPacket) {
RosterPacket roster = (RosterPacket) packet;
RosterSerializable rs = new RosterSerializable();
rs.from = roster.getFrom();
roster.getType();
ss[0] = rs;
return ss;
}
}
return null;
}

public void deal(PresenceSerializable ps) {
// To be override
}

public void deal(MessageSerializable ms) {
// To be override
}

public void deal(RosterSerializable rs) {
// To be override
}

}

SimplePipeRunnable

public abstract class SimplePipeRunnable extends SimpleRPCRunnable {

/**
* Pipe’s id
*/

public String pipeKey;

private boolean pipeAlive;

private SimplePipeHelper.IPipeThrough helper;

/**
*
* @param helper
* @j2sIgnore
*/

void setPipeHelper(SimplePipeHelper.IPipeThrough helper) {
this.helper = helper;
}

public String getPipeURL() {
return “simplepipe”; // url is relative to the servlet!
}

public String getPipeMethod() {
return “GET”;
}

@Override
public void ajaxRun() {
pipeKey = SimplePipeHelper.registerPipe(this);
if (pipeKey != null) {
pipeSetup();
pipeAlive = true;
} else { // failed!
pipeAlive = false;
}
}

/**
* Listening on given events and pipe events from Simple RPC to client.
*/

public abstract void pipeSetup();

/**
* Destroy the pipe and remove listeners.
* After pipe is destroyed, {@link #isPipeLive()} must be false
*/

public abstract void pipeDestroy();

/**
* Return whether the pipe is still live or not.
* @return pipe is live or not.
*/

public boolean isPipeLive() {
return pipeAlive;
}

/**
* Notify that the pipe is still alive.
*/

public void keepPipeLive() {
// to be override
}

/**
* Update pipe’s live status.
*
* @param live if live is true, just notify the pipe is still alive. if live is false
* and {@link #isPipeLive()} is true, {@link #pipeDestroy()} will be called.
*/

protected void updateStatus(boolean live) {
if (live) {
keepPipeLive();
pipeAlive = true;
} else if (isPipeLive()) {
pipeDestroy();
pipeAlive = false;
}
}

/**
* Convert input objects into SimpleSerializable objects.
*
* @param args
* @return SimpleSerializable objects to be sent through the pipe.
*/

public abstract SimpleSerializable[] through(Object … args);

public void deal(SimpleSerializable ss) {
try {
Class clazz = ss.getClass();
if (“net.sf.j2s.ajax.SimpleSerializable”.equals(clazz.getName())) {
System.out.println(“Default!”);
}
Method method = null;

Class clzz = getClass();
String clazzName = clzz.getName();
int idx = -1;
while ((idx = clazzName.lastIndexOf(‘$’)) != -1) {
if (clazzName.length() > idx + 1) {
char ch = clazzName.charAt(idx + 1);
if (ch span class=”string”‘0′/span && ch span class=”tag”> ‘9′) { // not a number
break; // inner class
}
}
clzz = clzz.getSuperclass();
if (clzz == null) {
break; // should never happen!
}
clazzName = clzz.getName();
}
if (clzz != null) {
method = clzz.getMethod(“deal”, clazz);
if (method != null) {
method.invoke(this, ss);
return;
}
}
} catch (Exception e) {
e.printStackTrace();
}
// default
System.out.println(“Default!”);
}

/**
* A method used to pipe a bundle of instances through.
*
* Attention: Only visible inside {@link #pipeSetup()}.
* @param args
* @j2sIgnore
*/

protected void pipeThrough(Object … args) {
SimplePipeRunnable pipe = SimplePipeHelper.getPipe(pipeKey);
if (pipe == null) return;
SimpleSerializable[] objs = pipe.through(args);

if (objs == null || objs.length == 0) return;

if (pipe instanceof SimplePipeRunnable) {
SimplePipeRunnable pipeRunnable = (SimplePipeRunnable) pipe;
if (pipeRunnable.helper != null) {
pipeRunnable.helper.helpThrough(pipe, objs);
return;
}
}
for (int i = 0; i

Nov
09

JavaScript Style Guide Conformance

We are updating our JavaScript courseware and our JavaScript tutorial and Ajax tutorial to mostly conform with the conventions recommended by Douglas Crockford at http://javascript.crockford.com/code.html and http://javascript.crockford.com/style1.html. First of all, here’s what we decided to do. Some of these had already been implemented in our courseware, but we hadn’t formalized those decisions.

  1. Remove the language attribute from the tag. There is no need for it and it has been deprecated.
  2. No using to wrap scripts as they are no longer necessary for modern browsers.
  3. Always use var to declare variables to avoid accidental globals.
  4. Avoid global variables as much as possible. We will still sometimes use global variables when it makes it easier to illustrate a simple concept.
  5. Never use assignment as expressions. For example, avoid the following: if( flag = (a && b) ){ ... }
  6. Always use brace-delimited blocks in control structures, even simple ones.
    1. Indent the statements inside the braces.
    2. Place the opening brace on the same line as the control structure start.
    3. Place the closing brace on a line by itself and indent it so that it falls directly below the first character of the control structure. For example:
      while (some condition) {
          //do some interesting stuff
      }
  7. End function assignments with a semi-colon. That is to say, when assigning a function to a variable, the statement should end in a semi-colon.
    var myFunc = function (arg) { .... };
  8. Use object augmentation wisely. See the section on Object Augmentation at http://www.crockford.com/javascript/inheritance.html.
  9. Use === and !== instead of == and != to prevent unintended type coercion.
  10. Only use the ternary operator for value selection. Use this:
    var a = (x===y) ? 0 : 1;

    …instead of this…

    var a;
    if (x===y) {
        a = 0;
    } else {
        a = 1;
    }
  11. Use the default operator: ||. Use this:
    var a = getValue() || 1;

    …instead of this…

    var a = getValue();
    if (typeof a == "undefined") {...
        a = 1;
    }
  12. Use inner functions to avoid globals and excessive parameters. We plan to do this in our advanced JavaScript course and our Ajax courses, but not too early as inner functions are difficult to understand for JavaScript newbies.
  13. Use the .js file extension.
  14. Only embed JavaScript in HTML for code that belongs to the current page and session.
  15. Constrain lines to 80 characters.
    1. Break lines right after operators or comma.
    2. Indent the line after a line break.
  16. Comment Use:
    1. Add meaningful comments
    2. Avoid obvious comments.
    3. Use single-line comments when possible (// rather than /* */).
  17. Declare all variables with var at the beginning of each function.
  18. Declare inner functions right after the var statements.
  19. Put a space between “function” and the opening parens “(” for anonymous functions:
    var myFunc = function (arg) { ... };
  20. Use only letters, digits and underscores for identifiers.
    1. Don’t start identifiers with _.
    2. Don’t use $ or \.
    3. Start all identifiers with lower case, except constructors and global variables.
    4. Start constructors with upper case.
    5. Use ALL_CAPS for global variables.
  21. Do not put more than one statement in the same line.
    1. End all statements with a semi-colon.
  22. Only use expressions as statements for assignments and invocations.
  23. Only use labels (if really needed) in for, while, do, and switch statements.
  24. Do not use parenthesis in return statements. Use this:
    return a

    …instead of…

    return(a)
  25. Do not use the with statement.
  26. Avoid the continue statement.
  27. Whitespace use:
    1. Include a space between any keyword and an open parenthesis: for ( ... ).
    2. Do not put a space between a function name and the open parenthesis: execute(abc).
    3. Include a single space after each comma.
    4. Include a single space after each semi-colon in a for statement.
  28. Use {} instead of new Object().
  29. Use [] instead of new Array().
  30. Only use the comma operator inside the for statement control and then only if it’s absolutely necessary.
  31. Avoid eval().
  32. Do not pass strings to setTimeout() or setInterval(). Instead, pass an actual function or closure.
  33. Do not use the Function construction. Use this:
    var myFunc = function (arg){ statements; };

    …instead of…

    var myFunc = new Function (arg1, { statements; } );

Here are the recommendations we decided not to follow:

  1. Exclude the type attribute from the tag.
    1. We disagree with this recommendation as the type attribute is required in HTML 4. Excluding it will make the HTML invalid.
  2. Place
Nov
08

Useful JavaScript: maxCheckbox

I don’t write a lot of JavaScript. Every now and then I need it to use it solve a design problem. Recently, I needed JavaScript that would make sure that only three checkboxes could be checked at once. Here’s what I came up with in case it’s helpful to someone else.


var current_count = 0;
var max_count = 3;

function maxCheckbox(item) {
if(item.checked) {
if(current_count >= max_count) {
item.checked=false;
alert(’You may only choose ‘+max_count+’ checkboxes.’);
} else {
current_count += 1;
}
} else {
current_count -= 1;
}
}

One
Two
Three
Four
Five

Each time a box is clicked the script runs. If a check mark is being added then the script tests to see if the running total (current_count) is larger than the defined maximum (max_count). If so, then it undoes the checkmark and displays an alert, but if not, then it allows the check and adds one to the current tally. When a box is unchecked, the tally simply decreases by one.

Nov
06

Aptana IDE - Milestone 4

We just released milestone 4 of the Aptana IDE last week. This was mostly a bug fix release. (We’re going to try odd number releases for new features and even number releases for bug fixes and optimizations). However, we did squeeze in a few new features: snippets and improved XHTML support.

If you write HTML, CSS, and JavaScript then you should give Aptana a try. You can see the IDE in action with a number of screencasts we’ve put up on Aptana.tv. Oh, and this is all open source and free.

Nov
04

TwittEarth

Wow, I like TwittEarth. I’m not big on the monster icons, but, hey, the experience is still very cool.

TwitterVision has a 3D live tweet map too, using Poly9’s (great studio in Quebec City) FreeEarth application.

I’d love to see a trip animated in FreeEarth. Perhaps a mashup with Dopplr? It would seem easily possible.

Nov
02

Performance of Comet and Simple Pipe

About one and a half months ago, I introduced Java2Script Simple Pipe, another Comet implementation. At that time, I knew there were lots of performance issues on such Comet technology. Because at that time I were busy and it was not a urgent deal for me, I didn’t write test codes to test out the performances at that moment.

Only recently, I took some tests on performance issues. And the results said Simple Pipe’s Comet implementation performs really bad!

Opening 10 Comet connections using Simple Pipe does not affect the whole server. But when I opened 20 Comet connections, the CPU usage is up to 100% quickly! It’s not a problem of the application logics. It is a matter of Comet connection.

Java2Script Simple Pipe supports switching pipe mode into query mode. It is very easy, just call a static method:

SimplePipeRequest.switchToQueryMode(250);

After switching to query mode for the pipe, I can open up to 100+ connections to the server to receive stream data back to browser. The peak of CPU usage is about 60% ~ 70%. The average CPU usage may be about 20%-30%. It is an acceptable technology with such performances under the pressure tests.

( I did not test those server with special Comet optimizations. I just tested Simple Pipe on Apache Tomcat 5.5. Maybe those Comet optimized should have a better results. )