• The Old New Thing

    Why doesn't the mail image resizer check the image size before offering to resize?

    • 70 Comments

    Commenter Igor lambastes the image resizer dialog that appears when you select Send To Mail Recipient. (And people think I'm the one with the social skills of a thermonuclear device.) This dialog pisses him off so much, he complained about it again.

    The root of the diatribe appears to be that the image resizer dialog appears, even if it turns out the resizer won't do anything. For example, the resizer dialog appears even if the images are already small, or if the files have a .jpg extension but aren't actually JPG images, Why is it so idiotic that it fails to check these simple things before offering to do its work?

    Because checking these simple things before showing the dialog is even more idiotic.

    One of the grave errors when doing work with files is accessing the file before the user asks for it. This is a grave error because accessing the file can take an excruciatingly long time if the file is stored on a server halfway across the world over a slow network connection, or if the file has been archived to tape.

    This particular code path is sensitive to the file access time because the user has just picked a menu item. Suppose the dialog box went ahead and opened the files to confirm that, yes, they really are images, and yes, the dimensions of the image are larger than what the dialog offers to resize them to. You select 1000 small images on a slow server, right-click them, and pick Send To... Mail Recipient.

    Then you wait 30 minutes while the dialog box goes off and does something like this:

    shouldOfferResize = false;
    foreach (file in selection)
    {
      if (file.IsJPGThatIsNotCorrupted() &&
          file.IsWorthResizing()) {
        shouldOfferResize = true;
        break; // can early-out the loop once we find something
      }
    }
    

    Opening each file, parsing it to verify that it is a valid JPG file that decodes without error, and extracting its dimensions takes, say, 2 seconds per file. (The file is slow to access, say, it's on a network server or on a slow medium like a CD-ROM or a tape drive. Or the file is large and it takes 2 seconds to read it off the disk and parse it to verify that there are no decoding errors.)

    After about 15 seconds with no response, you give up and say "I hate computers." and go off and do something else, frustrated that you were unable to email your photos.

    And then in the middle of working in your word processor, this dialog box suddenly appears: "Windows can resize the pictures you send in e-mail so that they transfer faster and are easier to view by the recipient."

    Gee thanks, Windows, for finally getting around to asking me about that thing I wanted to do a half hour ago.

    Idiot.

    And then when you click No, Windows has to go and decode the files a second time in order to print them. (Unless Igor's recommendation is to cache the decoded bits from the first pass. Then you'd complain that selecting 1000 files and clicking "Send To... Mail Recipient" causes your computer to run out of memory. As Igor is fond of saying when insulting the Windows team: "Looks like this feature was designed without any adult supervision.")

    Sidebar: A good fraction of these blog entries are just elaborations on very simple concepts. When I toss an entry onto the "I should blog this" pile, it usually gets a short remark of five to ten words which captures what I want to say. Then when it floats to the head of the queue, I expand those ten words into a 300-word entry. The short version of today's entry: "That would hit the disk."

  • The Old New Thing

    The mystery of the other girlfriend

    • 32 Comments

    Many of my married friends have "other girlfriends", or at least that's how their wives tease them.

    I don't know for certain, but if you ask my wife, she'll probably say that my "other girlfriend" is this Web site.

  • The Old New Thing

    When you commit memory, you get a commitment to receive memory when you need it, but no sooner

    • 44 Comments

    When you allocate memory, say by creating a shared memory section or by calling VirtualAlloc with the MEM_COMMIT flag, what you have is known to the memory manager as a commit. The memory manager has promised that if you try to access that memory, the memory access will succeed. But that doesn't mean that the memory manager knows exactly which memory chip on your motherboard it's going to use. (Yes, I know that the memory is actually spread out over multiple memory chips, but I'm talking metaphorically. If you want to get all nitpicky, I'll call them physical page frames since that's what they are.)

    This is actually obvious if you think about it. After all, if the memory gets paged out, and then paged back in, it might get assigned to a different physical page frame when it comes back. Therefore, the memory manager cannot promise "Okay, if you try to access memory at address 0x00900000, I will map that to physical page frame 0x471."

    But what if I turn off paging by disabling my page file?

    Sure, that takes the "page it out and back in" scenario out of the picture, but the memory manager still doesn't decide which page frame to assign to your virtual linear address until you actually access it.

    Think of a memory commitment as obtaining a contract with a cleaning service to clean your room. You hire them to clean your room a week from Saturday. At the time you sign the contract, the cleaning service will typically not decide which member of its cleaning staff will come to your room. It just remembers that it has committed to cleaning your room, and it ensures that there will be somebody available to do it. For example, if they have a staff of ten people, and it takes a day to clean a room (hey, it's a messy dorm room), then they won't book more than ten jobs per day.

    Why don't they pre-assign the jobs? Well, different members of the staff may have different skills, and not all jobs may require all the skills of a particular staff member. For example, suppose the staff consists of two people, Alice and Bob. Alice is good at carpets and Bob is good at blinds. Your dorm room has neither. If the cleaning service decided to assign your job to Alice at the time you signed the contract, then it is taking the risk that it may receive another offer for a carpet job and it would have to turn it down because Alice is already assigned to your room. On the other hand, if it assigned Bob, then it's taking the risk that an offer would come in for a job that included blinds. The best thing for the cleaning service to do is not to assign anybody yet, but still remember that it needs to assign somebody by Saturday morning, so it knows it can accept one more job, but not two. (And it can't accept any jobs which involve both carpets and blinds.)

    The memory manager does the same thing. It knows that it needs to assign some page frame to your process, but it doesn't make any decision until you actually use the memory, so it can have maximum flexibility to satisfy other memory allocations in the meantime. And if you free the memory without ever accessing it, then the memory manager didn't need to make the decision at all!

    For example, a device driver might request some memory with a particular characteristic; for example, it might ask for memory below the 4GB boundary (because it's communicating with a hardware device that doesn't support addresses above 4GB), or it might ask for 64KB of physically contiguous memory. If the memory manager had decided ahead of time to assign physical page frame 0x471 to your process, it might have to turn down one of those other requests because your page frame was the only one available that fit the bill.

    As one of my colleagues explained, "Commit is the system's guarantee you will get a page when you need it. In giving you this guarantee, it does not have to give you the page yet." Commit is merely a promise that when you need the page, it will be there.

    The fire department promises that if there's a fire in your house, they will come to try to put it out. But that doesn't mean that there's a tank of water at the fire station with your name on it.

  • The Old New Thing

    A Few Seconds of Panic: Life as an NFL kicker

    • 5 Comments

    Although I don't follow him regularly when he appears on All Things Considered and didn't when he wrote for The Wall Street Journal, I'm a quiet fan of Stefan Fatsis's books because he writes about joining a world most of us don't get to see. I previously wrote about his excursion into the world of competitive Scrabble. Today, it's his book A Few Seconds of Panic, or more formally, A Few Seconds of Panic: A 5-Foot-8, 170-Pound, 43-Year-Old Sportswriter Plays in the NFL, another example of the Catchy title: Long boring subtitle book title fad. [Update: Now available in paperback.] Fatsis convinces a professional football team to let him join them for a pre-season game as a place kicker. From there, he observes the working of an NFL team from the inside. NPR's Only a Game interviewed him in August 2008. [mp3]

    (Fatsis is a regular member of Slate's new weekly sports podcast Hang Up and Listen. He mentions his kicking career only every other podcast now.)

    (And I wasted far too much time on what is rumored to be another Stefan Fatsis production, Name of the Year. Here's a list of previous winners.)

  • The Old New Thing

    In the search for the subtle source of the problem, you sometimes overlook the obvious one

    • 36 Comments

    A customer was encountering a problem with lots of duplicate GUIDs. How is that possible? The whole point of the GUID generation algorithm is to work hard to avoid duplication. Was one of the fundamental assumptions of the algorithm broken? Maybe there was a duplicate MAC? Was the clock regressing?

    One of my colleagues pointed out that in the search for the subtle source of the problem, you sometimes overlook the obvious one. In fact, this is the most common source of problems with so-called duplicate GUIDs. As he so tersely puts it: "A GUID can easily be duplicated by simply copying it."

    In other words, you have a duplicate GUID because you duplicated the GUID. This can happen, for example, if you have a Clone method on an object which creates an exact duplicate of the object. Since the GUID is a property of the object, it too gets cloned. Then you add the clone to the same database as the original.

    Boom, instant duplicate.

  • The Old New Thing

    2009 Q3 link clearance: Microsoft blogger edition

    • 7 Comments

    It's that time again: Sending some link love to my colleagues.

  • The Old New Thing

    Why do messages posted by PostThreadMessage disappear?

    • 8 Comments

    The only thread message you can meaningfully post to a thread displaying UI is WM_NULL, and even then, it's only because you want to wake up the message loop for some reason.

    A common problem I see is people who use PostThreadMessage to talk to a thread that is displaying UI and then wonder why the message never arrives.

    Oh, the message arrived all right. It arrived and then was thrown away.

    This is actually a repeat of an earlier entry with the title Thread messages are eaten by modal loops, but I'm repeating it with a better subject line to help search engines.

    But since I'm here, I may as well augment the existing article.

    Obvious places where you have modal loops on a UI thread are functions that are explicitly modal like DialogBox or MessageBox or TrackPopupMenuEx(TPM_RETURNCMD) or DoDragDrop. But there are less obvious modal loops, like the modal loop that runs when you click on the caption bar and hold the button or the modal loop that runs when COM is waiting for a cross-thread call to complete.

    And since you don't control those modal loops, when they call DispatchMessage, your thread message will simply be thrown away.

    If you need to communicate reliably with a thread that also displays UI, then create a hidden window and send or post messages to that window.

  • The Old New Thing

    Microspeak: Net net

    • 24 Comments

    In finance, the net is the total after you have cancelled positive values against negative values. For example, if you took in $30 and paid out $20, then your net is $10.

    In Microspeak, this term has moved into project planning and has undergone redoubling, so it's not just net; it's net net. The doubling of the word was probably added to create a sense of impatience. Here's an imaginary conversation that illustrates the term:

    Speaker 1: We're five days over on component X, but component Y is ahead of schedule, and we can have some of them h...

    Speaker 2: (interrupting) What's the net net?

    Speaker 1: Um, we're two days behind.

    The net net is not a real estate transaction but rather is a short summary of a complicated situation, what often goes by the term bottom line.

    Here is an actual citation:

    (At the top of a long email message)

    Net net, we're delaying the release we had planned for tomorrow to try and get some critical fixes in.

    Another use of the term net net is to highlight a conclusion from a lot of data.

    (at the bottom of a large information-dense PowerPoint slide)

    Net Net: Eliminate XYZ from our target set.

    Both senses of net net highlight the principle of I know you're impatient, so I'll cut to the chase.

  • The Old New Thing

    Why doesn't Explorer have an interface for creating hard links?

    • 119 Comments

    Nick asks why Explorer doesn't have UI for creating hard links.

    Heck, while you're at it, why not ask "Why doesn't Explorer have a UI for hex-editing a file?"

    Remember, all features start out with minus 100 points. Explorer is not under any obligation to expose every last NTFS feature, and it's certainly not going to help to expose an NTFS feature that even technical people don't understand. Just look at all the people who ask questions like "How can I tell if a file name is a hard link instead of a normal file?" or online explanations of hard links which claim that "A hard link is only a reference to the original file, not a copy of the file. If the original file is deleted, the information will be lost." I mean, if even a techno-geek doesn't understand hard links, how is your average user supposed to have a chance?

    First, let's see how you would explain a hard link to an end user.

    When you create a hard link, you give the item an additional name. The file can be accessed by either its old name or its new name; they are equivalent. A file is not deleted until all its names are deleted.

    If you open a file by one name, make changes, and then save the file, the update is made to the file, and accessing the file by a second name will show the updated file, because the data for a file is separate from its name.

    Actually, that paragraph above is only true if the application which saves the file does so by writing directly to the name you used when you opened the file. If the application updates the file by creating a temporary file, then renaming the original to a backup name and renaming the temporary file, then updating a file by one name will sever its connection with other names for the file. The other names will continue to refer to the unmodified file; the name you used for the update will refer to the updated file. Different applications handle this situation differently; consult your application documentation for information on how it treats hard links.

    Note also that some backup programs have difficulty with hard links. Consult the documentation for your backup program for information on how it behaves when faced with hard links.

    If a file has multiple names, editing the file by using different names simultaneously may result in data corruption.

    If a file has multiple names, all the names must exist on the same drive.

    Most users clicked Cancel at about the time you said, "When you create a hard link..." You'll probably lose the rest of them while you are busy warning about the potential problems with hard links, and the brave few who managed to stick it out to the end will be completely confused and hit Cancel. (The ones who hit Cancel early on were the smart ones.)

    The problem with backup programs is particularly nasty. A backup program that is not hard-link-aware will miscalculate the necessary size of the backup volume, and when it attempts to restore the files, it will not restore the hard links.

    There was a Windows XP PowerToy for creating hard links, but the backup team recommended that it not be released because so many third party backup programs exploded when they stumbled across files that had multiple names in the file system.

  • The Old New Thing

    The ways people mess up IUnknown::QueryInterface, episode 2

    • 35 Comments

    Sadly, I get to add another entry to The ways people mess up IUnknown::QueryInterface:

    Blindly responding to everything.

    Some people are just too eager to please.

    HRESULT CSomething::QueryInterface(REFIID riid, void **ppvObj)
    {
      *ppvObj = this;
      this->AddRef();
      return S_OK;
    }
    

    No matter what the interface is, they say, "Sure, we do that!"

    Furthermore, no matter what you ask for, they always return the same interface. Even if it's not what you asked for.

    Exercise: Some people say that "these problems wouldn't be there if Microsoft Windows had enforced correct behavior to begin with." My exercise to you, commenter "foo", is to come up with a list of all bugs in IUnknown::QueryInterface which Windows should enforce and describe how to enforce it. (If your response is "You should have designed it differently so these bugs are impossible to write", please outline that alternate bug-resistant design. Remember that your design must be language-independent, while still supporting things like tear-offs, aggregation, and remote objects. Oh and it needs to work on typical PC-class computers of the early 1990's, which ran at 25MHz with 4MB of memory.)

Page 123 of 388 (3,874 items) «121122123124125»