September, 2005

Larry Osterman's WebLog

Confessions of an Old Fogey
  • Larry Osterman's WebLog

    Beresheit, with sidekicks (from the New Yorker, via Monica Cellio's blog)

    • 7 Comments

    Monica (old friend from college) linked to it, I nearly had to clean up my monitor after reading it...

    Day No. 1:

    And the Lord God said, “Let there be light,” and lo, there was light. But then the Lord God said, “Wait, what if I make it a sort of rosy, sunset-at-the-beach, filtered half-light, so that everything else I design will look younger?”

    “I’m loving that,” said Buddha. “It’s new.”

    “You should design a restaurant,” added Allah.

    http://www.newyorker.com/printables/shouts/050926sh_shouts

     

    Edit: fixed link to Monica
  • Larry Osterman's WebLog

    The Amazing Race: Family Edition, first impressions (no serious spoilers)

    • 4 Comments

    Interesting.

    I think I'm going to like it - the kids aren't as bad as I had feared (the Gaghan kids are cute, although I thought "She'll be coming 'round the mountain" was cruel (and funny)).  The Gaghan girl (Carissa) is 9 going on 20.  Oh, and "Sorry I couldn't participate more" "Get used to it, dork!" - it had us in stitches for about 5 minutes.

    I'm wondering if the SUV's are going to be kept for the entire race - that might make things quite interesting, actually.

    The Paolo family is going to drive me nuts.

    I actually like the Schroeder family, Dad's sense of humor reminds me of my father's :)

    I'm hoping that the pink ladies tone the screaming down a bit.

    I'm finding myself rooting for the Aiello's, although Dad looks like his shoulders are somewhere above his ears.

     

    Oh, and Kevin and Drew make a cameo!  That was awesome (it almost made the entire show for me), even if nobody but the Paolo kid seemed to recognise them.  If this continues, it'll be awesome.

    In general, not bad - different from the normal TAR, but not bad at all.

     

    Hopefully this is sufficiently spoiler-free for the people who don't get to see the show live.

    Edit: Added "get used to it" comment, I'd forgotten it last night.

     

  • Larry Osterman's WebLog

    Anniversaries

    • 24 Comments
    Judaism has a tradition that on the anniversary of a loved ones death, one lights a candle (known as a Yahrzeit candle).  Since it's a tradition, there are no laws associated with it, so each person chooses their own time to light a candle.  Yahrzeit candles are designed to burn for 24 hours so that they will be lit during the day of morning.

    I have a yahrzeit candle burning in my office today, because today would have been my father's 71st birthday, he died six weeks ago on August 14th (of complications related to a bee sting, go figure).

    I've avoided writing about it because I've not really known how to express the loss (beyond saying "it sucks"), and I'm not really into public grieving, but I feel it's important to say something right now.

    I truly miss my father - we didn't talk much beyond holidays, but it doesn't matter - knowing I could always call him up was enough.  And now I can no longer do that.

    It's wierd.  After a death, you go on with your life and everything's just fine, and all of a sudden, the loss really hits home, usually when you don't expect it.  I totally lost it a couple of weeks ago when watching "The Sound of Music" when Christopher Plummer started singing "Edelweiss" (my sister-in-law sang it at Dad's funeral).  Similarly, on Saturday night, while watching "The King and I", I totally lost it at the end - I usually cry at the sad parts of musicals, but this one was personal.  I relate to Prince Chulalongkorn at a totally different level now.

    So much of who I am comes from my father - we were so much in common.  There's no question that I got my love for the stage (musicals in particular) from him, and also my interest in photography. 

    I so miss the ability to talk with him about whatever - the law, tech, shows - it didn't seem to matter, Dad knew about everything.

    I have so many wonderful memories of Dad, and I regret that I won't be able to make any new ones.

     

    So Happy Birthday, Dad.  I miss you.

     

  • Larry Osterman's WebLog

    New Audio APIs for Vista

    • 22 Comments

    In an earlier post, I mentioned that we totally re-wrote the audio stack for Windows Vista.  Today I want to talk a bit about the APIs that came along with the new stack.

    There are three major API components to the Vista audio architecture:

    • Multimedia Device API (MMDEVAPI) - an API for enumerating and managing audio endpoints.
    • Device Topology - an API for discovering the internals of your audio card's topology.
    • Windows Audio Session API ((WASAPI) - the low level API for rendering audio.

    All the existing audio APIs have been re-plumbed to use these APIs internally, for Vista, all audio goes through these three APIs.  For the vast majority of the existing audio applications, things should "just work"...

    In general, we don't expect that anyone will move to these new APIs, they're documented for completeness reasons, but the reality is that unless you're dealing with extremely low latency audio (sub 20ms), or writing a control panel applet for a specific audio adapter, you're not likely to ever want to deal with them (the new APIs really are very low level APIs - using the higher level APIs is both easier and less error prone).

    MMDEVAPI:

    MMDEVAPI is the entrypoint API - it's a COM class that allows applications to enumerate endpoints and "activate" interfaces on them.  Endpoints fall into two general types: Capture and Render (You can consider Capture endpionts as microphones and line in, Render endpoints are things like speakers).  MMDEVAPI also allows the user to manage defaults for each of the types. As I write this, are actually three different sets of defaults supported in Vista: "Console", "Multimedia", and "Communications".  "Console" is used for general purpose audio, "Multimedia" is intended for audio playback applications (media players, etc), and "Communications" is intended for voice communications (applications like Yahoo! Messenger, Microsoft Communicator, etc). 

    Windows XP had two sets of defaults (the "default" default and the "communications" default), we're adding a 3rd default type to enable multimedia playback.  Consider the following scenario.  I have a Media Center computer.  The SPDIF output from the audio adapter's connected to my home AV receiver, I have a USB headset that I want to use for VOIP, and there are stereo speakers connected to the machine that I use for day-to-day operations.  We want to enable applications to make intelligent choices when they choose which audio device to use - the default in this scenario is to use the desktop speakers, but we want to allow Communicator (or Messenger, or whatever) to use the headset, and Media Center to use the external receiver.  We may end up changing these sets before Vista ships, but this give a flavor of what we're thinking about.

    MMDEVAPI supports an "activation" design pattern - essentially, instead of calling a class factory to create a generic object, then binding the object to another object, with activation, you can enumerate objects (endpoints in this case) and "activate" an interface on that object.  It's a really convenient pattern when you have a set of objects that may or may not have the same type.

    Btw, you can access the category defaults using wave or mixer messages, this page from MSDN describes how to access them - the console default is accessed via DRVM_MAPPER_PREFERRED_GET and the communications default is accessed via DRVM_MAPPER_CONSOLEVOICECOM_GET.

    Device Topology:

    Personally, I don't believe that anyone will ever use Device Topology, except for audio hardware vendors who are writing custom control panel extensions.  It exists for control panel type applications that need to be able to determine information about the actual hardware. 

    Device Topology exposes collections of parts and the connections between those parts.  On any part, there are zero or more controls, which roughly correspond to the controls exposed by the audio driver.  One cool thing about device topologies is that topologies can connect to other topologies.  So in the future, it's possible that an application running on an RDP server may be able to enumerate and address the audio devices on the RDP client - instead of treating the client as an endpoint, the server might be able to enumerate the device topology on the RDP client and manipulate controls directly on the client.  Similarly, in the future, the hardware volume control for a SPDIF connector might manipulate the volume on an external AV receiver via an external control connection (1394 or S/LINK).

    One major change between XP and Vista is that Device Topology will never lie about the capabilities of the hardware - before Vista, if a piece of hardware didn't have a particular control the system tried to be helpful and provide controls that it thought ought to be there (for instance if a piece of hardware didn't have a volume control, the system helpfully added one).  For Vista, we're reporting exactly what the audio hardware reports, and nothing more.  This is a part of our philosophy of "don't mess with the user's audio streams if we don't have to" - emulating a hardware control when it's not necessary adds potentially unwanted DSP to the audio stream.

    Again, the vast majority of applications shouldn't need to use these controls, for most applications, the functionality provided by the primary APIs (mixerLine, wave, DSound, etc) are going to be more suitable for their needs.

    WASAPI:

    WASAPI is the "big kahuna" for the audio engine.  You activate WASAPI on an endpoint, and it provides functionality for rendering/capturing audio streams.  It also provides functions to manage the audio clock and manipulate the volume of the audio stream.

    In general, WASAPI operates in two modes.  In "shared" mode, audio streams are rendered by the application and mixed by the global audio engine before they're rendered out the audio device.  In "exclusive" mode, audio streams are rendered directly to the audio adapter, and no other application's audio will play.  Obviously the vast majority of applications will operate in shared mode, that's the default for the wave APIs and DSound.  One relatively common scenario that WILL use exclusive mode is rendering content that requires a codec that's present in the hardware that Windows doesn't understand.  A simple example of this is compressed AC3 audio rendered over a SPDIF connection - if you attempt to render this content, if Windows doesn't have a decoder for this content, then DSound will automatically initialize WASAPI in exclusive mode and will render the content directly to the hardware.

    If your application is a pro audio application, or is interested in extremely low latency audio then you probably want to consider using WASAPI, otherwise it's better to stick with the existing APIs.

    Tomorrow: Volume control (a subject that's near and dear to my heart) :)

  • Larry Osterman's WebLog

    What's an audio endpoint?

    • 11 Comments

    One of the parts of the audio engine rework was a paradigm shift in how audio devices are addressed.

    Before Vista, audio devices were enumerated (more or less) by the KSCATEGORY_AUDIO PnP devinterface that exposed a Wave filter.

    The big problem with this is that it doesn't even come close to representing how users think about their audio solution (audio adapter, USB audio device, motherboard audio chipset connected to output speaker and microphone jacks).  I'm willing to bet that 90% of the people reading this post have no idea what a "KSCATEGORY_AUDIO PnP devinterface that exposed a Wave filter" is.  But every single one of you knows what a speaker is.

    It also turns out that the PnP definition is unnecessarily simplistic.  It doesn't cover scenarios where the device that renders the audio isn't physically attached to the PC.  There are a number of these scenarios in Windows today (for instance, remote desktop audio is a perfect example), and to solve them, developers have designed a number of hack-o-rama solutions to the problem, none of which is particularly attractive.

    For Vista, what we've done is to define a new concept called an "audio endpoint".  An "audio endpoint" represents the ultimate destination for audio rendering.  It might be the speakers on your local workstation, it might be speakers on the workstation of a remote machine running an RDP client, it might be the speakers connected to the receiver of your home stereo, it might be the microphone or headset connected to your laptop, it might be something we've not yet figured out.

    The key thing about an audio endpoint is that it represents a piece of plastic, and NOT a PnP thingamajig[1].  The concept of endpoints goes directly to the 3rd set of problems - troubleshooting audio is simply too hard, because the objects that the pre-Vista audio subsystem referenced dealt with the physical audio hardware, and NOT with the things to which users relate.

    Adding the concept of an audio endpoint also makes some scenarios like the RDP scenario I mentioned above orders of magnitude simpler.  Before Vista, remote desktop audio was implemented with a DLL that effectively replaced winmm on the RDP server and redirected audio to the RDP client.  With this architecture, it would have been extremely difficult to implement features like per-application volume and other DSP related scenarios for remote clients.  For Vista, remote desktop audio was implemented as an audio endpoint.  As such, applications running on a remote desktop server function just like they would on the local machine - instead of bypassing the audio engine in the client application, remote desktop audio runs through the audio engine just like local audio does, it gets redirected at the back end of the engine - instead of playing out the local audio adapter, the audio is redirected over the RDP channel.

    Once again, some of this stuff won't appear until Vista Beta2 - the Beta1 RDP code still uses the old RDP infrastructure.  In addition, while the endpoint mechanism provides a paradigm that allows a mechanism to address the speakers connected to your AV receiver as an endpoint, the functionality to implement this doesn't exist in Vista.

    [1] Did you know that Microsoft Offices spelling corrector will correct the spelling of  thingamajig?

  • Larry Osterman's WebLog

    Windows Audio Quality Enhancements

    • 16 Comments
    In my last post, I mentioned the architectural thrust behind the Vista audio changes.

    I left off explaining how we're dealing with problem #2 - the audio quality issue (because it deserves an entire post on its own).

    There were a couple of significant problems with audio quality in the pre-Vista audio stack.  The first (and probably most significant) had to do with the audio format being rendered.

    Before Vista, the kernel audio stack set the output audio format to match the format of the audio being played.  Normally, this isn't a problem, since it means that we do less DSP of the signals.  Unfortunately, it can lead to some rather unanticipated consequences.  For instance, if you're playing a system sound (usually stereo, 22kHz), at the same time you start playing your MP3 files, then the MP3 file rendering happens at 22kHz, which is a noticeable  degradation of audio quality.  Once the audio system goes quiet, the rendering format will reset to the format of the content being played, but that may be quite some time later.

    Another problem that the pre-Vista audio stack had was that the DSP wasn't particularly good.  Because the audio stack worked with integer math, it turns out that many of the calculations involved in the audio processing suffered from significant rounding errors.

    For Vista, we worked to fix both of these problems.

    First off, we removed the behavior that auto-selected the output format.  Instead, the system chooses an intelligent default output format (based on the formats that the device claims to support), and we've added UI to allow the user to override the default.  This selected format will be the output format for all content, regardless of the format of the content being rendered.  It's the responsibility of a system that uses the audio engine to ensure that it matches the output format providing whatever format conversions are necessary to match the output format.

    The good news is that application authors don't typically have to care about this, for all the higher level audio APIs (waveXxx, DSound, MF, etc), we automatically insert the appropriate format converters between the source format and the output format.

    The other significant change we made to ensure high fidelity audio rendering is that we converted the entire audio pipeline from dealing with 16bit integers to 32bit floating point values.

    I have to say that originally I was quite skeptical about this change - I thought that floating point rounding errors would cause massive problems, but it turns out that using floating point values allows us to get 24bits of accuracy with no rounding errors at all.  This allows our DSP to have significantly fewer rounding errors when performing calculations on the audio.  We're also deploying a new higher quality rate converter that the Windows Codec team developed, which will also have a huge impact on the quality of audio when we DO have to perform sample rate conversions during the mix.

    The end result of these changes should be a significant improvement in the quality of audio being rendered, especially on UAA compatible audio adapters.

     

  • Larry Osterman's WebLog

    What's up with Audio in Windows Vista?

    • 43 Comments

    Steve Ball (the GPM for the MediaTech group (of which Windows Audio is a part)) discussed some of these changes in the Windows Audio Channel 9 video, but I'd like to spend a bit more time talking about what we've done.

    A lot of what I'm discussing is on the video, but what the heck - I've got a blog, and I need to have some content to fill in the white space, so...

     

    The Windows audio system debuted in Windows 3.1 with the "Multimedia Extensions for Windows", or MME APIs.  Originally, only one application at a time could play audio, that was because the original infrastructure didn't have support for tracking or mixing audio streams (this is also why the old audio apps like sndrec32 pop up an error indicating that another device is using the audio hardware when they encounter any error).

    When Windows 95 (and NT 3.1) came out, the MME APIs were stretched to 32 bits, but the basic infrastructure didn't change - only one application could play audio at one time.

    For Windows 98, we deployed an entirely new audio architecture, based on the Windows Driver Model, or WDM.  As a part of that architectural change, we added the ability to mix audio streams - finally you could have multiple applications rendering audio at the same time.

    There have been numerous changes to the audio stack over the years, but the core audio architecture has remained the same until Vista.

    Over the years, we've realized that there three major problem areas with the existing audio infrastructure:

    1. The amount of code that runs in the kernel (coupled with buggy device drivers) causes the audio stack to be one of the leading causes of Windows reliability problems.
    2. It's also become clear that while the audio quality in Windows is just fine for normal users, pro-audio enthusiasts are less than happy with the native audio infrastructure.  We've made a bunch of changes to the infrastructure to support pro-audio apps, but those were mostly focused around providing mechanisms for those apps to bypass the audio infrastructure.
    3. We've also come to realize that the tools for troubleshootingaudio problems aren't the greatest - it's just too hard to figure out what's going on, and the UI (much of which comes from Windows 3.1) is flat-out too old to be useful.

    Back in 2002, we decided to make a big bet on Audio for Vista and we committed to fixing all three of the problems listed above.

    The first (and biggest) change we made was to move the entire audio stack out of the kernel and into user mode.  Pre-Vista, the audio stack lived in a bunch of different kernel mode device drivers, including sysaudio.sys, kmixer.sys, wdmaud.sys, redbook.sys, etc.  In Vista and beyond, the only kernel mode drivers for audio are the actual audio drivers (and portcls.sys, the high level audio port driver).

    The second major change we made was a totally revamped UI for audio.  Sndvol32 and mmsys.cpl were completely rewritten (from scratch) to include new, higher quality visuals, and to focus on the common tasks that users actually need to do.  All the old functionality is still there, but for the most part, it's been buried deep below the UI.

    The infrastructure items I mentioned above are present in Vista Beta1, unfortunately the UI improvements won't be seen by non Microsoft people until Vista Beta2.

  • Larry Osterman's WebLog

    Windows Audio Channel9 Video is up.

    • 16 Comments

    Robert Scoble's posted the audio team Channel9 video, in it, the GPM for our group goes over what the Windows Core Audio team's been doing for the past three or so years, and lays out some of the stuff that we've got in store for Vista.

     

    I am super psyched about this, and I'll be talking about some of the changes we've made over the next several posts.

     

  • Larry Osterman's WebLog

    Converting between bases...

    • 35 Comments
    The other day there was a thread on Channel9 where "orangie" was complaining about the fact that his programming class required him to learn how to convert between different bases (base 10->2->whatever).

    In reality, it's actually quite useful to know how to do the conversions, because knowing how the computer represents values can be remarkably important, especially in a CS course.  In my case, we covered base conversions in the "intro to digital circuits" class, one of our projects was to write a circuit that would take a binary input (from a set of switches) and convert it to hex.

    It turns out that base conversion is a core part of "New Math", Tom Lehrer's "New Math" song is all about how you do arithmetic in different bases.  They're still teaching "New Math" in classes, converting between bases is covered in the 5th or 6th grade at least at Wellington (the school where Valorie used to work).  This makes sense, because it's important that students have a fundamental understanding about how numeric operations work, and what makes up a number - understanding different base systems helps to figure it out.

    Most of the time, I do my base conversions using this:

    I've had it for over 20 years now, and it's still going strong (gotta love HP's engineering).  Until I looked it up on eBay, I hadn't realized it was worth about $100, go figure.

    But, for those times that I need to convert by hand, it's actually pretty simple, especially for some very common conversions (hex to binary, and hex to octal).

    For hex to binary, all you need to do is to memorize the bit pattern for the 16 possible hex values (5 is 0101, 6 is 0110, f is 1111, etc).

    Then it's just a matter of string concatenation - you convert each digit to binary, string them together and convert back to whatever your destination base is.

    Octal to binary is similar, you just have to remember values from 0-8 (which is easy if you've memorized the hex values :)).

    My personal favorites are converting from hex to octal (and vice versa) because you don't have to do any math.  You do it by converting to a common base, binary in this case.

    So 0x123456789abcdef in hex converts to:

    0001 0010 0011 0100 0101 0110 0111 1000 1001 1010 1011 1100 1101 1110 1111

    or:

    000100100011010001010110011110001001101010111100110111101111

    Regrouping:

    000 100 100 011 010 001 010 110 011 110 001 001 101 010 111 100 110 111 101 111

    And converting from binary to octal:

    04432126361152746757

    Tada!  Hex to octal conversion without having to do ugly math :)

    Obviously this works for any power of two, it's just that octal and hex are the two most common.

    Now once you want to include converting to decimal, it's gets a bit harder - then whipping out the calculator's usually the best solution.  If you still MUST do the conversion by hand, it's often easier to do it with the octal representation than the hex representation.  In this case, it's:

        4*180124248109481984
    +  4*22515531013685248
    +  3*2814441376710656
    +  2*351805172088832
    +  1*43975646511104
    +  2*5496955813888
    +  6*68719476736
    +  3*85889934592
    +  6*1073741824
    +  1*134217728
    +  1*16777216
    +  5*2097152
    +  2*262144
    +  7*32768
    +  4*4096
    +  6*512
    +  7*64
    +  5*8
    +  7
    -------------------------------------
    81985529216486895

    Easy, right?

    Oh, and before someone asks, no, they don't expect the 5th graders to convert numbers that are that large :)

     

    Edit: Toned down the language about orangie, and added the comment about Tom Lehrer's "New Math" song, it wasn't my intention to embarass orangie.

     

  • Larry Osterman's WebLog

    Interacting with Services

    • 15 Comments
    In the comments for my first services post, someone asked about the SERVICE_INTERACTIVE_PROCESS flag that can be specified for the CreateService API.

    This flag allows the user to specify that the service should be allowed to interact with the logged on user.  The idea of an interactive service was added back in NT 3.1 for components like printer drivers that want to pop up UI.

    IMHO this was a spectacularly bad idea that should never have been added to the system.

    MSDN has an entire page on interactive services, unfortunately IMHO, it doesn't go into enough detail as to why it's a bad idea to ever specify the SERVICE_INTERACTIVE_PROCESS flag on a service.

    The primary reason for this being a bad idea is that interactive services enable a class of threats known as "Shatter" attacks (because they "shatter windows", I believe). 

    If you do a search for "shatter attack", you can see some details of how these security threats work.  Microsoft also published KB article 327618 which extends the documentation about interactive services, and Michael Howard wrote an article about interactive services for the MSDN Library.  Initially the shatter attacks went after windows components that had background window message pumps (which have long been fixed), but they've also been used to attack 3rd party services that pop up UI.

    The second reason it's a bad idea is that the SERVICE_INTERACTIVE_PROCESS flag simply doesn't work correctly.  The service UI pops up in the system session (normally session 0).  If, on the other hand, the user is running in another session, the user never sees the UI.  There are two main scenarios that have a user connecting in another session - Terminal Services, and Fast User Switching.  TS isn't that common, but in home scenarios where there are multiple people using a single computer, FUS is often enabled (we have 4 people logged in pretty much all the time on the computer in our kitchen, for example).

    The third reason that interactive services is a bad idea is that interactive services aren't guaranteed to work with Windows Vista :)  As a part of the security hardening process that went into Windows Vista, interactive users log onto sessions other than the system session - the first interactive user runs in session 1, not session 0.  This has the effect of totally cutting shatter attacks off at the knees - user apps can't interact with high privilege windows running in services. 

     

    On the other hand, sometimes it's important to interact with the logged on user.  How do you deal with this problem?  There are a couple of suggestions as to how to resolve the issue.  The first is to use the CreateProcessAsUser API to create a process on the users desktop.  Since the new process is running in the context of the user, privilege elevation attacks don't apply.  Another variant of this solution is to use an existing systray process to communicate with the service.

    In addition, if a COM object is marked as running in the security context of the interactive user, it will be activated in the interactive user's session.  You can use a session moniker to start a COM object in a particular session.  There's an example of how to do this here.

     

  • Larry Osterman's WebLog

    I'm NOT at the PDC this year :)

    • 5 Comments

    It seems that every single Microsoft blogger's at the PDC today, but unfortunately, I'm not :(

    On the other hand, Robert Scoble's going to be posting a video he did of the Windows Core Audio team sometime in the next couple of days where we finally get to talk and show off some of the really cool things we've done for Vista.

    I'll update this post when the video goes live.

     

  • Larry Osterman's WebLog

    Breaking Up (shared services) Is(n't) Hard To Do

    • 19 Comments
    The last time I wrote, I talked about shared services. One of the problems of working with shared services is that sometimes one service in the process gets in the way of other services.

    For the audio service, it lives in the "networking services" service host (because the networking services svchost is used for all services that run as LocalSystem).  But, because it runs in the same process as the networking functionality, it means that it can be quite difficult to debug the audio service, especially if you're using a source level debugger - if your debugger has to talk to the network, and portions of the networking stack are suspended (by the debugger) it can be hard to make things work...

    It turns out that there's a remarkably clever trick that can be used to split a normally shared service into its own process. 

    From a Windows command prompt, simply type:

    C:\>sc config <servicename> type= own

    To move the service back into its normal shared config, type:

    C:\>sc config <servicename> type= share

    The SC tool should be in the system32 directory on all XP installations, if not, it's in the platform SDK (I believe), and obviously you need to be an administrator to make this work.

    I can't take credit for this, it was shown to me by one of the NT perf guys, but I like it sufficiently that it's worth sharing.

     

    One more caveat: Before people start trying this on their XP system, please note that there's a reason that those services are in the same process.  Splitting them up will cause your system to use a LOT more memory, and WILL make your system unstable.  I'm posting this trick because it can be quite useful for people who are developing their own shared services.

    Several of the built-in services assume that they're in the same address space as other services, and if they start running in separate processes, they will crash in strange and mysterious ways, if you're not careful, you can render your machine unbootable.

    Just don't go there, it wouldn't be prudent.

  • Larry Osterman's WebLog

    Shared Services

    • 13 Comments
    One of the comments I made when doing my "first impressions" of the Mirra backup device was that the Windows software starts two separate services running in two different processes.

    I see this a lot - people architect their product into multiple services (which is often a good thing), but they then run the services in separate processes.

    Sometimes this is a good thing - for example, the Windows Media Connect add-on for Windows runs as two services - one service does very little, but runs as LocalSystem (full privileges).  The other service (which does most of the work) runs in a limited LocalService account.  By running as two services, in two different privilege levels, the Windows Media Connect carefully limits which functionality has to run with elevated privileges.  This is a good example of the principle of least privilege - isolate the parts of the functionality that need higher privileges and run them out-of-proc instead of running the entire service with elevated privileges.

    But sometimes it doesn't really make sense.  Mirra is a good example, and there are others as well.  These products have multiple Windows Services, which run in the same security context, but use separate processes.

    Why is this a big deal?  Well, unlike *nix, on Windows, a process is a relatively expensive entity.  It takes a non trivial amount of time to launch a process, and each process consumes a fair amount of system resources (something like 1M of virtual memory, just for the various process structures (virtual address map, handle table, etc), IIRC).  Each process running drains the system of resources that could be used for your application, so it's important to reduce the number of system processes running.  It always annoys me when I install some application and discover that it's installed three or four processes that run all the time on my machine, especially when those functions could have been combined into a single process.

    For services, this is especially annoying - the NT service controller has had support for shared services built-in since NT 3.1.

    You can see shared services in action on any Windows machine.  If you have the SDK tool tlist.exe, you can run "tlist -s" and see the services running in each process.  On my machine, tlist shows (among other things):

    1280 svchost.exe Svcs: AudioSrv,BITS,CryptSvc,Dhcp,dmserver,ERSvc,EventSystem,helpsvc,lanmanserver,lanmanworkstatio
    n,Netman,Nla,RasMan,Schedule,seclogon,SENS,SharedAccess,ShellHWDetection,srservice,TapiSrv,Themes,W32Time,winmgmt,wuause
    rv,WZCSVC

    In this example, svchost.exe is running 26 different services.  Without shared services, each of these would be a separate process, thus consuming a huge chunk of resources.  In fact, that's the entire purpose of svchost - it provides a common hosting framework for Windows to use for shared services.  svchost.exe is an internal-only facility, but the functionality on which it is based is available for everyone.  To specify a service as being a shared service, all you need to do is to specify the dwServiceType as SERVICE_WIN32_SHARE_PROCESS when you call CreateService and the service controller will do "the right thing".

    You need to do a smidge more work - if you're a shared service, then when you call StartServiceCtrlDispatcher, you need to specify all the services that will be running in your process, but that's about it. 

    When you ask the service controller to start a share process service, the service controller first looks to see if that service is started.  If it's not, it looks at the running service control dispatchers to see if there's a dispatcher running for the new service.  If there is a dispatcher running for the service, then it uses that dispatcher to start the new service, if there isn't, it launches the process that was specified in the lpBinaryPathName parameter to CreateService.

    The bottom line is that if you're responsible for more than one service (or your product contains more than one service), you should seriously consider combining them into a single process - it's not that much extra effort, and the benefits can be huge.

  • Larry Osterman's WebLog

    APIs you never heard of - the Timer APIs

    • 24 Comments

    It's time for another "APIs you never heard of" article :)

    This time, I'd like to talk about the time* APIs.

    The time* APIs are a set of 7 APIs built into the windows multimedia extensions (winmm.dll).  They provide a rudimentary set of timer functions for Windows applications.  At this point, except for two of the APIs, they exist only for historical purposes, the core OS now provides significantly higher quality APIs for timers.

    The time APIs fall into three rough categories:

    1. Timer information (timeGetDevCaps, timeGetTime and timeGetSystemTime)
    2. Timer callback functions (timeSetEvent and timeKillEvent)
    3. Timer frequency functions (timeBeginPeriod and timeEndPeriod)

    The first two categories are obsolete (arguably timeGetDevCaps still has valid uses).  The timeGetTime API is effectively identical to the GetTickCount() API, and timeGetSystemTime simply returns the exact same value that timeGetTime would have returned, packed into a MMTIME structure. 

    The timeSetEvent and timeKillEvent have been replaced with the Win32 Timer Queue functions, I'm not sure if I know of any reason to ever call the MME versions of these functions :).  In fact, timeSetEvent will call PulseEvent API, which is fundamentally flawed.  There is one difference between timeSetEvent and the Win32 timer queue functions - timeSetEvent will call timeBeginPeriod to set the timer resolution to the resolution specified in the call to timeSetEvent.  Even with this, you're better off calling timeBeginPeriod and using the Win32 Timer Queue functions (because the Win32 timer queue functions are far more flexible). 

    But then there's the timeBeginPeriod and timeEndPeriod APIs.  These are actually fun APIs, especially in the multimedia or gaming space, because they allow you to change the resolution of the internal scheduler, which can lower (or raise) the resolution with which the internal clock runs.

    This has a number of side effects - it increases the responsiveness of the system to periodic events (when event timeouts occur at a higher resolution, they expire closer to their intended time).  But that increased responsiveness comes at a cost - since the system scheduler is running more often, the system spends more time scheduling tasks, context switching, etc.  This can ultimately reduce overall system performance, since every clock cycle the system is processing "system stuff" is a clock cycle that isn't being spent running your application.  For some multimedia applications (video, for example) the increased system responsiveness is worth the system overhead (for instance, if you're interested in very low latency audio or video, you need the system timers to run at a high frequency).

    Edit: Added comment about timeSetEvent calling timeBeginPeriod to set the resolution.\

    Edit2 (years later): Updated the link to GetTickCount...

  • Larry Osterman's WebLog

    Mirra, first impressions

    • 18 Comments

    We've currently got something like 7 computers currently in use in my house these days, and I've been looking for a centralized backup solution for the home for a while.

    Eventually, I settled on a Mirra - a small form-factor appliance-like backup server.  It comes in four sizes, 80GB, 160GB, 250GB, and 400GB.  I ordered the 400GB based on the amount of stuff we've got saved on the various machines that will have to be backed up.

    I've not yet had a chance to use all the features of the product (in particular, I've not used the remote access functionality), but I  did set it up and get it running on two of the machines over the weekend.

    I have to say that I'm impressed.  IMHO, these guys have been taking lessons from Apple in terms of out-of-box experience (Personally, I think that Apple does OOBE better than any other PC hardware company).

    You open the Mirra box, and you see a cardboard inset, with a folded card-stock flyer and the power cord and an ethernet cord.

    On the cover of the flyer, are the words "Welcome to Mirra".  You open it up, and it unfolds into a four page story telling you that you're about to enter into a new world where you don't have to worry about your data.  On the back of each of the four pages is one of the four steps to setting up the Mirra - the first tab has you plugging in the appliance (you need to plug it into AC and into an ethernet port), the second tab has you installing the software on your PC, the third has you configuring the PC, the fourth is "Relax".

    I LOVED this experience - it's exactly the balance that computer-related appliance should strike - simple instructions, clearly spelled out, easy for Abby to get right.  The actual Mirra device is a small form-factor PC, I didn't crack the case to see what was running inside it, but it's got video, keyboard, mouse, and USB ports on the case (the video and USB are covered over with plastic).  The small form-factor PC is perfect for "plug it in and forget about it".

    I had some difficulties getting the software installed on the first machine I tried, it didn't recognize the firewall I was running (Microsoft One-Care Beta1), and I had to manually configure it.  On the other hand, the manufacturers web site was extremely helpful getting past this hurdle, and once set up, it immediately started copying files.

    I next went to each of the four accounts on that machine and set the software up on each of them.  It worked seamlessly for all four accounts, including all the limited user accounts.  This alone impressed the heck out of me - there aren't that many software products out there that consider the FUS (fast user switching) and LUA scenarios, but clearly the Mirra guys had.

    I then went upstairs to my computer, and installed it.  This machine doesn't have One-Care installed on it, and the Mirra detected the XP SP2 firewall and opened the relevant ports in the firewall (the firewall is enabled and I didn't need to do anything about it).  The machine then started hammering our home network copying off all the files on the machine.

    I still need to get it installed on the kids computers, that'll be interesting since the kids computers don't have access to the internet.

    The Mirra backup software runs as two services, running in two processes (I'm not sure why, since both services run at localsystem).  However, once configured, the Mirra backup software will run without requiring any process in the user's session.  If I was doing it, I'd have used just one process to run both services, but...

    As I commented to Valorie "This is the software I would have designed".  I was utterly impressed that they seem to have nailed several critical scenarios that are usually overlooked.

    One negative (not relevant to me, but probably to others) is that this is a Windows-only product - they don't seem to have Mac or Linux clients.

    In general, though, I'm pretty impressed.

     

  • Larry Osterman's WebLog

    Administrivia

    • 6 Comments

    When we switched to community server, back in April, I decided to stop moderating my posts, since the comment spam had reduced.

    Well, over the past couple of weeks, I've seen a number of comment-spam attempts, which means that I'm likely to be a target again.

    As a result, I've enabled moderation on all anonymous posts - if you're logged in, you won't be moderated, but if you aren't, your posts will take some time to show up.

    Edit: Manip brings up a good point: To log in, go to http://blogs.msdn.com and click on the "Log In" link on the top left.  You can also click on the "Join" link if you don't have an account yet.

     

Page 1 of 1 (16 items)