添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below. Reading through the database section of the forum, I came across this thread here:
http://www.vbforums.com/showthread.php?t=511775
where RhinoBull said that the IIF statement should never be used because it was slow and inefficient. I decided to test this out in VB to see if that claim held up. Turns out it does. Running the code:
vb Code:
  1. Dim sw As New Stopwatch
  2.         Dim x As Integer
  3.  
  4.         sw.Start()
  5.  
  6.         For i As Integer = 0 To 1000000
  7.  
  8.             IIf(i Mod 2 = 0, x = 1, x = 2)
  9.  
  10.         Next
  11.  
  12.         sw.Stop()
  13.         lstResults.Items.Add("IIF - " & sw.ElapsedMilliseconds.ToString())
  14.         sw.Reset()
  15.  
  16.         sw.Start()
  17.  
  18.         For i As Integer = 0 To 1000000
  19.  
  20.             If i Mod 2 = 0 Then
  21.                 x = 1
  22.             Else
  23.                 x = 2
  24.             End If
  25.  
  26.         Next
  27.  
  28.         sw.Stop()
  29.         lstResults.Items.Add("If Then - " & sw.ElapsedMilliseconds.ToString())
  30.  
  31.         sw.Reset()
  32.  
  33.         sw.Start()
  34.  
  35.         For i As Integer = 0 To 1000000
  36.  
  37.             IIf(i Mod 2 = 0, x = 1, x = 2)
  38.  
  39.         Next
  40.  
  41.         sw.Stop()
  42.         lstResults.Items.Add("IIF - " & sw.ElapsedMilliseconds.ToString())
  43.  
  44.         sw.Reset()
  45.  
  46.         sw.Start()
  47.  
  48.         For i As Integer = 0 To 1000000
  49.  
  50.             If i Mod 2 = 0 Then
  51.                 x = 1
  52.             Else
  53.                 x = 2
  54.             End If
  55.  
  56.         Next
  57.  
  58.         sw.Stop()
  59.         lstResults.Items.Add("If Then - " & sw.ElapsedMilliseconds.ToString())
shows that the If Then statement runs 4 or 5 times faster than the IIF statement.
RhinoBull is right and the IIF statement should never, ever be used under any circumstances whatsoever. It just sucks. Well, that's probably because the If statement is a language construct where as IIF is a function within VB. They're probably not optimized the same though I would be curious as to what the MSIL looks like.
If you really wanted to (but I sure hope you wouldn't) you can use IIF in C#.
I know that, but in 2008, you can use IF just like IIF: If(condition, true value, false value) as typeof value.
I was wondering if it behaved like IIF (i.e. it was garbage) or if it behaved like IF. the If() construct is now a ternary operator in the VB language... it is not a function, and it supports short-circuiting. The True value is ONLY evaluated if the condition returns true. the False value is ONLY evaluated IF the condition returns false. It's superior to the IIF() function of old. However, like anything else, it should be used under the appropriate conditions.
It doesn't get compiled the same as an If because it's actually different from an If. One is a lnaguage keyword that signifies the beginning of a code block, while the other is an operator which will return one of two values. The IF() operator is NOT a control block. It returns one of two values.
* I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
* I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
* How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
* How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *
That could have a slight impact on unsafe multi-threaded programs, since I believe a context switch couldn't happen in an If() statement, but could happen in an If....End If block. Shouldn't matter, but the state of an object shouldn't change during the first one, but could during the latter. Of course, if you are engaging in unsafe threading, this will be the least of your problems.
It doesn't get compiled the same as an If because it's actually different from an If. One is a lnaguage keyword that signifies the beginning of a code block, while the other is an operator which will return one of two values. The IF() operator is NOT a control block. It returns one of two values.
Sort of like an If Else statement. There's nothing else that an IIF statement would do, so wouldn't it make sense to have it compile to the IL the same way that an If Else statement would? Regardless of how it's set up in VB, there's only one way that it would work in IL, so why bother to compile the extra drudge that slows it down? no, not like a If Else.....Not even close. The IIF is a scalar function (as is the If() now in VB2008).... If Then Else is a control block two clearly different operations.
To say one is the same as the other is to say that my house key could also be my car key. After all, they both go into a lock, and the outcome is the same, the lock is released.
IIF was/is a function ..... just like any function that you create... which means that in order to pass TrueValue and FalseValue to it, it had to first evaluate them to see what their results are, BEFORE passing them to the IIF function. This is where the pitfall of the IIF was/is found. It prevents me from doing things like this:
strMyString = IIF(IsNull(rst.Fields("MyField").Value), "", rst.Fields("MyField").Value)
This is the #1 gotcha of the IIF. because the TrueValue returns NULL, an Invalid use of Null is thrown. With If() this will not happen.
Since If() can still only return a singlular value, it shouldn't emit the same IL as an if/then/else
* I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
* I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
* How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
* How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *
It's just occurred to me that the new If() expression could lead to some very creative expressions. Let's say you have a bit field (boolean-yes/no for you Access folks), it could contain true (1) or false(0), but let's also say that the field allows NULLs. Which means it could have a potential of three values (two true values and one non-value). And let's say you want to display "YES", "NO" or "UNKNOWN" for each of the possibilities:
Code:
txtSetting.Text = If(IsNull(drDataRow.Item("SettingFlag")), "UNKNOWN", If(drDataRow.Item("SettingFlag"), "TRUE", "FALSE"))
You couldn't do that with an IIF... and to do that with standard If/Then construct would take a few more lines. Correctly used, it can be a time saver and make the code easier to understand.
* I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
* I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
* How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
* How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *
I can't really see why it is running so much slower. If you decompile the Microsoft.VisualBasic.dll you will see that the IIF function looks like this.
Code:
Public Shared Function IIf(ByVal Expression As Boolean, ByVal TruePart As Object, ByVal FalsePart As Object) As Object
     If Expression Then
          Return TruePart
     End If
     Return FalsePart
End Function
This is virtually the same as writing it yourself. I don't really see how that can be slower, however you have tested it to be so. I wonder what else they are running to slow down this operation.
Boooya
  • Visual Studio 2008 Professional
  • Don't forget to use [CODE]your code here[/CODE] when posting code
  • Don't forget to rate helpful posts!
  • If you're question was answered please mark your thread [Resolved]

Code Contributions:
PHP Image Gallery v1.0 PHP Image Gallery v2.0
VB 2005
Find Computers on a network Simple License Encryption SQL Server Database Access dll Use Reflection to Return Crystal ReportDocument Silently Print PDF Generic Xml Serailizer
Useful Links: (more to come)
MSDN (The first and foremost) MSDN Design Guidelines API Reference • Inno Setup Compiler Inno Setup Preprocessor ISTool - Fairly easy to use GUI for creating inno setup projects • Connection Strings NAnt -Automated Builds Cruise Control .NET - Frontend for automated builds
The reason why IIF can be slower, is because it evaluates, that is looks at, all 3 params. It evaluates the test condition, it evaluates the true part, and it also evaluates the false part. This is all before the function is even stepped into.
The If operator on the otherhand, only evaluates the test condition, then from there, picks either the true part or the false part to evaluate.
If you want to see a test of this, just paste this code in:
Code:
    Private Function FalsePart(ByVal testName As String) As String
        MessageBox.Show("False Part: Test " & testName)
        Return "False Part"
    End Function
    Private Function TruePart(ByVal testName As String) As String
        MessageBox.Show("True Part: Test " & testName)
        Return "True Part"
    End Function
    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
        Dim result1 As Object = IIf(1 = 2, TruePart("IIF"), FalsePart("IIF"))
        Dim result2 As Object = If(1 = 2, TruePart("IF Operator"), FalsePart("IF Operator"))
    End Sub
The condition I use (1 = 2) is obviously always false, but only in the case of the If (short circuiting) operator, does it NOT evaluate the True part.
This also makes it clear that SOMETIMES IIF is actually better than the IF operator. It all depends on what you are doing. What if (like my example) both your true and false parts were functions. What if you wanted both functions to run no matter what, but you only wanted the result of the one that met the test condition. Since IIF evalutes both functions you used as your truepart and falsepart params, both functions would run, but you only get the result from the one that matches your test condition. It's because there is no short-circuit ability in the IIF method.
In a real If statement, if you're comparing two items and the first item can satisfy the entire statement, it'll "short-circuit" and move on without touching the second statement. Using the IIF method, each item is evaluated when they are passed as parameters. From there, a regular If statement is run.
Try using an IIF with two message boxes. Then try using a regular If statement with two. The regular If statement will only pop up one of them where as the IIF will pop up both.
TomSawyer ... I'm curious as to the resulting times you got in your test program. Sure, maybe IIF is 4-5 times slower, but how often do you execute it a million times in a loop, as in your test code? If you are just using it one time to set a variable based on some condition, then I don't see a problem with using it and I certainly wouldn't say it sucks.
TomSawyer ... I'm curious as to the resulting times you got in your test program. Sure, maybe IIF is 4-5 times slower, but how often do you execute it a million times in a loop, as in your test code? If you are just using it one time to set a variable based on some condition, then I don't see a problem with using it and I certainly wouldn't say it sucks.
True, but you want to cut down processing time as much as possible. If you have two ways of doing the same thing and one is four times slower than the other, then you slow your app down by doing that one. Sometimes it will slow it down by a microsecond and it doesn't matter, sometimes it will slow it down by a minute and it does.
You're never going to execute something a million times in a row, but if you're doing something basic like looping through a few thousand rows returned from a database and processing based on some if statements, adding a hundredth of a second to the time it takes to do each loop results in significant delay.
Even if the vast majority of the programming you do will never even get slowed down by that amount, it's best to implement the most efficient coding in your applications so when you do find yourself making something that processor-intensive, you don't have to change the standard way of doing things in order to get it working.
If you want to create a distributed program to be used for processing major business for a multinational corporation, you can do it in VB5, but that doesn't mean that writing in in VB5 doesn't suck in comparision to writing the same thing in VB 2008. Speed is important no matter what the language. If you're using VB, you should try to get it as fast as possible.
Sure, VB.Net isn't the fastest language but it's pretty quick for what it's meant for. Why would you think it's acceptable to make the user wait a few more seconds-minutes than necessary? IIF is a pretty useless method so why use it just to slow your application down?
well for starters, the If operator didn't exist until VB9.
I suspect you will start to see much less of IIF() in newly coded projects now that there is the shortcircuiting version.
Another problem is MOST programmers don't know (or learn the hard way) that IIF evaulates all its params. Most people think it does shortcircuit.
As I mentioned above, the only real valid use of IIF() other than trying to squeeze something into as few lines of code as possible, is when you actually want both true and false parts to run regardless of the test condition.
Code:
lblStatus.Caption = IIF(txtName.Text = "", "Enter Name","")
It wasn't (I think) meant to take on the kind of stuff developers have tried to do with it. It fell victim to the laws of unintended consequences. I don't think it ever was meant to be a speed demon.... just a nifty short cut to make a developer's life easier.
The reason IIF is slower compared to a straight-up If..... Stack. Since IIF is a function, the parameters first must be pushed onto the stack. But BEFORE it can do that, it has to evaluate each of the parameters, which means more data has to be pushed onto the stack so that THOSE functions can run, return their values, the results stored, pushed onto the stack again, then and only then will IIF then return a value. Meanwhile, if you created your own MyIIF() function.... I wouldn't be surprised to find out it suffers the same performance degradation the IIf does.... if not worse.
In general, IIf has it's uses, when applied properly . The opposite it true too, there are times when it's inappropriate. But that's what programming is about, using the right tool at the right time for the right job.
* I don't respond to private (PM) requests for help. It's not conducive to the general learning of others.*
* I also don't respond to friend requests. Save a few bits and don't bother. I'll just end up rejecting anyways.*
* How to get EFFECTIVE help: The Hitchhiker's Guide to Getting Help at VBF - Removing eels from your hovercraft *
* How to Use Parameters * Create Disconnected ADO Recordset Clones * Set your VB6 ActiveX Compatibility * Get rid of those pesky VB Line Numbers * I swear I saved my data, where'd it run off to??? *
I don't understand your point. Using IIF isn't making development time any faster, so why use it in a situation where it's going to slow things down? I understand VB isn't the fastest language in the world but that doesn't mean optimization shouldn't happen.
All developers should try to write the most efficient code as possible but what you're saying is it doesn't matter with VB since it's already going to be slow. To me, that's a cop-out or a way to excuse bad / slow code. C# / VB.Net, while slower than C++, can still be very fast. .Net is fast enough that you can write computer games with HD graphics at high resolution and have them play very smoothly (look at Xna and the racers sample game; very shiney).
I don't think .Net will ever replace C++ since there are times where people want the most horse power available but I think you're writing off .Net too quickly/easily.
I think that it rarely matters, but there are a few of us out there who are interested in using the most efficient code possible, even when it makes little difference. If you get into the habit of reaching for the most efficient tool, it will make no difference 99% of the time, but will make a difference in that other 1%.
Virtually everything I have ever written has not been time critical, so something like this wouldn't matter. On the other hand, there is the one program I have that takes three days to run, without ever hitting the HD (it's one giant iterative calculation-a giant model) except to save state periodically. For something like that, shaving off a little time here or there is probably a reasonable thing to do. I suspect that if I ever ran the code with a significantly larger dataset, run times would extend into multiple weeks. At that point, a millisecond here or there will begin to add up. Also, you never really know when an efficiency improvement will make a big difference instead of a small difference, so it's always good to be continually searching for them.
For instance, we have one nightly db process that takes a few hours to run. There are additional processes that need to run based on this completing that sometimes aren't finished by morning, which backs a lot of work up when people are at their desks. I found one article that mentioned that when you use functions in WHERE clauses, SQL doesn't process indexes for the columns being used and simply changing the SUBSTRINGs to LIKEs shaved about 15 minutes off it, which is 15 minutes less of people waiting for things to end in the morning when the processes run long. Yeah well show me a game with 1000000 IIFs() that can be made tolerable to play by replacing IIF() with IF. You may think you are optimizing (heck, I even know exactly how your pleasure center fires) but no software engineer would fall for that.
To continue on topic - I decided to replicate Tom Sawyer's test. On my PC (1.4 GHz P4) IIF() is like 12x slower than IF. On my new 3.4 P4 it is 5x slower and on my notebook's 2.0 Core2Duo - 4x. I expected the ~same ratio but it is not. It seems that IIF() makes better use of better CPUs. Who knows what this would be with 8 GHz. Maybe I could try using 2 threads to see if it'd make a difference. Too bad I have no idea about another language to compare that too.
Here are the test results. I used 100000000 iterations instead of the original 1000000 to produce more meaningful data.
1.4 GHz Intel P4: IIF() - 15843; If - 1259
3.4 GHz Intel P4: IIF() - 2144; If - 418
2.0 Core2Duo: IIF() - 2028; If - 477
I think that it rarely matters, but there are a few of us out there who are interested in using the most efficient code possible, even when it makes little difference. If you get into the habit of reaching for the most efficient tool, it will make no difference 99% of the time, but will make a difference in that other 1%.
Virtually everything I have ever written has not been time critical, so something like this wouldn't matter. On the other hand, there is the one program I have that takes three days to run, without ever hitting the HD (it's one giant iterative calculation-a giant model) except to save state periodically. For something like that, shaving off a little time here or there is probably a reasonable thing to do. I suspect that if I ever ran the code with a significantly larger dataset, run times would extend into multiple weeks. At that point, a millisecond here or there will begin to add up.
I once read somewhere that 1% of code executes 99% of the time. Find that 1% and fine tune it.
I was (am?) working on factorials. When I started I could do 10,000! in the one minute timeframe. It is now down to .5 secs and 100,000! in the thirty second range. I wasted a lot of time making things efficient that didn't contribute much. When I focused on areas doing most of the processing things got better faster.
My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

"Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein
Yeah, improving your algorithm is going to pay off far more than code efficiency. My original concept for the program that takes three days, which is a genetic algorithm, was based on a more litteral conversion of genetic terminology. I was using strings to represent genes, rather than objects. The reason was that it was then possible to look at the genome in a highly visual way. However, strings are really slow. Generation time was on the order of one generation per second or less. Once I converted it all to using objects, generation time dropped to several generations per second. Of course, I then needed another function to be able to see the genome, but that was fine.
However, there is no particular bottleneck in the code that could be substantially re-written, so minor efficiency tweaks are all that matter. I'd like to see that, sounds cool, but it wouldn't make sense if I did. I wonder if I did see it could I make it faster.
It was never the Thing, it was the trip. I have done total re-writes just because it was ugly.
My First Computer -- Documentation Link (RT?M) -- Using the Debugger -- Prime Number Sieve
Counting Bits -- Subnet Calculator -- UI Guidelines -- >> SerialPort Answer <<

"Those who use Application.DoEvents have no idea what it does and those who know what it does never use it." John Wein
I'd like to see that, sounds cool, but it wouldn't make sense if I did. I wonder if I did see it could I make it faster.
It was never the Thing, it was the trip. I have done total re-writes just because it was ugly.
I ported this to .NET simply because .NET was OO.
The code evolves mathematical equations (which are nothing but a string of characters when you write them down) to match a data pattern. It's actually really obvious what it does when you see it, what amazes people is that it can be done. I've presented the program twice, and had the most amazing reactions to it.
However, it's not useful as it stands. Technically, you could put in a whole bunch of stock values, and the factors that you think influence those values, and set it running. It will eventually come up with a model that will predict the behavior of the stock based on the values. However, it will ALWAYS succeed, as far as I can tell. If you put in junk....you will get an answer, and the answer will be better than average. In fact, using the same statistics as linnear regression, it would probably be considered highly significant.
The value doesn't lie in the result, but in a certain population produced right before the result. The similarities between the members of that population probably holds meaning, but figuring out the similarities between N dimensional polynomic equations is more than a little bizarre. I added a module that does some sensitivity testing, and some rough statistics, but a serious analysis may not be automatable. Advertiser Disclosure: Some of the products that appear on this site are from companies from which TechnologyAdvice receives compensation. This compensation may impact how and where products appear on this site including, for example, the order in which they appear. TechnologyAdvice does not include all companies or all types of products available in the marketplace.