Author Archives: kenny

Volunteer Park Café (Seattle, WA)

Rating:

Just over a year ago, a new restaurant/coffee-shop opened on the north side of Capitol Hill, in the location of the former Café Europa. It wasn’t until early summer that I made my first stop at Volunteer Park Café. It was to be the first of many tasty visits.

Fast forward to October 10th. Lauren and I attempted to have dinner at Lark, but were greeted with an hour wait.  So we decided to check out how VPC handles dinner.  I still remember the Fig and Gorgonzola Pizza we had that night. We returned last night and the waits were running over an hour. Fortunately we had called ahead for a table, as it seems reservations are a must over the weekend (the weeknights we’ve been there have been much more sedate). VPC rotates their menu weekly, though it always includes a daily bruschetta that is worth checking out. Last night’s variation was a garlic spread with butternut squash, red peppers, kale and a little pecorino cheese. On top of freshly grilled bread of course. A hearty and tasty beginning!

vpcGarlicBruschetta

Next was a mixed beet salad (with all local vegetables), with chevre, arugula, and a light vinaigrette. The chevre was fantastic, and a little bit of salt in the dressing brought together all the flavors perfectly.

vpcBeetSalad

Another regular appearance on VPC’s dinner menu is their selection of pizzas. We’d already had the "Roasted Mushroom" (with truffle oil) and the "Bianco", both of which were fantastic (though not quite as good as the heavenly Fig and Gorgonzola). Last night we branched out and tried the Spinach Pesto, with oven roasted tomatoes, red onion, feta, and oregano. The pizza was decent, but not in the same league as the rest of the pizzas I’ve had there. Maybe it was the pesto base, maybe it was the thickness of the crust, or maybe it was the greater number of toppings or the higher than usual ratio of bread to toppings. Whatever the reason, I’d pass on the Spinach Pesto pizza in the future, especially given the solid alternatives.

On weekends Volunteer Park Café offers both breakfast and lunch options well into the afternoon, and in the summer they have (slightly rickety) tables flanking the sidewalk in front of the café.  For those with a sweet tooth, definitely try the Caramelized Banana Brioche French Toast. It’s heavenly.  Other breakfast highlights include the Brie and Apple Panini (on croissant, not baguette) and the quiche of the day.  A running theme is that the pastries are sinful, but oh so flaky and buttery.  Orders take a long time to complete, so make sure you’re not ravenously hungry when you arrive (or if so, grab yourself a scone or croissant while you wait).

For lunch, the Herb Roasted Mushroom Panini is my current favorite.

vpcMushroomSandwichKW

Though I also frequently order the Chicken Salad Sandwich.

vpcChickenSaladSandwich 

Overall, Volunteer Park Café is a relaxed, enjoyable, friendly place that consistently turns out great food for all meals. Add a reasonably priced wine list (which seems to be rarer and rarer these days) and super-friendly staff and it’s no surprise that the lines can be out the door!

Volunteer Park Café
1501 17th Ave E
Seattle, Washington 98112
206-328-3155

Tues-Fri 7:00AM-4:30PM (Breakfast, Lunch)
Sat-Sun 8:00AM-4:30PM (Breakfast, Lunch)
Tues-Sat 5:30PM-9:00PM (Dinner)

Notes on lifetimes of Channels and their Factories

One question I get from custom channel authors has to do with the various lifetimes of the components involved. Especially since, as per best practice, their heavyweight resources are attached to ChannelFactories and ChannelListeners and simply referenced from the Channel. Nicholas covered the basics in this post. Which to summarize is:

  • ChannelFactory created Channels cannot outlive their creator
  • channelFactory.Close/Abort will Close/Abort all Channels created by that factory
  • ChannelListener created Channels can outlive their creator
    • channelListener.Close/Abort simply disables the ability to accept new channels; existing channels can continue to be serviced

    Which makes life on the ChannelFactory end pretty straightforward.  On the ChannelListener side, there are a few subtleties. 

    First, a Channel is owned by the listener from the time of creation until the successful completion of channel.Open.  So if you are writing a custom listener that has offered up channels, you should clean them up if and only if they haven’t been opened.

    Second, in order to perform eager disposal, you will need to track active ownership of your heavyweight resources. If there are opened channels, then you need to make sure that the shared resources that they leverage have their ownership transferred from the listener to your active channel(s). This can be accomplished through ref-counting, active transfers, or other mechanisms.

    Butternut Risotto

    In our quest to go through the myriad of squash that we’ve gotten from Pioneer Organics, tonight’s experiment was butternut squash risotto (base risotto with shitakes, cream, and butternut squash). And we doubled down on new recipes; tonight we also tried the George’s Bank scallops (frozen) from Trader Joe’s.

    Verdict: The risotto was fantastic. The scallops had a good texture but tasted a tad fishy. They did look nice though 🙂

    KLscallopRisotto

    Pumping in a Layered IInputChannel

    When writing a layered channel, sometime you want to decouple processing without changing the channel shape. One example would be for layered demux purposes. When layering your IInputChannel on top of a "lower" IInputChannel, you have a few options for lifetime management and pumping that are worth noting:

    1. When your innerInputChannel.Receive call returns "null", that means that no more messages will arrive on that particular channel. You should Close that channel and then Accept a new one.
    2. If the innerListener.AcceptChannel call returns null then your inner listener is completely done providing messages and you need to follow suit when you are through with any added messages that you may have buffered.
    3. If someone calls Close/Abort on your IInputChannel, you have the option of holding onto the inner channel within your listener (and providing a new facade on top when a new channel is accepted). Alternatively, you can close the inner channel and create a new one with your new channel. That choice is entirely at your discretion (and at the mercy of your perf tuning results :))

    The Taste of SAM

    This weekend Lauren and I flexed our underutilized membership and had a cultural Sunday afternoon at SAM. They have a fantastic exhibit on Roman art from the Louvre that opened this weekend.  I was surprised at how extensive the exhibit was (large enough that I’ll have to return for a second go around before it’s through on April 6th).  They also have three panels on temporary loan from Ghiberti’s Gates of Paradise. All ten panels have been under years of restoration, and they are on a final run before returning to a hermetically sealed chamber in Florence (at the Musee dell’Opera del Duomo).

    We also stopped at TASTE (the new restaurant at SAM) for lunch. TASTE is all about local organic ingredients, with a bunch of soup, sandwich, and salad options at lunchtime. I thoroughly enjoyed my tomato soup w/grilled cheese. I also snuck a taste of Lauren’s squash soup, which was delicious. I plan to return for dinner and we’ll be sure to bring our camera 🙂

    TcpTransport's Buffer Management in WCF

    I’ve gotten some questions recently about how our net.tcp transport functions at the memory allocation level. While at its core this is simply an “implementation detail”, this information can be very useful for tuning high performance routers and servers depending on your network topology. 

    When writing a service on top of net.tcp, there are a few layers where buffer allocations and copies can occur:

    • Buffers passed into socket.Receive()
    • Buffers created by the Message class (to support Message copying, etc)
    • Buffers created by the Serialization stack (to convert from Message to/from parameters)

    In addition, this behavior differs based on your TransferMode (Buffered or Streamed). In general you’ll find that Buffered mode will provide you the highest performance for “small messages” (i.e. < 4MB or so), while Streamed will provide better performance for larger messages (i.e. > 4MB). Usually this switch is combined with a tweak of your MaxBufferPoolSize in order to avoid memory thrashing.

    TransferMode.Buffered

    In Buffered mode, the transport will reuse a fixed-size buffer on its calls to socket.Receive(). The ConnectionBufferSize setting on TcpTransportBindingElement controls the size of this buffer.

    The data read from the wire is incrementally parsed at the .Net Message Framing level, and is copied into a new buffer (allocated by the BufferManager) that is sized to the length of the message. This step always involves a buffer copy, but rarely involves a new allocation for small messages (since BufferManager will cache and recycle previously used buffers).

    The message-sized buffer is then passed to the MessageEncoder for Message construction. Again, minimal allocations should occur here since we will pool XmlReader/Writer instances where possible. At this point you have a Message that is backed by a fixed-size buffer and we will share that backing buffer for all copies of the Message created through message.CreateBufferedCopy().

    If your contract is Message/Message, then no more deserialization will occur. If you are using Stream parameters, then the allocations are determined by your code (since you are creating byte[]s to pass to stream.Read), and given the nature of the Stream APIs you will entail a buffer copy as well (since we have to fill the caller buffer with data stored in the callee).

    If your contract uses CLR object parameters, then the Serializer will process the Message and generate CLR objects as per your Data Contracts. This step often entails a number of allocations (as you would expect since you are generating a completely new set of constructs).

    TransferMode.Streamed

    There are three main differences that occur when you are using TransferMode.Streamed:

    1. The transport will use new variable-sized byte[]s in its calls to socket.Receive. These byte[]s are still allocated from the configured BufferManager. The transport will then offer up a scatter/gather-based stream to the MessageEncoder so there are no extra buffer allocations or copies in this case.
    2. The Message created from the Encoder will be a “Streamed” message. This means that if you simply Read() from the Message’s Body in a single-shot then we don’t allocate any extra memory. However, if you call message.CreateBufferedCopy() we will entail some large allocations since we need to fully buffer at that point. Note that some binding elements (such as ReliableSession and certain Security configurations) will call CreateBufferedCopy() under the hood and trigger this situation.
    3. Since the backing data may not all be in memory, invoking the Serializer will incur a larger cost since it will be pulling all the data into memory at once (in order to generate the appropriate CLR objects, even if that is simply a byte[]).

     

    As you can see, there is a tension between performance and usability. Hopefully this data will help you make the appropriate tradeoffs.

    Meatless Riblets

    A few years ago, I stocked up on vegetarian friendly foods as a hospitality nod to a few good friends. One of the items I picked up was Gardenburger’s “Meatless Riblets“. What can I say, I was intrigued. Lauren opened the freezer, took one look at them and said “no vegetarian is ever going to eat these, they are too meat-like.” Over time the riblets got buried in the freezer, to be rediscovered about 2 years later (in December). When I found them I wondered aloud how they would taste. Lauren continued her skepticism and claimed that there was no way she would ever come near the meatless riblets.

    Well at long last the moment of truth arrived. Back from the gym tonight I was famished. We’re a little low on food after the recent vacation, and I spied the riblets in our freezer. I knew what my evening snack would be, and my wife could forage for an alternative if she wasn’t interested. I opened the box and inside were two vacuum sealed frozen burgundy blocks.  Opting for the grilling instructions, they went onto the grill pan (hey, it gets cold out here in January) for the requisite 4 minutes per side. To add to the evening’s humor I recited some anecdotes from the back of the box around the virtues of vegarian food, vegetarian ribs (no one ever chokes on a bone), and Gardenburger in general (which is a pretty self-effacing company).

    About 2 minutes in, Lauren started to change her tune: “uhm, those smell pretty good.” By the time they were ready, her resolve was completely broken. I managed two bites before having to offer up a taste, at which point a second fork came out of the drawer. The funny thing is they really did taste an awful lot like the BBQ ribs I had while growing up, but without the bones or extra grease! When the riblets were gone (including a full sweep of any remaining sauce), my wife joked: “who knew that meatless riblets would be the first step in converting me back to eating beef.” After years of teasing over this tiny box, I was finally redeemed.

    P.S. As a testament to how long this item had lingered in my freezer, Gardenburger has not only new packaging, but also a new name for the product: “BBQ Riblets

    Do we live in a Scrabulous world?

    My favorite Facebook app (which has been one heck of a time sink) is scrabulous. It’s great to play scrabble as a disconnected game and Facebook has the perfect environment to mix this with your friends.  However, I always wondered when Hasbro was going to take an axe to this brand-free effort. Turns out that after many months (and many, many users), Hasbro is trying to shut down Scrabulous. Hopefully they come to their senses and simply buy them out or license their brand (perhaps for a cut of the ad revenues)….