Welcome to AddressOf.com Sign in | Join | Help

(Rebuttal) Reason #458 Why Visual Basic.NET Sucks

I can't help it... this crap is so wrong that it *MUST* be discussed.  It's been picked up my many people in the blogsphere and used as “reference“ material in forums.  It's wrong, wrong, wrong, WRONG!  You'd think after almost 5 months of being posted people would check their facts.  So since others apparently don't wish to do so, here goes.

Where should I start?  Well, let's ignore the “performance” portion of this and break down a few other things before I get there.  Let's look at some of his comments:

Supposedly he decided to do a bit of IL spelunking and discovered that VB does indeed treat the = operator a bit differently than C# does.  In fact, VB does a lot more and it's wrapped up within a call to Microsoft.VisualBasic.CompilerServices.StringType.StrCmp.  What is interesting about his “observation” is:

“Holy cow!  This means that if you use the equals operator... you're actually calling into old VB6 libraries using COM Interop.“

WHAT!?!?!  Where did he derive this conclusion from?  How about we look at the *ACTUAL* IL...

.method public static int32 StrCmp(string sLeft, string sRight, bool TextCompare) cil managed
{
      // Code Size: 51 byte(s)
      .maxstack 4
      .locals init (
            int32 num1)
      L_0000: ldarg.0 
      L_0001: brtrue.s L_000a
      L_0003: ldstr ""
      L_0008: starg.s sLeft
      L_000a: ldarg.1 
      L_000b: brtrue.s L_0014
      L_000d: ldstr ""
      L_0012: starg.s sRight
      L_0014: ldarg.2 
      L_0015: brfalse.s L_002b
      L_0017: call [mscorlib]System.Globalization.CultureInfo Microsoft.VisualBasic.CompilerServices.Utils::GetCultureInfo()
      L_001c: callvirt instance [mscorlib]System.Globalization.CompareInfo [mscorlib]System.Globalization.CultureInfo::get_CompareInfo()
      L_0021: ldarg.0 
      L_0022: ldarg.1 
      L_0023: ldc.i4.s 25
      L_0025: callvirt instance int32 [mscorlib]System.Globalization.CompareInfo::Compare(string, string, [mscorlib]System.Globalization.CompareOptions)
      L_002a: ret 
      L_002b: ldarg.0 
      L_002c: ldarg.1 
      L_002d: call int32 string::CompareOrdinal(string, string)
      L_0032: ret 
}

OK, I see some calls to another Visual Basic library method to gather the current culture information.  Let's see what the IL for the additional VB library method is...

.method assembly static [mscorlib]System.Globalization.CultureInfo GetCultureInfo() cil managed
{
      // Code Size: 11 byte(s)
      .maxstack 1
      .locals init (
            [mscorlib]System.Globalization.CultureInfo info1)
      L_0000: call [mscorlib]System.Threading.Thread [mscorlib]System.Threading.Thread::get_CurrentThread()
      L_0005: callvirt instance [mscorlib]System.Globalization.CultureInfo [mscorlib]System.Threading.Thread::get_CurrentCulture()
      L_000a: ret 
}
The rest of the calls, meaning the non-VB library methods, in these methods are *ALL* in the .NET Framework.  There is absolutely *NO* call to any VB6 libraries in this call.  Again, where did he derive his conclusion from?  Oh, so maybe he just mis-spoke... let's continue on...

“When this occurs, you get a major lag because you have to marshal the string out of managed memory into unmanaged memory.  Using the .Equals method on the other hand keeps everything in managed memory and does a much faster comparison.  That explains the difference.” 

He is definitely talking about P/Invoke (whether it be COM or Win32) since states the string being marshalled between managed and unmanaged memory.  Hard to mistake what his conclusion was.  He then continues on to refer to at least one member of the VB team being an “absolute moron“.

“My question is... Who was the absolute moron on the VB.NET compiler team who made that decision?“

Um... based on what you've read so far, who's the moron... anyway, let's continue on...

He continues on to discuss how C# is soooooo superior in this regard.  However, he finds that in C# that the = operator and .Equals are different in speed as well.  By his numbers, a factor of 4.  So let's look at the performance...

He points out that C# utilizes the op_Equality method (what the == operator in C# gets translated to at the compiler level).  Here's it's IL.

.method public hidebysig specialname static bool op_Equality(string a, string b) cil managed
{
      // Code Size: 8 byte(s)
      .maxstack 8
      L_0000: ldarg.0 
      L_0001: ldarg.1 
      L_0002: call bool string::Equals(string, string)
      L_0007: ret 
}

As you can see, internally it calls upon the .Equals everyone seems to like to discuss.  However, how is it that the inclusion of just 4 opcodes could introduce a speed difference by a factor of 4?  It can't.  Essentially, the timings his code reflects can't be counted upon since he's only running a single iteration.  The test should be done drastically different since in this single iteration many other factors could be occurring such as memory management on the machine, other applications running (CPU load), JIT, etc.  You'd have to take a sampling of timings across several iterations to gather some numbers that mean anything significant.

So based on this single pass test, his numbers showed as VB's version being 200 times slower.  This is also not true.  It is true that it is slower than the C# counterpart (read further for updates in Visual Basic 2005).  However, the performance hit is nothing near a factor of 200.  My testing has shown this to be more of a factor of 6-7.  Yes, slower than C#, but not that slow.  What causes the difference?  In VB it's doing two additional checks.  Let's look at the IL again (this time, converted to VB for easier reading).

Public Shared Function StrCmp(ByVal sLeft As String, ByVal sRight As String, ByVal TextCompare As Boolean) As Integer
  If (sLeft Is Nothing) Then
    sLeft = ""
  End If
  If (sRight Is Nothing) Then
    sRight = ""
  End If
  If TextCompare Then
    Return Utils.GetCultureInfo.CompareInfo.Compare(sLeft, sRight, (CompareOptions.IgnoreWidth Or (CompareOptions.IgnoreKanaType Or CompareOptions.IgnoreCase)))
  End If
  Return String.CompareOrdinal(sLeft, sRight)
End Function

The VB StrCmp method will automatically handle Nothing (or NULL) strings in the comparison.  This could be good or bad depending on your point of view since “” could equal Nothing.  However, most of the time this behavior is preferred since you don't have to specifically worry about the difference between an empty string and a Nothing string.  If you need to know, then you could check for it specifically.

This is where the slight performance hit comes in... again it's not hit by a factor of 200, but rather more like 6-7... which is 25% to 33% over the C# counterpart.  In addition, the VB StrCmp ends up calling upon String.CompareOrdinal, which in my testing has shown to be slightly faster than String.Equals... so if you want to get picky... C# isn't as fast as it could be.

Up to this point, I've been discussing VB7.1 (aka the Visual Basic .NET 2003 / .NET 1.1).   What about VB8 (Visual Basic 2005 / .NET 2.0)?  In VB8, the StrCmp method has been updated...

Public Shared Function StrCmp(ByVal sLeft As String, ByVal sRight As String, ByVal TextCompare As Boolean) As Integer
  If (sLeft Is sRight) Then
    Return 0
  End If
  If (sLeft Is Nothing) Then
    If (sRight.Length = 0) Then
      Return 0
    End If
    Return -1
  End If
  If (sRight Is Nothing) Then
    If (sLeft.Length = 0) Then
      Return 0
    End If
    Return 1
  End If
  If TextCompare Then
    Return Utils.GetCultureInfo.CompareInfo.Compare(sLeft, sRight, (CompareOptions.IgnoreWidth Or (CompareOptions.IgnoreKanaType Or CompareOptions.IgnoreCase)))
  End If
  Return String.CompareOrdinal(sLeft, sRight)
End Function

A few changes as you can see, so how is the performance?   Well, probably not due specifically to the changes made in the method that the = operator has gone through, although in some cases, it is possible that the new method could be a lot faster since it may never even make it to the CompareOrdinal call under the right conditions.  .NET 2.0 code just seems to be a bit faster overall and this is probably where some of the speed improvement has come from.  So what is the improvement?  Let me let someone else point out a difference (even though they decided to post anonymously... go figure)...

Equals Operator: 3.7993655618242E-05 sec
Equals Function: 3.43619091253218E-05 sec

Hmmm... not much of a difference there.  But instead of taking this guys word for it, let's look at my own testing... one where I do several iterations [1].  After 100,000 iterations, doing a raw addition of the individual timings and comparing these across three different operations (= operator, String.Equals, and String.CompareOrdinal), the numbers are rather interesting...

VB version:

= Operator:                     0.177467527297846 : 102.65 %
String.CompareOrdinal:   0.177394892368044 : 102.61 %
String.Equals:                   0.172890688621453 : 100.00 %

C# version:

= Operator:                     0.166826230708464 : 104.47 %
String.CompareOrdinal:   0.173935234785814 : 108.92 %
String.Equals:                  0.159690407580096 : 100.00 %

Essentially, I did a percentage comparison using String.Equals as the baseline.  What's interesting is that sometimes when running this test, I have seen drastically different timings when running in “debug” mode.  Here's the C# timings (for the naysayers out there)...

= Operator:                     2.04699200596579 : 107.95 %
String.CompareOrdinal:   1.8898748304617 : 99.67 %
String.Equals:                   1.89616278046669 : 100.00 %

Not only is the timings drastically different, notice that the String.CompareOrdinal is actually faster than String.Equals.  This has been pretty much consistent in my testing.  I have however seen String.CompareOrdinal run faster than String.Equals in release builds as well, so who knows what is really happening with such a simple test.  And if you run enough tests, you'll see results like this...

VB version:

= Operator:                    0.186439896691224 : 94.34 %
String.CompareOrdinal:  0.16090648392503 : 81.42 %
String.Equals:                 0.197625955254675 : 100.00 %

So in at least one test, the VB version was actually faster than String.Equals. 

What does all this mean?  It means a few things.

  • Don't listen to people like this.  No matter how much crap they try to spout, check their facts if their claims seems to be amazingly silly.
  • Don't rely on other peoples “testing“ to base your performance decisions upon.  In the end, you have to take into account your specific needs (or more specifically, your codes needs) and test it accordingly.  You might have a need to try to gain a few microseconds of performance by utilizing String.Equals or String.CompareOrdinal directly.  However, I believe that you would probably be gaining that overhead right back by having to do the extra tests that would have been handled for you already if you'd just use the operator.  But that's me... like I said, your individual circumstance, it might be a performance improvement.
  • Performance is more than just “raw numbers“.  Circumstances play a huge part of what makes up your overall application performance.  Saving a few opcodes here and there when that part of the code is only running once every so often isn't going to help you improve your applications overall performance.  Performance improvement is more a case-by-case discussion rather than a blanket argument.  Sure, there are some best practices, but not utilizing the = operator is *NOT* one of them.
  • **VB IS NOT INFERIOR**... in many respects *IT IS SUPERIOR*.  Yes, I said it.  There.  Deal with it.  Think I'm wrong, by all means, let me know.  (Leave out the syntax argument... if you like semicolons and curly braces... fine... that's a preference, not an argument as to why one is better than the other... bring me “real“ issues.)  ;-) 

[1] - Download code (Yes, there's a VB and C# version of the code in the zip file.).

Published Wednesday, December 07, 2005 4:21 AM by CorySmith
Filed under: ,

Comments

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Wednesday, December 07, 2005 11:37 AM by Greg
Nice work.

Having released production apps in all versions of VB since 1.0, my skin has hardened quite a bit on this subject...

I usually sigh, and then continue to knock out the apps my customers need in less time, with more features. ;)

I wish people could focus on why their language of choice is good and how to make it better, than focusing on why others suck compared to it. But if wishes were fishes no one would ever be hungry...

In any case, thanks for taking the time to do this...

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Wednesday, December 07, 2005 2:04 PM by Dale LeBlanc
After reading this and so many other posts about what language is better I had to respond to both sides. This is the same type of bickering as which is better MACs or Windows, and started the virus wars way back when.

I’ve been programming for near 30 years now and have learned several different languages (VB, BASIC, C, C++, C#, PASCAL, COBOL, DBxx , CPL ) and am continuing to learn (ASP, JAVA, etc). The impressions I am getting from all of these posts is the younger generation of programmers are hurting them self and their customers by learning only one language. In all those years I have found no single language which would allow me to do everything every time. A good programmer has a grasp of many languages and uses them based on what he/she has to do. In some cases VB might be a better choice then C or you may need to go way back and use COBOL if it is the best method of doing the job.

Quit worrying about which is better or faster, start thinking in terms of how can I best get this done. Be different, learn as many languages as you can and you may find out that you don’t know as much as you think you do.

As I was once told: “A truly lazy person is the one who does the job in the fastest, easiest and most efficient way and does it right the first time so they don’t have to do it again.”

Dale LeBlanc
Systems Integration Professional

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Wednesday, December 07, 2005 8:49 PM by David Stone
Cory...you're going to have a heart attack and die at a very young age. :-P

I would, however, love a post on why VB.NET is superior to C#. :)

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Thursday, December 08, 2005 9:41 AM by VBMan
David -

Uh, because it doesn't SUCK like C#?

I mean really now... what new languages are still stuck wearing bell-bottom curly braces and large belt buckle semicolons? It's soooo 70's! Smalltalk, Eiffel, Ruby, Boo, Haskell, nope, none of them use them. All productive languages, especially business oriented languages that have had success didn't use them, except for Delphi (semicolons), but of course no one uses Delphi! :-P

Seriously, what is it with the curly brace cowboys? It's like the Stockholm effect; I guess if you use them long enough, you begin to like them...

I'll pass. I'm trying to cut down on my consumption of braces and semicolons this Holiday season! <g>

# More C# Elvis impersonators

Thursday, December 08, 2005 7:11 PM by @ Head

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Sunday, December 11, 2005 9:06 AM by Holly
Semicolons are 70's???? Boy, you really don't know what you're talking about.

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Monday, December 12, 2005 4:14 PM by VBMan
Enlighten me oh wise Holly... please, share the wisdom.

For such a smart compiler as C#, it's amazing they still need superfluous {} and ;. Oh well, guess some folks just love fashion a bit too much. :-|

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Tuesday, December 13, 2005 6:55 PM by VBMan
C# - it's the new look-alike language. Besides VB, does any mainstream language have the cojones to NOT follow the C-wannabe languages and show some improvement and originality? Oy vey!...

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Tuesday, March 14, 2006 6:39 PM by JC
How are curly braces superfluous but "Sub" and "End Sub" are not?

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Wednesday, April 12, 2006 6:13 PM by Old Guy
OK, OK, OK - thanks to Cory for his research into this, and enough already with the "curly braces vs Sub...End Sob". Do you want to use a blue sweater or a red one???

What I'd like to see (but am too lazy to do) is to compare Cory's results (C# or B#) against an "as similar as possible" program in VB6 (or C++ - I don't really care). I have in mind an opportunity to determine whether Richard Grimes' analyses about the speed of .NET managed code often being comparable to "old fashioned" unmanaged code are borne out...

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Monday, May 22, 2006 5:30 PM by TL
Holy cow! I think I've found where some of the zealots hang out! ;)

What is important about .NET is the !Framework!, not the languages! And guess what... that's the same between both VB.NET, C#, even COBOL.NET, for pete's sake. I personally like C# because:

1. braces are quicker to type than End Sub
2. I'd rather use semicolons consistently than deal with line continuation characters.
3. Dim x As y is about the most stupid way to declare a variable that I've ever seen.

and a few other reasons that also DON'T IMPACT MY PRODUCT at all.

The only functional difference I've found is the ability to apply attributes to parameters in C#. Other than that, code in what you want 'cuz it just doesn't matter.

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Saturday, August 26, 2006 2:46 PM by Terry
I like Sub and End Sub better than braces because I read english and it just looks better to me. I'm not saying C# sucks, just that I prefer VB. I've never found anything that I couldn't do in VB.

I personally find that DIM x as String is easier to read than string x.

I also like the line-contiuation character lots better than using semi-colons. Semi-colons are required after every statement. Line-continuations are only required if you want to split up a long line, which doesn't happen very often for me.

To each his own I guess.

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Friday, September 01, 2006 1:40 PM by wtf
Wow whats the big deal you like this syntax I like that.

In reality I couldn't care less. I'll program vb today c# tomorrow Delphi the next day and why the hell not I'll program some prolog if the job calls for it. You can do anything with all of these languages they're all turing complete. Sometimes one language is better suited for one job so you use it for that job. For the next job you find the best suited language and move on and so on

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Tuesday, June 26, 2007 4:24 PM by mrwizzard
No Clue where you "don't" see it, but when i tested the equals, it calls the visual basic compatability string compare... while C# Does not... a Direct "=" is SLOWER than doing a string.equals in VB... the C# "=", does the string.equals, where in VB, it calls some compatability routine, instead of the equivalent string.equals... so to produce the same IL in VB as C#, you Must use string.equals(string,string) The fact that there is few less opcodes makes a HUGE difference if you were doing these kind of compares in a loop.... FYI, i've also read this is several .NET preformance Books, one from one of the guys that worked on .NET

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Monday, July 30, 2007 9:08 AM by YaMan
Dim Stability as Variant ;-D

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Tuesday, September 25, 2007 4:47 PM by Bill Fazakerly
I had no problem using VB6 to create disconnected recordsets, modify them, and (batch) update databases. I am really struggling with datasets, dataadapters, datatables, binding sources, command builders, and the myriad of .NET constructs. I have been working, unsuccessfully, for a week just to get a dataadapter to update a dataset. Keep getting syntax error, and I can't figure out how to "see" the SQL that was actually sent to the database engine. I like VB but .NET sucks.

# re: (Rebuttal) Reason #458 Why Visual Basic.NET Sucks

Friday, October 05, 2007 3:25 PM by CodeMonkey411
You want to know why VB sucks? Yeah, it sucks. But not for any real technical reason. Because the people who use it suck. Yeah, this is a stereotype, but for the most part it seems to be true. CompSci majors don't tend to gravitate to the language because it has been a mickey mouse language for the past decade that did not posess most of the important features that a robust language should posess. It was good for rinkydink applications, but if you needed something fast and powerful, you wrote in c/c++. And to do that properly, you needed a skilled coder that understood pointers, algorithims, buffers, and stacks. VB seemed to attract hobbyist coders. people who could wire up a few forms and text boxes, and work on a minor pet project for the boss. Oh sure, there were some real skilled VB people who could wire up a COM control and read hex, but they were pretty rare. Perhaps now that it growing into a real language in .net, new skilled programmers might discover it. But for now, you have tons of VB 'coders' working in the real world who can't build a decent object in VB.NET, and they are making the language suck. If I were an employer, I would not be hiring VB people. I bet that the average c# coder could kick the average VB jerk around the block, because C# seems to be where the C++ type guys are going. Let's take this debate up in ten years, when some of the VB hacks have died off and the talent pools are more equal. The language isn't bad, the coders are.
Anonymous comments are disabled