June 2007 Entries
These are the articles (in no particular order) that I felt best showed a thorough use of the WinDbg.exe tool from start to finish. They were absolutely priceless to me. Enjoy!
ASP.NET 2.0 Crash case study: Unhandled exceptions
A word for WinDbg (2)
Some new SOS functions
System.ArgumentException: Illegal characters in path
Tracking down a production bug
.NET Memory Leak: XmlSerializing your way to a Memory Leak
ASP.NET Case Study: High CPU in GC - Large objects and high allocation rates
ASP.NET Case Study: Tracing your way to OOM exceptions
Basic debugging of an application crash
Tracking Down Managed Memory Leaks
+ 1 Troubleshooting ASP.NET using WinDbg and the SOS extension
=)
5 things I wish I had known or done prior to attempting to work with SOS.dll and windbg.exe:
sos.dll needs to be in the path for windbg in order to load it
you can .load %full path to sos.dll% instead of .load sos mscorwks or other statements
SOS for .NET 2.0 does *NOT* have all the commands the .NET 1.x version does (a source)
review http://msdn2.microsoft.com/en-us/library/bb190764(vs.80).aspx and use !help %command% often
where these two articles were: one, two.
I experienced an extreme amount of pain first working with SOS.dll because of some of the problems above. I also found that there were LOTS of articles about using it, but some were more detailed...
something cool i've never heard of. quoted from http://blogs.msdn.com/dougste/ about a path value of \\?\C:\WEBSites\WWWMyApp\scripts:
First of all, what is illegal about this path? Well, nothing, if you are a Unicode Win32 API. As you can read in Naming a File on MSDN, certain Unicode Win32 file handling APIs allow a path to be prefixed with \\?\ which allow paths to be up to 32,000 characters in length among other things. It also tells the operating system to not canonicalize the path by interpreting things such as .. to mean 'go to the parent directory'. Unfortunately not all parts of the System.IO namespace...
since i've had it in mind to write this for *so* long, i will at least write something, and maybe someday i'll come back and clean it up. =P
i was talking to a friend of mine quite some time back about what i call the 'triangle theory' of resource management at most companies. the idea is that most companies distributed resources in a triangular fashion. the top (narrow) part of the triangle is where the smallest amount of resources go. the top part also is where the most skilled people reside and is represented by the small area taken up...
I found this while in my surfing and thought it was a noteworthy point on .net multi-threading.
quoted from http://msdn2.microsoft.com/en-us/library/ms998547.aspx (underlining is mine):
The CLR exposes managed threads, which are distinct from Microsoft Win32® threads. The logical thread is the managed representation of a thread, and the physical thread is the Win32 thread that actually executes code. You cannot guarantee that there will be a one-to-one correspondence between a managed thread and a Win32 thread.
If you create a managed thread object and then do not start it by calling its Start method, a new Win32 thread is not created. When a managed thread...
i feel like i have seen a ton of places that say for and foreach are the same performance-wise in .net. i never really worried about it much. i have historically done a lot of refactoring and loops are definitely one area you can see lots of improvement in. so i figured i would post some actual documentation about this. =)
quoted from http://msdn2.microsoft.com/en-us/library/ms998574.aspx:
Using foreach can result in extra overhead because of the way enumeration is implemented in .NET Framework collections. .NET Framework 1.1 collections provide an enumerator for the foreach statement to use by overriding the IEnumerable.GetEnumerator. This approach is...
This is in response to this article and is me giving dennis a hard time. =P
byte[] XmlToByte(XmlDocument d){ using (StringWriter sw = new StringWriter()) { using (XmlTextWriter xw = new XmlTextWriter(sw)) { d.WriteTo(xw); ASCIIEncoding encoding = new ASCIIEncoding(); return encoding.GetBytes(sw.ToString()); } }}
Ah. Garbage Collection... how I love and hate thee. =P
I think one sad thing about programming in .net is that it seems many developers don't know or care anything about garbage collection and memory management. You used to *have* to know about it in order to write bug free code. I suppose it is a two edge sword in that developers can develop faster as the intention was to relieve developers of the need to know or care anything about memory management. I personally have always tried to follow best practices for implementation and have tried to stay somewhat cautious...
so I saw this headline the other day in one of my feeds:Speed Up Performance And Slash Your Table Size By 90% By Using Bitwise Logicwhich, of course, piqued my interest. after reading this article, i decided to do a little research. one thing to realize is that using the int datatype you can only utilize 32 choices. i'm not an expert in using base 2 for math, however i went out and tried to find some articles that would refresh my memory. the following two were my favorites:Bitwise Operations in CPHP Bitwise TutorialThe second had my favorite bit (haha!)...
create table t(id int identity primary key, v bit)go
insert t select 1go 10
select count(*) [before] from t
begin tran truncate table t select count(*) [after
truncate] from trollback tran
select count(*) [after
rollback] from tgo
drop table tgo
I have heard this in multiple meetings. It's not true. Please investigate your individual situations, but the idea that you can not rollback a truncate at all is incorrect.
Johnson, Sean [9:58 AM]:I love theseAshbrook, Roy [9:59 AM]:i have seen entire procs that have like a whole extra complicated proc in them, just because they want one temp table that they think they need heheAshbrook, Roy [9:59 AM]:so they copy like the top 80% of the proc, just to get the 10% in the middle =PJohnson, Sean [9:59 AM]:ok you are looking at this along with me apparently... LOL!Johnson, Sean [9:59 AM]:same thingAshbrook, Roy [9:59 AM]:yep. makes me sad hahaJohnson, Sean [9:59 AM]:it makes you cringe to look at the rest of the procs now doesnt itAshbrook, Roy [10:00...
-- create a mini inventory structure-- let's say it has toys in itdeclare @x xmlset @x ='<items> <item id="1" type="toy"> <name>car</name> <description>toy car</description> <price>10</price> </item> <item id="2" type="toy"> <name>bike</name> <description>toy bike</description> <price>100</price> </item> <item id="3" type="sport"> <name>bike</name> <description>real bike</description> <price>100</price> </item></items>'--look at the toysselect x.item.value('@id[1]','int') [id] , x.item.value('@type[1]','varchar(20)') [type] , x.item.value('name[1]', 'varchar(20)') [name] , x.item.value('description[1]', 'varchar(20)') [description] , x.item.value('price[1]', 'money') [price]from @x.nodes('//items/item') as x(item)--wait, they should all be toys.--what's that real bike doing in here?--let's delete the non toysset @x.modify('delete (/items/item[@type!="toy"])')--hmm, that price is still way wrong on our toy bike, let's fix itset @x.modify( 'replace value of (/items/item[description/text() = "toy bike"]/price/text())[1] with "10"')--yay!select x.item.value('name[1]', 'varchar(20)') [name] , x.item.value('price[1]', 'money') [price]from @x.nodes('//items/item') as x(item)
datalengthfrom BOL - "Returns the number of bytes used to represent any expression." the individual that asked me about this recently started using some much larger xml objects in their xml datatype column. it threw off sql because the stats weren't being updated and caused some performance issues which an update statistics and a clustered index rebuild corrected.this also works with the xml datatype variables. so you can do adeclare @x xmlset @x = 'some xml here'select datalength(@x)