Using Mixed Language Programming
Correctly written Visual Basic code can easily outperform poorly written C code. This is especially true with Visual Basic 6. (Visual Basic 6 native code is faster than p-code.) Whatever language you use, apply the correct algorithm.
At times, of course, you might have to use other languages, say, to gain some required speed advantage. One of the truly great things about Windows (all versions) is that it specifies a linkage mechanism that is defined at the operating system level. In MS-DOS, all linkages were both early and defined by the language vendor. The result was that mixed-language programming was something that only the very brave (or the very foolish) would ever have attempted. It used to be impossible, for example, to get some company's FORTRAN compiler to produce object files that could be linked with other object files generated by another company's C compiler. Neither the linker supplied with the FORTRAN compiler nor the one that came with the C compiler liked the other's object file format. The result was that mixed-language programming was almost impossible to implement. This meant, of course, that tried-and-tested code often had to be ported to another language (so that the entire program was written in one language and therefore linked).
Trouble is that these days we've largely forgotten that mixed language programming is even possible. It is! Any language compiler that can produce DLLs can almost certainly be used to do mixed-language programming. For example, it's now easy to call Microsoft COBOL routines from Visual Basic. Similarly, any language that can be used to create ActiveX components can be used to create code that can be consumed by other, language-independent, processes.
At The Mandelbrot Set (International) Limited (TMS), when we really need speed-and after we've exhausted all the algorithmic alternatives-we turn to the C compiler. We use the existing Visual Basic code as a template for writing the equivalent C code. (We have an internal rule that says we must write everything in Visual Basic first-it's easier, after all.) We then compile and test (profile) this code to see whether the application is now fast enough. If it's not, we optimize the C code. Ultimately, if it's required, we get the C compiler to generate assembly code, complete with comments (/Fc and /FA CL.EXE switches are used to do this), and discard the C code completely. Finally, we hand-tune the assembly code and build it using Microsoft's Macro Assembler 6.11.
Controlling Your Code's Speed
Don't write unnecessarily fast code. What I mean here is that you shouldn't produce fast code when you don't need to-you'll probably be wasting time. Code to the requirement. If it must be fast, take that into account as you code-not after. If it's OK to be slow(er), then again, code to the requirement. For example, you might decide to use nothing but Variants if neither size nor execution speed is important. Such a decision would simplify the code somewhat, possibly improving your delivery schedule. Keep in mind that each project has different requirements: code to them!
Putting On Your Thinking Cap
The best optimizations usually happen when people really think about the problem. I remember once at TMS we had to obtain the sine of some number of degrees many times in a loop. We used Visual Basic's Sin routine to provide this functionality and ultimately built the application and profiled the code. We found that about 90 percent all our recalculating execution time was spent inside the Sin routine. We decided therefore to replace the call to Visual Basic's routine with a call to a DLL function that wrapped the C library routine of the same name. We implemented the DLL, rebuilt, and retested. The results were almost identical. We still spent most of the time inside the Sin routine (although now we had another external dependency to worry about-the DLL!). Next we got out the C library source code for Sin and had a look at how we might optimize it. The routine, coded in an assembly language, required detailed study-this was going to take time! At this point, someone said, "Why don't we just look up the required value in a previously built table?" Brilliant? Yes! Obvious? Of course!
Don't take your eyes off the ball. In the preceding example, we lost our focus. We got stuck in tune mode. We generated the lookup table and built it into the application, and then we rebuilt and retested. The problem had vanished.