Prev: VB 6 & VS?
Next: C:\WINDOWS\system32\ieframe.dll\1
From: Karl E. Peterson on 17 Mar 2010 18:13 Mike Williams wrote: > 12.3 nanoseconds - Jim Mack's DLL as a Public function in module > 9.4 nanoseconds - Compiled VB code using all optimizations > 3.1 nanoseconds - Jim Mack's DLL exposed as a TypeLib > > The results speak for themselves. I tend to consider those numbers suspicious. It's almost incomprehensible to me that the added GetLastError call of the Declare'd function could quadruple the overhead. Am I misunderstanding how you describe that first test? -- ..NET: It's About Trust! http://vfred.mvps.org
From: Karl E. Peterson on 17 Mar 2010 18:25 Jim Mack wrote: > When we had this exact discussion here a couple of years ago, I placed > that function into a DLL, using a Typelib, and others here timed it > against the vbspeed code. I wonder if it might've been this thread? http://groups.google.com/group/microsoft.public.vb.winapi/browse_thread/thread/be07e101f58d0ff8/7a29b0df16095b51 Or whether you're remembering another off-group list discussion? I think that latter one was where I first became aware of Mike's endian swap method. -- ..NET: It's About Trust! http://vfred.mvps.org
From: Tony Toews [MVP] on 17 Mar 2010 19:04 MM <kylix_is(a)yahoo.co.uk> wrote: >>>0.056 microseconds for Nobody's VB method >> >>I sure wish nobody would change their name to somebody. <smile> > >Yeah, but somebody would be just as anonymous. A new moniker entirely, >perhaps? How about "Monica", Nobody? Somebody? Anybody? Actually I was thinking in terms of the classic Abbott and Costello Who's on first routine. Nobody stated .... But somebody said .... Anybody explained.... <smile> Tony -- Tony Toews, Microsoft Access MVP Tony's Main MS Access pages - http://www.granite.ab.ca/accsmstr.htm Tony's Microsoft Access Blog - http://msmvps.com/blogs/access/ For a convenient utility to keep your users FEs and other files updated see http://www.autofeupdater.com/ Granite Fleet Manager http://www.granitefleet.com/
From: Mike Williams on 18 Mar 2010 07:55 "Karl E. Peterson" <karl(a)exmvps.org> wrote in message news:u3QKZ8hxKHA.4752(a)TK2MSFTNGP04.phx.gbl... > Mike Williams wrote: >> 12.3 nanoseconds - Jim Mack's DLL as a Public function in module >> 9.4 nanoseconds - Compiled VB code using all optimizations >> 3.1 nanoseconds - Jim Mack's DLL exposed as a TypeLib >> The results speak for themselves. > > I tend to consider those numbers suspicious. > .. . hmmm. I wonder if it is really me you view as suspicious, or just the numbers ;-) I've just repeated the same tests this morning, in the cold light of day and after a fresh boot up on my 2.4 GHz Q6600 Quad running Vista, and on this machine I'm getting similar results, which are as follows: 10.9 nanoseconds - Jim Mack's DLL as a Public function in module 9.9 nanoseconds - Compiled VB code using all optimizations 3.3 nanoseconds - Jim Mack's DLL exposed as a TypeLib > It's almost incomprehensible to me that the added GetLastError call > of the Declare'd function could quadruple the overhead. Well I've just tried timing a call to GetLastError and I'm getting a time of about 10.8 nanoseconds for that call alone. It's quite probable that using such a call would end up with the system calling GetLastError twice, and if that is the case then GetLastError would be about 5.4 nanoseconds. I'm not sure what GetLastError is actually doing (almost certainly something more than a simple reading of a stored Long) or whether the system does anything else when a declared function is called but a difference of between 6 and 9 nanoseconds does not seem unreasonable. > Am I misunderstanding how you describe that first test? I'm not sure, but I don't think you are. It is just a Private Declare Function to Jim Mack's DLL in the Form's General declarations section (I get very similar resuts if I instead declare it as Public in a Module). The thing is, Jim Mack's machine code is using only a couple of instructions and is very efficient whereas the optimized machine code that the VB compiler comes up with for the specific case of the "vbspeed" VB code will almost certainly be nowhere near as efficient. I'm sure that compilers are extremely good these days, and certainly very much better than they were when I was a lad (;-)), but they are not actually human (well, at least not yet!) and they cannot always analyse your code to see what job you actually want to perform in the way that a human can. Believe it or not I used to be quite good at machine code, but that was more than twenty years ago and I'll admit that I know zilch about machine code on modern processors! The speed difference is real, Karl. I'm not making it up ;-) The differences here are nanoseconds if the routines are called just once, but the percentage difference is very large and they can add up to a signifant saving if such routines are called a very large number of times. And of course if a routine such as Jim Mack's was turned into a routine that accepts a pointer to a couple of arrays and if it reads the data in one array and fills the other with the result of the endian swap (or perhaps fills the existing array with it) then passing such an array to his DLL (whether exposed as a TypeLib or called as a standard declared function or whatever) will result in a time that is orders of magnitude faster than passing the same array to the vbspeed VB code. And I'm sure there will be many other areas that might sometimes crop up where it is possible to hand craft machine code that will beat anything the VB compiler can hope to come up with, and in some cases, especially when working on large blocks of data, it will be much more than a few nanoseconds you will be saving. Such optimizations are not always either necessary or desireable in real word code of course, but all I'm doing here is dealing in the best way I can with the subject of the thread. Anyway, all this talk about machine code and about using it to receive and fill arrays with data and return them is just "thinking on the hoof" about things I don't currently really understand of course because, as I said earlier, it's almost a quarter of a century since I was "into" machine code and I am far to long in the tooth now to start looking into it again now! I just know that I woud get sucked right in and spend half my spare time messing about with it, and I haven't got much time left ;-) For what it's worth, here is the code I used to perform the tests. I make no apologies for the way I do the "copy and paste" stuff, repeating essentially the same thing in three separate places . . that's just the way I work when writing test code in a hurry . . and also no apologies for the lack of indenting (another little idiosyncrasy of mine, especially when I want to avoid possible wrap in newsgroup postings! Anyway, start off by placing Jim Mack's bendian.DLL in your System32 folder (because of a possible problem I'll mention in a minute) and then paste the following code into a VB Form containing three Command Buttons. Then use Project / References / Browse to set a reference to bendian.DLL in your System32 folder. If this reference does not "take" (as sometimes happened with me whether I was using "run as admin" or not) then just save the project as it is and open your .vbp file in NotePad and manually add the following reference and save it: (I've had to manually wrap it because it wrapped in a test posting at a place I didn't want it to, so the following reference should really be on one line (with no space between the curly bracket and the hash sign) Reference=*\G{4BA6BF63-DCA7-4CB0-B337-064710A86382} #1.0#9#bendian.dll#Endian Test DLL Once you get the reference added so that all three functions work okay then compile to a native code exe (using all optimizations if you wish) and check it out. I've tried it now on three different machines at this end and I would be very interested in the results you get there. Mike Option Explicit Private Declare Function timeGetTime _ Lib "winmm.dll" () As Long Private Declare Function timeBeginPeriod _ Lib "winmm.dll" (ByVal uPeriod As Long) As Long Private Declare Function timeEndPeriod _ Lib "winmm.dll" (ByVal uPeriod As Long) As Long Private Declare Function Endian4Declared Lib "bendian.dll" _ Alias "Endian4" (ByVal LongToSwap As Long) As Long Private Sub Form_Load() timeBeginPeriod 1 End Sub Private Sub Form_Unload(Cancel As Integer) timeEndPeriod 1 End Sub Private Function SwapEndian08(ByVal dw As Long) As Long ' http://www.xbeat.net/vbspeed/c_SwapEndian.htm SwapEndian08 = _ (((dw And &HFF000000) \ &H1000000) And &HFF&) Or _ ((dw And &HFF0000) \ &H100&) Or _ ((dw And &HFF00&) * &H100&) Or _ ((dw And &H7F&) * &H1000000) If (dw And &H80&) Then SwapEndian08 = _ SwapEndian08 Or &H80000000 End Function Private Sub Command1_Click() Dim n As Long, p As Long, q As Long Dim t1 As Long, t2 As Long p = &HF1F2F3F4 t1 = timeGetTime For n = 1 To 10000000 q = SwapEndian08(p) Next n t2 = timeGetTime Print "VB code http://www.xbeat.net/vbspeed/c_SwapEndian.htm" Print Hex$(p) & ", " & Hex$(q) & " Time: " _ & Format((t2 - t1) / 10, "0.0") & " nanoseconds" End Sub Private Sub Command2_Click() Dim n As Long, p As Long, q As Long Dim t1 As Long, t2 As Long p = &HF1F2F3F4 t1 = timeGetTime For n = 1 To 10000000 q = Endian4Declared(p) Next n t2 = timeGetTime Print "Jim Mack's DLL declared as a function" Print Hex$(p) & ", " & Hex$(q) & " Time: " _ & Format((t2 - t1) / 10, "0.0") & " nanoseconds" End Sub Private Sub Command3_Click() Dim n As Long, p As Long, q As Long Dim t1 As Long, t2 As Long p = &HF1F2F3F4 t1 = timeGetTime For n = 1 To 10000000 q = Endian4(p) Next n t2 = timeGetTime Print "Jim Mack's DLL exposed in Project / References" Print Hex$(p) & ", " & Hex$(q) & " Time: " _ & Format((t2 - t1) / 10, "0.0") & " nanoseconds" End Sub
From: Mike Williams on 18 Mar 2010 08:26
"Karl E. Peterson" <karl(a)exmvps.org> wrote in message news:u3QKZ8hxKHA.4752(a)TK2MSFTNGP04.phx.gbl... > I tend to consider those numbers suspicious . . . Sometimes I really hate Micro$oft! . . well, most of the time, actually ;-) I initially tried to send my response to your post hours ago and it was rejected by the daft Micro$oft newsgroup filters! The first time I tried to send it I saw the header come into the group when I checked, but it was immediately "struck through" with a line with a report to the effect that there was a problem and that the message "no longer existed on the server". I tried again a number of times, and each time it just did not ever appear, with no further "no longer exists on the server" reports. I check on Google and the first of them had actually got through to Google (the one whose header was struck through at my end), so it would appear that Google grab messages from the MS servers quite regularly and that sometimes they just happen to grab one just before the MS server filter mechanism rejects it as not being "kosher"! This was a quite long message and so I then wasted half my morning sending the usual "binary chop" message portions to Microsoft.public.test.here, and then waiting ages each time just to be sure of what got through and what didn't, in order to determine exactly what part of my quite long message the MS servers were objecting to. It finally turned out to be the word o_c_c_a_s_i_o_n_a_l_l_y which was rejected time after time in any "binary chop" in which it occurred. I replaced the "offending" word with the word "sometimes" and it got through okay. Now that I think about it, I've had MS newsgroup problems with the word o_c_c_a_s_i_o_n_a_l_l_y before, and with other perfectly innocuous words such as s_a_m_p_l_e_s_p_e_r_s_e_c_o_n_d. What a load of cobblers! I really do hate Micro$oft! Mike |