Thursday, September 3, 2026

Local LLM Research

Local LLM models racing through benchmarks toward a wall of computer code topped by a crown

Introduction

I was curious how capable a local LLM could be on the hardware I already have, so I started this project. I wanted to see what would fit on one GPU, how fast it would run, and how the models compared once I put them through the same basic tests. So I tried a bunch of them, ran the benchmark samples, and kept track of the failures too. Below are my results.

Hardware And Test Setup

  • GPU: NVIDIA RTX 6000 Ada Generation with 49,140 MiB (48 GiB) VRAM.
  • Story runs used Dynamo in dynamo:latest-vllm-local-dev with vLLM 0.25.1, one GPU, --gpu-memory-utilization 0.90, --max-model-len 32768, --max-num-batched-tokens 2048, --max-num-seqs 4, and --enforce-eager. Benchmark clients used different concurrency values, and the 70B runs used a 4K context cap and one sequence.
  • Successful models were reached through Dynamo's OpenAI-compatible POST /v1/chat/completions endpoint at the local frontend. Each model was loaded alone and stopped before the next one.
  • Story measurements are one-request eager-mode smoke tests, not tuned throughput benchmarks. Time to first token (TTFT) and tokens per second are measured at the client through Dynamo.

Working Models

The models below are ordered by measured LiveCodeBench score first, then by the broader benchmark mean. This ordering is provisional because the LiveCodeBench runs used different runtime settings and only Qwen3 0.6B has a thinking/no-thinking pair.

ModelCheckpoint and SpecsMeasured VRAM and Context CapacityBasic TestStory PerformanceQuality SignalCaveats
Qwen3-VL-30B-A3B InstructAWQ 4-bit, QuantTrio/Qwen3-VL-30B-A3B-Instruct-AWQ; 262K native context; tested text-only15.93 GiB weights; 26.39 GiB KV cache; 288,256 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench 38%; Text Arena not recordedBest measured LiveCodeBench result in the historical sample. Image input was disabled.
Qwen2.5-Coder 32B InstructOfficial AWQ 4-bit, Qwen/Qwen2.5-Coder-32B-Instruct-AWQ; 32K native context18.14 GiB weights; 23.99 GiB KV cache; 98,240 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench 35%Conventional instruct model; BF16 version did not fit.
OpenAI GPT-OSS 20BOfficial MXFP4; 131K native context13.8 GiB weights; 28.51 GiB KV cache; 1,167,515 KV tokensPartial: guesses 5 and 7 returned higher and correctTTFT 0.120 s; 768 output tokens; 24.465 s end to end; 31.55 tokens/sLocal LiveCodeBench 27%; Text Arena 1317 +/- 6Fastest measured story result; historical LiveCodeBench run had 44 transport errors.
DeepSeek-R1-Distill-Qwen-32BAWQ 4-bit, casperhansen/deepseek-r1-distill-qwen-32b-awq; 131K native context18.17 GiB weights; 23.96 GiB KV cache; 98,144 KV tokensPartial: guesses 5 and 7 reached correct final answersTTFT 0.088 s; 768 output tokens; 32.553 s end to end; 23.66 tokens/sLocal LiveCodeBench 25%; AIME24 72.6; MATH-500 94.3Lowest measured TTFT; long reasoning and 3 transport errors in the historical LiveCodeBench run.
Qwen3 32BOfficial AWQ 4-bit, Qwen/Qwen3-32B-AWQ; 32K native context, 131K with YaRN18.24 GiB weights; 23.92 GiB KV cache; 97,968 KV tokensAPI request passed with a 1,024-token allowanceNot measuredLocal LiveCodeBench 20%; Text Arena 1347 +/- 9Emits <think> content; historical result was not mode-controlled.
Qwen3-Coder 30B-A3B InstructAWQ 4-bit, stelterlab/Qwen3-Coder-30B-A3B-Instruct-AWQ; 262K native context15.69 GiB weights; 26.63 GiB KV cache; 290,832 KV tokensPassed exactly: higher, higher, correctTTFT 0.192 s; 548 output tokens; 35.821 s end to end; 15.38 tokens/sLocal LiveCodeBench 20%Best short deterministic smoke-test behavior; historical LiveCodeBench run had 41 transport errors.
Gemma 3 27B ITAWQ 4-bit, gaunernst/gemma-3-27b-it-int4-awq; 128K input and 8K output; tested text-only17.0 GiB weights; 25.18 GiB KV cache; 210,825 KV tokensPassed: higher, higher, correctTTFT 0.180 s; 588 output tokens; 62.274 s end to end; 9.47 tokens/sLocal LiveCodeBench 20%; Text Arena 1365 +/- 4Slowest tested model; one historical response was unparsed.
NVIDIA Nemotron 3 Nano 30B-A3BNVFP4; 262K model/configuration context; this run used 32K18.22 GiB weights; 23.98 GiB FP8 KV cache; 1,624,473 KV tokensPassed logically: higher, higher, correct; each included visible reasoning markupTTFT 0.207 s; 768 output tokens; 56.183 s end to end; 13.72 tokens/sLocal LiveCodeBench not collectedThe Ada GPU has no native FP4 compute; the LiveCodeBench run did not complete.
Qwen3.5-35B-A3BAWQ 4-bit, QuantTrio/Qwen3.5-35B-A3B-AWQ; 262K native context; tested text-only21.38 GiB weights; 20.8 GiB KV cache; 889,909 KV tokensAPI request reached the response only with a larger output allowanceNot measuredLocal LiveCodeBench 17%; Text Arena not recordedHistorical result; explicit no-thinking run still required.
Qwen3 0.6BOfficial BF16; 32K native context1.12 GiB weights; 40.59 GiB KV cache; 380,032 KV tokensNot ranked by model qualityNot measuredLiveCodeBench: 15% thinking; 8% no-thinkingSame prompts and seed, but different historical runtimes, concurrency, token limits, and no explicit no-thinking field in saved payloads.
DeepSeek-R1-Distill-Llama-70BAWQ 4-bit; 128K native context; test limited to 4K37.09 GiB weights; 5.34 GiB KV cache; 17,488 KV tokensAPI request returned an OpenAI JSON responseNot measuredLiveCodeBench not collectedFits only with a 4K request cap and one sequence.
Llama 3.3 70B InstructAWQ 4-bit; 128K native context; test limited to 4K37.09 GiB weights; 5.34 GiB KV cache; 17,488 KV tokensAPI request passed and returned the exact requested responseNot measuredLocal LiveCodeBench not collectedFits only with a 4K request cap and one sequence.

Benchmark Comparison Progress

These are 100-question samples run through Dynamo's OpenAI-compatible API with AIPerf 0.12.0 and temperature 0. Each model uses the largest practical per-model settings tested or supported by the local GPU and model mode, so completion limits and concurrency may differ. They are not full benchmark scores. The ranking below uses the arithmetic mean of MMLU-Pro, GSM8K, MATH-500, and a usable local LiveCodeBench percentage; it is a local comparison score, not an official composite benchmark. GPQA-Diamond is blocked by gated dataset access. The fixed runner used a persistent environment with AIPerf 0.12.0 and datasets 3.6.0 installed in separate steps. In these exports, AIPerf reports unparsed=100 for every GSM8K row even when correct answers were recorded, so that field is not used to interpret GSM8K results.

What The Benchmark Measures Mean

MMLU-Pro samples broad academic and professional knowledge questions, with harder questions and less reliance on simple recall than the original MMLU. GSM8K samples grade-school math word problems and checks whether the model reaches the correct numerical answer. MATH-500 samples challenging competition-style mathematics problems and checks the final answer. LiveCodeBench samples recent programming problems and runs extracted code against tests. GPQA-Diamond samples difficult graduate-level questions in subjects such as biology, physics, and chemistry, where answering usually requires expert reasoning. The simple mean is the arithmetic average of the available MMLU-Pro, GSM8K, and MATH-500 percentages; the rank orders models by that average and is not an official overall score.

For LiveCodeBench, unparsed means the grader could not extract a runnable code block from the response. A response may contain a correct idea or solution but still be unparsed when it fails the expected code format, is truncated, or includes extra text that prevents extraction. These are 100-question samples, not official full benchmark scores. Comparisons are limited because sampling, prompts, model settings, response lengths, parsing, software versions, and grader behavior can change results; the simple mean also weights the three included benchmarks equally and does not include LiveCodeBench or GPQA-Diamond.

Rank so farModelMMLU-ProGSM8KMATH-500LiveCodeBenchFour-benchmark meanLiveCodeBench - thinkingStatus
1Qwen3-VL-30B-A3B AWQ77%94%84%38%73.3%Not mode-controlled: 38% official; 22 unparsedHistorical result; mode not recorded; tested text-only
2Qwen3-Coder 30B-A3B AWQ73%94%81%36%71.0%36% official; 8 unparsed; 0 transport errors; 8,192-token capCorrected 100-question run; settings selected for best practical local result
3GPT-OSS 20B MXFP479%89%85%27%70.0%Not mode-controlled: 27% official; 21 unparsed; 44 transport errorsHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
4DeepSeek-R1-Distill-Qwen-32B AWQ81%89%83%25%69.5%Not mode-controlled: 25% official; 72 unparsed; 3 transport errorsHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
5Qwen3 32B AWQ81%92%84%20%69.3%Not mode-controlled: 20% official; 80 unparsedHistorical result; mode not recorded
6Qwen2.5-Coder 32B AWQ72%84%80%35%67.8%Not mode-controlled: 35% official; 2 unparsedHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
7Gemma 3 27B AWQ61%83%81%20%61.3%Not mode-controlled: 20% official; 1 unparsedHistorical result; mode not recorded; GSM8K unparsed export is not meaningful
8NVIDIA Nemotron 3 Nano 30B NVFP480%90%36%Not collected68.7%Not supported: no successful LiveCodeBench runNo successful LiveCodeBench run
-Qwen3 0.6B35%76%71%15% thinking60.7%15% official; 77 unparsed; 0 transport; 28,000-token capHistorical pair; same prompts and seed, but different runtime, concurrency, token limits, and no explicit no-thinking field in the saved payloads
-Qwen3.5-35B-A3B AWQ82%91%Invalid17%Not rankedNot mode-controlled: 17% official; 68 unparsed; 0 transport; 4,096-token capExcluded: the saved MATH-500 run processed only 6 valid responses and 94 errors

Conclusions

  1. Qwen3-Coder 30B-A3B AWQ is the most dependable tested option for the short deterministic smoke test because it follows that response format cleanly and leaves substantial KV-cache capacity. In the corrected 100-question local sample it reached 36%, with 8 unparsed responses and 0 transport errors. The result is not a published-score reproduction and is not directly comparable to the earlier 20% diagnostic run because the runtime settings and transport reliability differed.
  2. GPT-OSS 20B is the fastest measured local model at 31.55 output tokens per second, but the current raw Dynamo response needs reasoning extraction.
  3. DeepSeek-R1-Distill-Qwen-32B AWQ has the strongest published reasoning signal among the tested models, but its long reasoning content reduces its suitability for short interactive responses without response parsing.
  4. Gemma 3 27B AWQ is usable in text-only mode, but was the slowest model tested and does not reliably return bare JSON without structured-output enforcement.
  5. The documented BF16 attempts from 27B through 70B exhausted the 48 GiB GPU. Quantized checkpoints made every tested model family loadable, including both 70B AWQ models, but the 70B models only leave enough capacity for a 4K request cap and one concurrent sequence.

Sources

Friday, March 27, 2026

I Sent Apple a Working iPhone 13 Pro. They Said It Was Worth $0.

I've used Apple Trade-In twice before. Both times it went fine. This time, I lost a phone worth $360-580 on the open market and got nothing back.

In March 2026, I bought two new iPhones and decided to trade in my old ones: an iPhone 13 Pro 256GB (Graphite, estimated $240) and an iPhone 13 256GB (Blue, estimated $195). I went through the usual process -- logged out of iCloud, erased the devices, and packed them into the FedEx trade-in kits Apple sent me.

Here's the first problem: Apple sent me two identical, unmarked FedEx kits. No label saying which box was for which phone. No instructions. Just two identical padded envelopes. I put the phones in and shipped them both on March 17. Both were delivered to Apple's trade-in facility in Elk Grove, CA on March 18.

Nine days later, on March 27, I got the results:

  1. iPhone 13 Pro trade-in: serial mismatch, revised refund $195
  2. iPhone 13 trade-in: serial mismatch, revised refund $0.00

Read that again. The iPhone 13 Pro box got a $195 refund -- which is the iPhone 13's value. That means Apple received the iPhone 13 in that box, correctly identified it, and paid the right amount for it. The phones simply ended up in the wrong boxes because Apple didn't label them.

So the iPhone 13 Pro was in the other box. Apple had it. They knew what it was. And instead of paying its $240 value, they gave me $0 with these reasons:

  • Incorrect product description or serial number
  • No functioning external ports
  • Data erasure unsuccessful

They identified the iPhone 13 correctly and paid $195. But when they got the iPhone 13 Pro -- a more valuable phone -- in the other box, suddenly it had "no functioning ports" and "unsuccessful data erasure"? Both phones were working and reset the same way, shipped the same day, delivered together.


So what really happened?

Maybe Apple's system is so rigid that putting phones in the wrong unmarked box -- a mistake their own packaging caused -- gives them grounds to reject the trade-in entirely and keep your phone for free. Maybe someone along the FedEx route or at the processing facility pocketed the more valuable phone, and the box swap gave them cover.

I'm not the only one this has happened to. A user on r/iphone sent in a working iPhone, got revised to $0, accidentally hit Accept just like I did, and Apple refused to reverse it. Another on r/apple had Phobio (Apple's trade-in partner) drop their phone from $370 to $0 over a disputed "cracked lens" claim. Apple's own Community forums have multiple threads asking "why did my device get $0?" The pattern is clear: working phones go in, $0 assessments come out, and there's almost nothing you can do about it.

It doesn't matter which scenario it is. Apple had both my phones, correctly identified at least one of them, and chose to pay $0 on the other.

My mistake

When I saw the $0 assessment, I was so baffled that I accidentally tapped "Accept" instead of "Reject -- ship the phone back." That was the fatal error. If I had rejected it, they would have been forced to return whatever phone they had, and I could have verified whether it was actually mine. By accepting, I gave up that right.

I also didn't take any photos or video of the phone before shipping. No proof it was working, no proof of the serial number, no proof it went into the box. Without documentation, it's my word against theirs -- and they have the phone (or whatever phone they claim is mine).




My advice to anyone thinking about using this service:

Don't. Just use eBay.

eBay gives you seller's protection, a verifiable transaction trail, and you'll get significantly more money. Right now on eBay, a used iPhone 13 Pro 256GB sells for $360-580 depending on condition and carrier -- even a "Fair" condition unlocked unit goes for $360. A refurbished one fetches $386. A phone that doesn't even have working Face ID sold for $470. Apple offered me $240 for a fully working one, then decided it was worth $0. eBay would have paid me 50-140% more than Apple's original offer, with actual buyer/seller protections backing the transaction.


But if you must use Apple Trade-In:

1. Trade in at the store.

When I picked up the new iPhones, the Genius at the Apple Store kept pushing me to trade in right there. I said no because I'd always mailed them in before. He was right. An in-store trade-in is inspected in front of you, the value is confirmed on the spot, and there's no chain of custody to worry about.

2. If you must mail it, document everything.

Before sealing the box, record a video showing:

  • The phone powered on, home screen visible
  • Settings > General > About (serial number and IMEI on screen)
  • All ports working (plug in a charge cable)
  • The phone being placed into the FedEx kit and the envelope being sealed

Keep that video until the refund posts to your account.


3. If it goes wrong, escalate -- but know what you're in for.

I'm currently trying to dispute this through Apple Support. It is a pain in the ass and incredibly time-consuming. You call, get transferred, explain the whole story again, get told someone will follow up, and then nothing happens. I don't know if anything will come of it. That's the reality: Apple's escalation process is designed to exhaust you into giving up. Do it anyway -- file the complaint, reference the trade-in order number, request the inspection report, ask for a senior advisor, mention the FTC and your state's consumer protection office. But go in with realistic expectations. The system is not built in your favor.


The bottom line

Apple Trade-In works great until it doesn't. And when it doesn't, you have almost no recourse. The process is opaque, the evaluation is done by a third party you never interact with, the packaging isn't tamper-proof, and the dispute mechanism is designed to make you give up.


I didn't lose a $240 phone. Apple's trade-in offer was $240, but the phone is worth $360-580 on eBay. That's what I actually lost -- a phone worth two to three times what Apple claimed, for a refund of zero dollars. Don't make the same mistake. Sell on eBay, trade in at the store, or at the very least, document everything before you seal that envelope.


Wednesday, April 16, 2025

One-Day Ski Bus to Tahoe: My Experience (and How to Pick the Right One)

One-Day Ski Bus to Tahoe: My Experience

If you're itching for some powder but not keen on the white-knuckle drive to Tahoe, the one-day ski bus is a pretty genius alternative. Over the past season, I tried two ski bus services: Tahoe Ski Trips (TST) and Sports Basement. Both promise the same basic deal — early morning departure, round-trip bus ride, and a full day of skiing or boarding without the headache of traffic, chains, or parking. But as with all things in life, the devil is in the details.


The Tahoe Ski Trips (TST) Experience

Departure:San Jose Around 3:30–4:00am from San Jose
First impression: This is a big, plush, 50+ person coach. Comfortable seats, USB and AC outlets, pull-down shades, and yes, even a bathroom onboard. Snacks and drinks? Included. And good ones, too.

The hosts are cheerful and helpful — cracking jokes, giving instructions, and most importantly, asking people to keep quiet so others can sleep. The first time I went, I couldn’t sleep a wink. But over time, I got used to the rhythm and managed to get solid rest during the early hours.

The Catch: Because the TST bus picks up at multiple locations (Walnut Creek, SF), arrival time at the resort can stretch. One trip, we didn’t pull into the lot until 10am — not great if you’re hoping to make a morning lesson. If you're booking instruction, go with an afternoon slot to play it safe.

Beware the Mini-Bus: On a lower-demand day, they subbed in a 22-person mini-bus. It was a disaster. Old, loud, no shocks, and no bathroom. No charging ports. My skis got banged up badly from rattling against the metal rack. I needed a full tune-up after. If they ever tell you it’s a mini-bus day, honestly, reschedule.


The Sports Basement Ride

Departure: 5:00am from Sunnyvale
Style: Point-to-point, no stops — arrival is much more predictable. Like the TST 50+ person bus, the ride is comfortable and quiet.

The bus is solid: same big coach with USB/AC outlets, shades, and a bathroom. The big difference? No snacks or drinks, and the host is pretty hands-off. That might sound fine… until you're trapped on a bus with people loudly chatting for four straight hours. No guidance = more noise.

Parking at Sports Basement can also be a little messy, especially on busier days.


Final Thoughts

If you’re the kind of person who values structure, comfort, and hosts who lay down the rules, TST (with the big bus) is the winner — as long as you’re okay with possible later arrivals. But if timing is your #1 concern and you’re fine bringing your own snacks and headphones, Sports Basement is more efficient and streamlined.


Pros & Cons Comparison

FeatureTahoe Ski Trips (TST)Sports Basement
Departure Time3:30–4:00am5:00am
Departure LocationSan Jose (easy parking)Sunnyvale (parking can be hectic)
Arrival TimeSometimes late (due to multiple stops)Predictable (point-to-point)
Bus Quality (50+ Coach)Excellent – USB, AC, shades, bathroomExcellent – USB, AC, shades, bathroom
Mini-Bus Backup (22-person)Poor quality, avoid if possibleN/A
Snacks & DrinksYes – includedNo – bring your own
Host/GuidanceFriendly and structuredMinimal, bus can be loud
Overall ComfortGreat (on the big coach)Great (but noisier people)
BonusFriday trips availableTypically weekends only

Friday, July 5, 2024

Taking a long leave

This has been one of the toughest decisions of my life, but after spending 7 years at the same company, I've decided to leave and spend more time with my family. I'm incredibly grateful for all the amazing friends and my extended family I've met at work, and the incredible opportunities to witness and contribute to groundbreaking research and innovative products. If you asked me 7 years ago if I would do the same thing again, of course I'd say yes!

Over the past few years, I've neglected spending quality time with my family. I've always wanted to play tennis, go hiking, go skiing, travel, and just basically, trying to be a better dad and better husband. However, unexpected challenges kept arising. First, my mom was diagnosed with stage 4 cancer. Then, a fire caused by a broken attic furnace led to half of her house's roof collapsing. Managing the reconstruction for a year while being her caretaker was incredibly tough. I witnessed her brave fight against the disease, only for her to succumb to multiple organ failures suddenly. Not long after, I had a ski accident that required surgery.

During my recovery, I had time to reflect on what I truly wanted to do. Life is short, and sometimes it's okay not to have a plan or a job. I believe this is the right time for me to take a very long break, so I can spend more time with the family. I don't know what the future holds, but I'm excited about the possibilities. 

See you soon!

Tuesday, June 11, 2024

Physical Therapy (PT) at the 401 clinic

PT and healing are going well! I can move around for most of the normal (light) activities, and without excessive pain. I've been out of pain killer for several weeks already. However, my surgeon (Eklund) seems to be more conservative and would like me to be on the sling AT LEAST 7-8 weeks because of the additional Remplissage procedure. 

The PT location is at the 401 location of Sutter Health. My physical therapist (Jason) said that even if I feel fine, the sling should be worn when I'm outside in case I accidentally do something that would mess up the healing process.


Below is a typical PT exercise sheet I need to perform every day. Currently, my range of motion upwards is about 135 degrees, and we're working to to get it up to 160-170 next week, hopefully.


Overall, I'm quite happy with my progress. I remember the first surgery (from decades ago) took months to heal, but this time, I'm healing much faster.


Thursday, May 9, 2024

I'm typing with both hands now! Things are going well and I'm pretty happy so far.

Per instructions given to me, I could not take wet showers because contaminants might get into the wounds. Earlier this week I went back for a pre-scheduled PO check and the doctor removed the first dressing, cleaned the bloody surfaces, and reapplied fresh clean dressings (see below). Things looked good, and I felt pretty good as well. And the first thing I did when I got home was to take a real shower, and boy, it felt good! Overall, it's been a positive experience so far -- no complications and manageable pains.

As for the post-op pics below, it's really funny that they marked my upper body all over with bold identifiers. During pre-op, the nurses kept asking me to confirm my name, birthday, and triple confirmed the correct side to perform the surgery on -- just in case!


At the PO clinic I learned a few medical terms. The repairing of the labrum was done by inserting screw anchors to the bone, and tying them around to stabilize it (Bankart procedure). It was explained to me that in time, my own tissues would grow around and strengthen parts to keep the labrum and scapula stronger (months). It's imperative that I don't stress the bones/muscles/tendons in order for the tissues to grow back properly. See the illustrations below:


During the procedure, Dr. Eklund also noticed more problems that were not clear from the CTs and decided to perform an additional procedure called "remplissage". This is a procedure that stabilizes recurrent anterior shoulder dislocations, by filling in a medium sized Hill-Sachs region in the humeral head caused by  prior dislocation traumas. Below is an illustration of the Hill-Sachs lesion (trauma areas) and repositioning of the infraspinatus tendon into the Hill-Sachs area, effectively "filling in" to prevent it from engaging with the glenoid (shoulder socket) during shoulder movement.
In total, Dr. Eklund inserted 6 1.8mm anchors + "knotless" sutures for Bankart lesions, and 2 (bigger) anchors for the Hill-Sachs lesions.

This is my second week, and pain is now manageable without opiates, when I use ice-packs intermittently. I'd like to avoid hydrocodone (opiate) because it works all TOO well -- it has a tendency to  make me feel invincible and want to move around, which is not a good thing when I am suppose to rest and heal.

Thursday, May 2, 2024

Today is the 2nd day of surgery. I'm feeling good enough to type now, albeit veeerrry sloooowly.

The first day was uneventful. I checked in at 6:30am. There were some pre-op checks and questionnaires and forms to sign. The anesthesiologist put me to sleep around 7:50am. I woke up around 11:30am, but barely able to think or talk. Pam was already here but I couldn't walk (I was too nauseated/dizzy) and it took a looong time to get into the car-- I don't remember the details but I was half dozing off and trying to get out of the wheel chair. I slept through half of the day. I didn't fully awake and drink water and walk around until late in the afternoon.

The funny thing about the surgery is that post-op, I didn't feel any pain at all. Zero -- NADA! And besides feeling tired and somewhat nauseated, I actually felt carefree and a bit happy. It was probably the opiates working all too well. Later at night, I started to feel more and more pain until I decided to take Hydrocodone (opiate) that I picked up the day before the surgery. First 48-72 hours -- pain management is utmost important.

Back to day 1: when I was asleep, Dr. Eklund told Pam that it went well, and everything else will just depend on post-op care. It's now day 2, and I am hoping that with good PT and some time to heal, I'll be good very soon. I can't wait to play tennis, biking, & skiing with my kid. And of course, I can't wait to get out of the house and start working again!


Below are some pictures from the scope. You can see the instrumentations drilling in for labral repairs, etc/aka capsular plication). High tech stuff -- I love it!