Thursday, June 30, 2005

Take a Walk on the Wild Side

I recently found myself in the interesting position of being asked by my client to help them write a web service client...in Java. I know basically nothing about Java, but I'm usually pretty good about picking things up quickly, so I dove in. I don't think I have anything particularly technical to add to the body of knowledge, but I thought I'd relate my experience as a complete Java n00b in the web services space.


My initial involvement in the effort happened after the client's attempts to get Axis working failed. This was probably due to the fact that Axis seems to be primarily a server-side technology, and they need to get it working from within an applet running in a browser (they're providing a rich UI for a complicated part of an ASP.NET web application). I imagine we could have gotten Axis to work had we banged on it for long enough, but this part of the project was rapidly becoming the biggest schedule risk. So I went and asked some of my smart Java friends what they recommended as an alternative.


One of them suggested XFire. It seemed like a reasonable alternative, but my client was unable to get it working either, even after a few days of hacking on it. Meetings were called, and more and more senior managers were called in. This is where I took an active hand.


Not knowing anything about Java or Java web service toolkits, I figured that given all the knobs and buttons we were having trouble figuring out, the most predictable route was one that eschewed web service toolkits entirely. So I asked some smart friends again, and got pointed to JAXB, which is Sun's equivalent of XmlSerializer. Once I located xjc.bat, I was able to generate some simple classes and to serialize/deserialze them to/from XML within a few hours.


At that point, I felt a lot better. The code to do low-level HTTP in Java is pretty straightforward, and with the JAXB-generated classes, I knew we'd be able to do what we needed to do. But since I was now slightly ahead of the three days I told my client it would take me to figure out the problem, I decided to spend a little time working with SAAJ, which is the next layer in Sun's web service stack. It abstracts away the HTTP part of doing XML web services. I figured it was worth a little time to experiment, as it was likely a higher-quality version of the code I was going to wind up writing myself anyway. As it turned out, it was also pretty easy to figure out, and after a few more hours I was able to use my JAXB classes together with the SAAJ stuff to call a simple .NET web service successfully.


The last part of the infrastructure I wrote by hand. It was a fairly simple XSLT that would walk a WSDL document and generate a Java proxy class that would make the SAAJ calls I'd figured out. That took me another few hours. All told I had something workable in around a day and a half. It's not the world's most robust thing right now, but it unblocked the guy who's writing the applet, and that's a Very Good Thing. As we move forward, I'm sure we'll need to add things like better SOAP fault handling, but I don't think that's going to be too terribly difficult either.


The bottom line of all this is that - in the Java world - it appears to have been much easier for me to get up and running with low-level, XML-oriented APIs in Java than with a big OO-oriented toolkit (Tim would be proud). I am, of course, no expert in Java, and the real test will come as we try to use the code I generated in a production application, but I found the experience quite interesting.

Sunday, June 26, 2005

Visual Studio Guidelines

Via John Robbins, I came across this little gem today. It's a registry setting that lets you display vertical guidelines in Visual Studio (2002, 2003, or 2005). This is handy as a cue that you might be writing lines that will be too long for your teammates to read without scrolling. Looks a bit like this:



Here's a .reg file for doing it in VS.NET 2003. Note that I've set my guides in columns 80 and 120 - you'll probably want something different.


Windows Registry Editor Version 5.00


[HKEY_CURRENT_USER\Software\Microsoft\VisualStudio\7.1\Text Editor]
"Guides"="RGB(128,0,0) 80, 120"

Wednesday, June 22, 2005

PerformanceCounter Slowness Explained

The unparalleled David Gutierrez from Microsoft stopped by and left a comment on my post about horrible PerformanceCounter slowness. His explanation in its entirety:



 I can shed some light on these issues. PerformanceCounters use a machine wide memory mapped file to publish perf counter data. That file contains an object graph and various places we use as spinlocks.


The problem comes in when processes get killed unexpectedly. A process which dies while holding a spinlock won't release it, meaning the next process gets blocked. After spinning 10000 times, we assume some process died and continue on, so we won't block forever - 4 minutes on your machine. My guess is that IIS is terminating your app when it resets it.

In Whidbey we've fixed these problems. If you're interested, I can post a blog entry with more details.

The bug you mention actually isn't related. It has to do with reading perf counters, and that really is horribly slow. It was also specific to services.


Obviously, I still need to track down why this is happening, but I think his guess is likely a good one: ASP.NET worker process resets could be dropping the spinlock on the floor. Many thanks to Mr. Gutierrez!

Tuesday, June 21, 2005

PerformanceCounter Constructor Horribly Slow

I'm doing some work on FlexWiki, and I'm finding that this call:


PerformanceCounter answer = new PerformanceCounter(s_PerformanceCounterCategoryName, name, false);


is sometimes taking a really, really long time to come back. Like several minutes. I started tracking it down via Reflector and native debugging, and it looks as though PerformanceCounter internally spins in this loop, inside a BCL-internal class called SharedPerformanceCounter:


int num1 = SharedPerformanceCounter.MaxSpinCount;
while (spinLockPointer[0] != 0)
{
  Thread.Sleep(1);
  num1--;
  if (num1 == 0)
  {
    spinLockPointer[0] = 0;
  }
}


Aside from the fact that this looks thread-unsafe to me, I'm not entirely sure what it's waiting for at this point. But given that MaxSpinCount is 10000, on my machine that seems to work out to around four minutes, so that explains where the delay is coming from. But what I don't understand is under what conditions this occurs - the SharedPerformanceCounter code is a bit hard to wade through, and I haven't made much headway with it.


In an RTFM moment, Shawn Van Ness suggested I look over at the Product Feedback Center to see if there were any similar bugs. I'd Googled, but hadn't landed there, although I should have thought of it. At any rate, when I did look I found this rather disturbing bug. Why disturbing? Because it implies that slowness in PerformanceCounter is to be expected. Although one could also read the bug report to merely indicate that the service hanging because of a long-running operation is the expected behavior. Either way, not very helpful.


Anyway, I haven't been able to figure anything out on this, so I'm blogging it. Ideally someone will know what I'm doing wrong. As a second best, perhaps the entry will serve as a sanity check for others with the same problem. Has anyone seen this constructor take a really, really long time to come back before?

Thursday, June 16, 2005

David Ornstein FlexWiki Interview on Channel9

David Ornstein - who wrote most of FlexWiki - was interviewed on Channel9 and made the front page. In the interview, he talks about the history and philosophy of FlexWiki, why he created it, and how it's being used inside of Microsoft.


Oh, and he mentions my name in the last minute or two of the interview, so you can just fast-forward to that part if you like. :)

Tuesday, June 14, 2005

TiddlyWiki

My friend Pinku posted a link to TiddlyWiki the other day. While I'm not quite sure I share his assessment of it as “the most amazing Javascript web app ever” I would definitely agree that it is a rather impressive application. If you're too lazy to go click the link, it's a full-up wiki running client-side, entirely within your browser. Very clever.

Monday, June 13, 2005

Interactive Mode for JavaScript.NET

Ever since I read Don's post the other day pointing out the often-overlooked support for a powerful command-line scripting languge in Windows (Javascript), I've been meaning to post this. It's a batch file that will let you run JScript.NET files interactively. Since Javascript is a compiled language, it does this by compiling it to a temporary directory first and then running the compiled EXE. While this might sound slow, as it turns out it's quite acceptable for quick, scripting-type tasks, and it gives me what I've always wanted: a convenient scripting language with full, natural-sytnax access both to COM and the .NET libraries.


Much as I'd like to claim credit for the batch file, I can't. It was written by John Elliott (for whom I don't have a URL) and posted to the WinTech Off-Topic List. The only modification I made was to add the /fast- switch to the compile, which turns off “fast mode”. Near as I can tell (not yet being that familiar with JScript.NET), it makes the code somewhat slower, but enables a lot of the more “scripty” features of the language, such as the ability to add methods dynamically to BCL types. Anyway, here's the script. I called mine rjs.cmd, and stuck it in my \bin directory, which is in my path. Then I can launch scripts by simply running “rjs foo.js“.





@echo OFF

rem ///////////////////////////////////////////////////////////////////////
rem // js-net-script.cmd
rem // ====================================================================
rem //
rem // Compiles and runs a JScript.NET source file.
rem //


goto :INIT


rem ///////////////////////////////////////////////////////////////////////
rem // HELP procedure
rem // ==============
rem //
rem // Display brief help message
rem //


:HELP


 if defined TRACE %TRACE% [proc %0 %*]
 
 echo Compiles and runs a JScript.NET source file as a console application.
 echo.
 echo JS-NET-SCRIPT script [args]
 echo.
 echo   script       Path to the JScript.NET file you wish to compile and run.
 echo   args         Any arguments you wish to pass to the JScript.NET app.
 echo.


goto :EOF



rem ///////////////////////////////////////////////////////////////////////
rem // MAIN procedure
rem //


:MAIN


 if defined TRACE %TRACE% [proc %0 %*]


 rem // make sure our working directory exists.
 rem // this is where our build outputs will be stored temporarily.
 if not exist "%APPDATA%\js-net-script" mkdir "%APPDATA%\js-net-script"


 rem // determine the various path information we'll need to compile
 rem // and run our script.
 set _ScriptPath=%APPDATA%\js-net-script\%~nx1
 set _ExePath=%_ScriptPath%.exe
 set _LogPath=%_ExePath%.log


 rem // copy the script to ensure it is on a local disk.
 copy "%~f1" "%_ScriptPath%" >nul 2>&1
 if errorlevel 1 set ERR=%errorlevel% && goto :ERROR


 rem // compile the script. we use a debug build so that we can
 rem // break into the debugger. we also log the build results to a
 rem // log file, so that we can show them to the user if there is
 rem // a problem.
 %SYSTEMROOT%\Microsoft.NET\Framework\v1.1.4322\jsc.exe /out:"%_ExePath%" /target:exe /debug+ /fast- /nologo "%_ScriptPath%" > "%_LogPath%" 2>&1
 if errorlevel 1 set ERR=%errorlevel% && goto :ERROR


 rem // run the application, passing in arguments.
 "%_ExePath%" %*


 rem // delete the local copy of the script, and all build outputs.
 del /s /q "%_ScriptPath%*" >nul 2>&1


goto :EOF



rem ///////////////////////////////////////////////////////////////////////
rem // INIT procedure
rem //


:INIT


rem @if not "%ECHO%"=="" echo %ECHO%
@if not "%OS%"=="Windows_NT" goto DOSEXIT


rem Set local scope and call MAIN procedure
 
setlocal & pushd & set RET=


 set SCRIPTNAME=%~n0
 set SCRIPTPATH=%~f0
 
 if "%DEBUG%"=="1" (set TRACE=echo) else (set TRACE=rem)
 
 if /i {%1}=={/help} (call :HELP %2) & (goto :HELPEXIT)
 if /i {%1}=={/?} (call :HELP %2) & (goto :HELPEXIT)


 :INIT_MAIN


 set _SAVED_PROMPT=%PROMPT%
 set PROMPT==$g


 call :MAIN %*


 set PROMPT=%_SAVED_PROMPT%


 :HELPEXIT


 popd & endlocal & set RET=%RET%


goto :EOF



rem ///////////////////////////////////////////////////////////////////////
rem // ERROR procedure
rem // ===============
rem //
rem // Abnormal exit. Expects the errorlevel has been stored in %ERR%.
rem //


:ERROR


 if defined TRACE %TRACE% [ERROR! %0 %*]
 
 echo.
 echo WARNING: Script failed with errorlevel: %ERR%
 echo.
 echo   Current directory is:
 echo     %CD%
 echo   Command-line was:
 echo     %CMDCMDLINE%
 echo.


 rem // show the build log. note: we'll show it in the console, but we
 rem // could also popup notepad.exe
 echo Compiler output:
 echo.
 type "%_LogPath%"
 echo.


 rem notepad "%_LogPath%"


 rem // give the user a chance to see the results.
 rem // note: this is not necessary if we open the log file in notepad.
 rem // note: while paused here, you can copy the build outputs from
 rem // the working directory in %APPDATA% to run ildasm, etc.
 pause


 rem // clean up all the build outputs.
 del /s /q "%_ScriptPath%*" >nul 2>&1


goto :EOF



rem ///////////////////////////////////////////////////////////////////////
rem // DOSEXIT
rem // ====================================================================
rem //
rem // These must be the final lines in the script.
rem //


:DOSEXIT


 echo This script requires Windows NT or later.


rem ///////////////////////////////////////////////////////////////////////



Friday, June 3, 2005

SoundMeter

Someone emailed me today asking if I had any plans to extend my DirectSound tutorial to show how to read from a microphone. I don't really have time to write a full-fledged tutorial right now, but I did have a few minutes to post some code I'd written quite a while ago. It's a little snippet that you can use to implement a poor-man's volume meter, and it does show how to capture a waveform using DirectSound. Check it out here.