|
|
||
Chris Campbell's BlogApril 2006 ArchivesThe World's Slowest Web ServicePosted by campbell on April 26, 2006 at 05:03 PM | Permalink | Comments (17)
The Set Up
Person: This rendering op is so slow...
Audience: How slow is it?
Person: It's so slow that it would be faster to air mail each
individual pixel to Timbuktu and back.
A few years ago when the phrase "web services" became all the rage we had to update the punchline:
Person: It's so slow that it would be faster to implement this
op as a web service and host the server in Timbuktu.
Okay, so you're not laughing, but I warned you earlier, I did. Plus, it doesn't help that our collective senses of humor have all been addled recently by Chet and his killer puns (Minneapplet anyone?)... But seriously forks, all the web service yumminess being integrated into Mustang has peaked my interest, especially from the desktop Java standpoint. I've seen a few JAX-WS 2.0 tutorials recently (see "Useful Resources" section below), but most are written from the server-side perspective, and therefore start out with "download the latest GlassFish build" or "grab the latest JWSDP release" or something similar. Already that's one too many steps for my lazy self. I'm a minimalist at heart, so what I really wanted to know was how quickly one could get up and running with JAX-WS using only the latest Mustang binaries. And what better way to learn than to bring that old "joke" to life, so I now present to a truly contrived example: a pixel blender service (and client).
Step 1: Write and compile the endpoint
package blend.endpoint;
import javax.jws.WebMethod;
import javax.jws.WebService;
import javax.xml.ws.Endpoint;
@WebService(serviceName="BlenderService")
public class Blender {
@WebMethod
public int blend(int src, int dst) {
int srcA = src >>> 24;
int srcR = (src >> 16) & 0xff;
int srcG = (src >> 8) & 0xff;
int srcB = (src ) & 0xff;
int dstA = dst >>> 24;
int dstR = (dst >> 16) & 0xff;
int dstG = (dst >> 8) & 0xff;
int dstB = (dst ) & 0xff;
int resA = (int)((srcA * 0.5) + (dstA * 0.5));
int resR = (int)((srcR * 0.5) + (dstR * 0.5));
int resG = (int)((srcG * 0.5) + (dstG * 0.5));
int resB = (int)((srcB * 0.5) + (dstB * 0.5));
return (resA << 24) | (resR << 16) | (resG << 8) | resB;
}
}
The "serviceName" parameter on
As the final part of this step, we will simply compile this source file:
Step 2: Generate the endpoint "portable artifacts"
We pass the
Step 3: Generate the client "portable artifacts"
The
Step 4: Write and compile the client application
package blend.client;
public class Test {
public static void main(String[] args) throws Exception {
BlenderService service = new BlenderService();
Blender blender = service.getBlenderPort();
int src = 0xff00ff00;
int dst = 0xff0000ff;
int res = blender.blend(src, dst);
System.out.printf("src=%08x dst=%08x result=%08x\n",
src, dst, res);
}
}
Note that by default this testcase will talk to the web service endpoint running at
Step 5: Publish the endpoint
package blend.endpoint;
import javax.xml.ws.Endpoint;
public class Test {
public static void main(String[] args) throws Exception {
Endpoint e = Endpoint.create(new Blender());
e.publish("http://127.0.0.1:8084/blend");
System.out.println("Endpoint running");
try {
Thread.sleep(300000);
} catch (InterruptedException ex) {
}
e.stop();
System.out.println("Endpoint stopped");
}
}
This code will publish the web service endpoint on the local machine on port 8084, and will keep it running for 5 minutes. You can run compile and run this testcase easily:
Note that the Endpoint API in Mustang is mainly useful for testing purposes. If you were to publish this for real, you'd probably want to deploy it on one of them application server things the server-side folks like to talk about these days.
Step 6: Run the client application
First fire up the endpoint (Blender Endpoint) using this link (thanks to Romain for hosting the binaries):
Then once the endpoint is running, try running the client app (Blender Client):
Click the button and behold, it should look something like this:
If all goes well, you should see the blended image filling in very, very slowly in the middle of the window. Basically, the app is consulting the Blender web service running on your machine, one pixel and one scanline at a time. Scary, and useless! (By the way, the source code for this application demonstrates a couple other Mustang features, namely SwingWorker and the Desktop integration API, in case you're curious.)
Conclusion
At some point I'd like to go into more detail about my issues with JAX-WS, but I've got a plane to catch! I'll be away for a couple weeks, so hopefully you'll understand if I don't respond to any comments right away. Useful Resources
In my ears: Destroyer, "Destroyer's Rubies"
Five Easy PiecesPosted by campbell on April 24, 2006 at 01:04 AM | Permalink | Comments (8)I'm looking forward to a 2-week vacation in Greece that begins this week, so my mind is prone to wandering these days. Therefore, I wanted to share with you a few short tidbits about some recent/nifty Mustang (Java SE 6) putbacks before they are indefinitely purged from my brain. These fixes and features are small compared to most others in Mustang, but sometimes it's the little things that help round out a release, even for one that already contains so much desktop goodness. And away we go, in no particular order...
AlphaComposite.derive(float alpha)
It's super easy to code up a fade effect in Java 2D using the AlphaComposite class, but eventually your fingers will tire of writing the following verbose code:
g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER,
alpha));
Carpal Tunnel? Suffer no more! Mustang will save you a few keystrokes:
g2d.setComposite(AlphaComposite.SrcOver.derive(alpha));
Clear, concise, nice! This new method saves Romain so much time that he can invent twice as many ridiculous office weapons as before. I recently had to work on a project that needed to run on JDK 5, and if there was one thing I wish I had from Mustang, it was AlphaComposite.derive()!
GTK L&F Default Font
In Tiger and earlier builds of Mustang, Swing's GTK L&F would simply use the default "Dialog" font. In most cases, the chosen font would not be the same as the one used by native GTK applications, and as a result Java applications would look woefully out of place. However, as of Mustang b77, the GTK L&F now consults the fontconfig library, so Swing applications will pick up the same desktop font used by native GTK applications. Clearly this fix is long overdue; it required quite a bit of work, so I'm grateful that Phil fixed this for Mustang (and now I don't have to pester him anymore)! Native fidelity of the GTK L&F has improved considerably in Mustang, and this fix played no small part, but in my opinion we still have a ways to go, so keep those contributions coming...
Double Precision for GeneralPath
This issue has come up at every Java 2D BOF at JavaOne for as long as I can remember, and I'm glad to say that this year we'll finally be able to say that it's available in Mustang. The GeneralPath class has always looked a bit strange without a "double" counterpart, and beyond the obvious symmetry issue, GeneralPath has not been sufficient from a technical standpoint for many advanced users, especially those in the GIS and mapping industries (see the bug report for one such justification). This is another long overdue enhancement, but it required a surprising amount of investigation to come up with a solution that fits in well with the existing java.awt.geom.* class hierarchy, performs well, and is easy to use. The solution that Jim devised, with help from our community friend "leouser", required lots of thought, but it was worth the wait. There is now a Path2D class (with Float and Double variants) in the java.awt.geom package, which will look familiar to longtime Java 2D users. The GeneralPath class is now a trivial subclass of the Path2D.Float class, so your code will continue to work as always with single point precision, but now you have the option to migrate to the new Path2D.Float/Double classes to make the choice of storage a bit more explicit in your code.
OpenGL Acceleration of LCD Text
If you've read Chet's blog or article on the subject, you'll know that it takes quite a bit more computation to get LCD-optimized text onto the screen (when compared to grayscale or monochrome text). As of Mustang b77, the text rendering codepath in the OpenGL-based Java 2D pipeline has been revamped to allow for acceleration of LCD text, in addition to the existing (and very fast) grayscale/monochrome codepath. This is especially noteworthy because it is the first time we have leveraged programmable fragment shader technology in Java 2D. We spent a number of weeks experimenting with a number of approaches in order to achieve maximum performance, and that work has mostly paid off. The performance benefits aren't so noticeable on first and second generation shader-level hardware, but advancements are happening so fast in the graphics hardware space that I think this work will really pay off on today's hardware and beyond (think Nvidia GeForce 7800, ATI Radeon x1800, etc). Unfortunately when this work was putback last month, there were a couple unresolved driver bugs that prevented us from enabling this support by default (see the above bug report for more details on performance as well as the magic incantation to enable this new codepath). Since then, I'm happy to say that both Nvidia and ATI have addressed those issues, but the fixes are not yet in publically available drivers. Once we're satisfied with those driver fixes, we should be able to turn this codepath on by default, when the OGL pipeline is enabled of course. While we're on the subject of driver fixes, I'd like to quickly say thanks to Andy Ritger and team at Nvidia, and Matthew Tippett and Balaji Calidas at ATI, for all their help the past couple years in resolving the remaining driver kinks affecting Java 2D and our OGL pipeline. It's been a lot of work, but the collaboration has paid off and I'm hoping that by the time Mustang ships the last couple outstanding driver issues will be resolved.
Multi-stop Linear/RadialGradientPaints
If you're familiar with the Batik SVG library, you may have used the multi-stop gradient paint classes that are included with it. Those classes were originally written by an intern on the Java 2D team, Nico Talian, way back in the year 2000 (when I was just a lowly intern myself!). The code was donated to the Batik project at that time and the classes have served their purpose well, but in recent years there have been quite a few requests to include these classes with the core JDK. Well, mostly it's been Josh, Richard, and Romain who have been doing the requesting on behalf of SwingLabs (check out their recent work on "painters"), and eventually they wore me down enough so that I'd take on this project. So, we cleaned up the original API and got it into Mustang just in time for b81. The JavaDocs for these new classes include a few basic (yet pretty) images to illustrate the various options: You can also download the latest Mustang snapshot and try the updated "GradAnim" pane in Java2Demo, which demonstrates these new multi-stop gradient classes. (Oh, and before anyone yells at me for not mentioning this, the standard disclaimer applies that these new classes are not officially "in" until the Mustang JSR community -- and the proverbial fat lady -- say so.) The biggest benefit of having these classes in the core JDK, other than the convenience factor, is that we are now able to provide hardware acceleration for these operations, which has been impossible up until this point. As you may know, the OpenGL pipeline already accelerates the basic GradientPaint and TexturePaint operations in hardware for ridiculously good performance (GradientPaint for example is as much as 25x faster via OpenGL than in software!)... When I get back from vacation, I hope to provide similar acceleration for LinearGradientPaint and RadialGradientPaint when the OpenGL pipeline is enabled. More fun with fragment shaders awaits!
More to come...
In my ears: Neu!, "Neu! 2"
| ||
|
|