Question

Performance improvements for this Q ( follow up question )

Asked by: gecko_au2003

Hi all,

I just wanted to know if there were any improvements that could be made to the coding from my previous question :

http://www.experts-exchange.com/Programming/Programming_Languages/Visual_Basic/Q_21348688.html#13535268

If so what are they and can I please have examples :)

Thank you all !!

This Question has been solved and asker verified All Experts Exchange premium technology solutions are available to subscription members.

Subscribe now for full access to Experts Exchange and get

Instant Access to this Solution

  • Plus...
  • 30 Day FREE access, no risk, no obligation
  • Collaborate with the world's top tech experts
  • Unlimited access to our exclusive solution database
  • Never be left without tech help again

Subscribe Now

Asked On
2005-03-14 at 08:10:42ID21349923
Topic

Visual Basic Programming

Participating Experts
4
Points
500
Comments
53

Trusted by hundreds of thousands everyday for fast, accurate and reliable tech support.

  • "The time we save is the biggest benefit of Experts Exchange to Warner Bros. What could take multiple guys 2 hours or more each to find is accessed in around 15 minutes on Experts Exchange." Mike Kapnisakis, Warner Bros.
  • "Our team likes having a resource that is more secure than just using Google and most experts using this service really know their stuff. It's nice to look here first versus using Google." Dayna Sellner, Lockheed Martin
  • "Anytime that I've been stumped with a problem, 9 out of 10 times Experts Exchange has either the accepted solution or an open discussion of the potential solution to the problem." Kenny Red, eBay Inc.

See what Experts Exchange can do for you.

Got a question?

We've got the answer.

Experts Exchange has been collecting answers to technology questions since 1996…3 million and counting! If you have a question, chances are we already have your answer.

Screenshot of Experts Exchange Knowledgebase

Need individual assistance?

Our experts are ready to help.

If you can't find the exact answer you're looking for, ask our exclusive community of 50,000 experts. You’ll get a personalized answer from a trusted professional.

Screenshot of Experts Exchange Knowledgebase

Want to learn from the best?

Read articles from industry experts.

Thousands of free tech tips, tricks, how-to’s and tutorials are available in our peer reviewed articles section. See for yourself how smart our experts are, no login required.

Screenshot of an Article

Working on a long term project?

Store your work and research.

Save solutions to your questions, answers you’ve discovered through searching plus helpful articles in your personal knowledgebase for easy future access.

Screenshot of Experts Exchange Knowledgebase

Access the answers to your technology questions today.

Subscribe Now

30-day free trial. Register in 60 seconds.

What Makes Experts Exchange Unique?

Members of the expert community talk about why the experience at Experts Exchange is different than what you will find anywhere else.

Trusted by the world's most respected brands.

image of each brand's logo

Faithfully serving IT professionals since 1996.

Experts Exchange Logo

Try it out and discover for yourself.

Subscribe Now

30-day free trial. Register in 60 seconds.

Related Solutions

  1. Improvements
    <HTML> <HEAD> <!-- Created with AOLpress/2.0 --> </HEAD> <BODY BGCOLOR="#00ff40" LINK="#0000ff" VLINK="#0000ff"> <P ALIGN=Center> <FONT COLOR="Blue"></FONT><BIG><BIG>Welcome ...
  2. Possible Performance Improvements
    I am currently using the code below. The performance is very slow and I am looking for suggestions on how to improve it. This application is currently being used to process between 100 meg and 2 gig of data. Thank you very much for your time and expertise, Gr8life Imports...

Free Tech Articles

  1. WARNING: 5 Reasons why you should NEVER fix a computer for free.
    It is in our nature to love the puzzle. We are obsessed. The lot of us. We love puzzles. We love the challenge. We thrive on finding the answer. We hate disarray. It bothers us deep in our soul. W...
  2. SCCM OSD Basic troubleshooting
    SCCM 2007 OSD is a fantastic way to deploy operating systems, however, like most things SCCM issues can sometimes be difficult to resolve due to the sheer volume of logs to sift through and the dispe...
  3. Migrate Small Business Server 2003 to Exchange 2010 and Windows 2008 R2
    This guide is intended to provide step by step instructions on how to migrate from Small Business Server 2003 to Windows 2008 R2 with Exchange 2010. For this migration to work you will need the fo...
  4. Create a Win7 Gadget
    This article shows you how to create a simple "Gadget" -- a sort of mini-application supported by Windows 7 and Vista. Gadgets can be dropped anywhere on the desktop to provide instant information, ...
  5. Outlook continually prompting for username and password
    There have been a lot of questions recently regarding Outlook prompting for a username and password whilst using Exchange 2007. There are a few reasons why this would happen and I will try to cover t...
  6. Backup Exchange 2010 Information Store using Windows Backup
    There seems to be quite a lot of confusion around the ability to backup Exchange 2010 using the built in Windows Backup feature. This stems from the omission of this feature prior to Exchange 2007 s...

Cloud Class Webinars

  1. Avoiding Bugs in Microsoft Access
    Alison Balter takes and in-depth look at avoiding bugs in Access. In this webinar you will learn about using the immediate window to debug your applications, invoking the debugger, using breakpoints to troubleshoot, stepping through code, setting the next statement to execute, ...
  2. Top 10 Best New Features in Visio 2010
    Scott Helmers gives live demonstrations of the top 10 new features in Visio 2010. This webinar will teach you how to create compelling diagrams by adding shapes to the page with a single click, linking the shapes in a diagram to data in Excel (or SQL Server, or SharePoint), ...
  3. IT Consultant Business Secrets Revealed
    Michael Munger, Experts Exchange tech pro and IT consultant, pulls back the curtain on his very successful businesses and answers question on every IT consultant and business owner should know about. He shares secrets on what he did to solve the 5 most common problems in IT, ...
  4. Disaster Recovery and Business Continuity
    Quest CTO, Mike Billon, gives an overview of the steps involved in building a dunamic disaster recovery plan. Through case studies and an examination of software/hardware tooles for monitoring and testing, you'll gain a better understandin of where you are, where you want ...
  5. Organize Your Visio Diagrams with Containers and Lists
    Scott Helmers uses cross functional flowcharts, wireframe diagrams, data graphic legends and seating charts to teach you: how to ustilize all three new structured diagram components in Visio 2010, the best practices for organizeing shapes in previous version of Visio, how to organize ...
  6. How to Us Objects, Properties, Events and Methods in Microsoft Access
    Alison Dalter gives an in-depbth look at objects, properties, events and methods in Microsoft Access. In this webinar you will learn about using the object browser, referring to objects, working with properties and methods, working with object variables, understanding the ...

Join the Community

Give a Little. Get a Lot.

Join the community of experts here and help other tech pros by answering question in your area of expertise. You can earn FREE access to all Experts Exchange's premium features and resources.

Join the Community

Answers

 

by: aikimarkPosted on 2005-03-14 at 08:40:11ID: 13536389

There are a few things to address.  Here's an overview of performance enhancements:
1. minimize operations
2. use the most efficient operators
3. take advantage of as many 'tricks' as possible
4. take advantage of VB language features
5. consider Windows APIs as alternatives to VB functions/statements

=========================
Before I show code examples I need to know if the string length is guaranteed to be a multiple of 8 or if the leading zero characters ("0") might have been removed.

 

by: PaulHewsPosted on 2005-03-14 at 08:56:42ID: 13536563

This will be pretty fast.  I'm sure it can be optimized further:

Private Function BinToStr(bin As String) As String
   
    Dim i As Long, Count As Long
    Dim strCompare(1) As String
    Dim b() As Byte
    ReDim b(0 To Len(bin) / 8 - 1)
   
    Debug.Assert Len(bin) Mod 8 = 0
   
    Dim strNibble As String
    strNibble = "0000-0001-0010-0011-0100-0101-0110-0111-" & _
                        "1000-1001-1010-1011-1100-1101-1110-1111-"
                       
    For i = 1 To Len(bin) - 7 Step 8
        strCompare(0) = Mid$(bin, i, 4)
        strCompare(1) = Mid$(bin, i + 4, 4)
        b(Count) = (InStr(1, strNibble, strCompare(0) & "-") - 1) / 5 * 16 + (InStr(1, strNibble, strCompare(1) & "-") - 1) / 5
        Count = Count + 1
    Next i
       
    BinToStr = StrConv(b, vbUnicode)
                       
End Function

 

by: aikimarkPosted on 2005-03-14 at 09:15:26ID: 13536750

Paul,

* Very good start.
* two Nibbles/pass => byte/pass => character/pass
* single operation to convert byte array back into string
* clever use of the Instr() function as a table lookup

 

by: gecko_au2003Posted on 2005-03-14 at 09:29:25ID: 13536881

You said "Before I show code examples I need to know if the string length is guaranteed to be a multiple of 8 or if the leading zero characters ("0") might have been removed."

Would you be able to do an example of each ie that they are multiple of 8, and have zero characters ("0") and then the same but without the zero characters ("0") and then the same again but with another multiple ie 7 , basically something that is valid with regards to binary.

Just curious how it is done with and without ("0")'s and also using a different multiple :)

Thanks all !

 

by: aikimarkPosted on 2005-03-14 at 09:42:19ID: 13536998

gecko_au2003,

The only difference is a check of the length and prepending (concatenation) of a string of "0" characters to make the string length a multiple of 8.  All the processing code needs to have enough characters to construct 8-bit bytes.

 

by: PaulHewsPosted on 2005-03-14 at 09:44:50ID: 13537021

Removing padding is a simple operation.

    If Len(bin) Mod 8 <> 0 Then
        bin = Right$(bin, 8 * (Len(bin) \ 8))
    End If

But I would have to redim my byte array after this operation... :)

7 bit could be done by adjusting the length of strcompare(0) and prefix it with "0" before comparing.  Of course the For ... Next statement has to be adjusted accordingly so that it steps through the bin string in groups of 7 instead of 8.

I don't have any test data, so I don't think I'll bother coding that out.

Frankly both requests are minor but I don't see what they have to do with the original question which was about optimization.

 

by: mgh_mgharishPosted on 2005-03-14 at 09:52:14ID: 13537095

Hi gecko, I would have given you the shortest possible code... but if the string contains number of characters which is not a multiple of 8, then the code will give an error.

This much is suffecient for conversion... but the code in the previous one is the best one. :)

Private Sub Form_Load()
On Error Resume Next
    Dim s As String           'Declare a variable for storing the given string
    Dim a As String           'Declare a variable for output string
    'Store the string
    s = "010010010010000001110011011100000110010101101110011101000010000000100100001
1000100110000001100000010000001100001011101000010000001010100011010000110100101101
1100110101101000111011001010110010101101011001000000110000101101110011001000010000
00110000101101100011011000010000001001001001000000110011101101111011101000010000001
11011101100001011100110010000001110100011010000110100101110011001000000110110001101
111011101010111001101111001001000000110110001101001011011010110100101110100011001010
110010000100000011001010110010001101001011101000110100101101111011011100010000001110
10000101101011100110110100001101001011100100111010000101110"

    While s <> ""        ' Loop until the string is empty
    'Take 8 digits from left and convert that to decimal and then to ascii.
        a = a & Chr(ToDec(Left(s, 8)))    
    'Remove the already converted digits    
        s = Right(s, Len(s) - 8)
    Wend
    'Show the output through a message box
    MsgBox a
End Sub

Private Function ToDec(ByVal bin As String) As Long
On Error Resume Next
    For i = 1 To Len(bin)         'Loop through the characters
        ToDec = ToDec + Mid(bin, i, 1) * (2 ^ (8 - i))       'Find the decimal value using binary weights
    Next
End Function

 

by: Idle_MindPosted on 2005-03-14 at 10:01:13ID: 13537180

Anyone want to analyze if this is faster?  I first build a table of binary to decimal conversions and place it into a collection.  Then we can convert the binary strings to decimal values using a fast key lookup.

I suppose if you are doing a very large string (like from a file) then the time spent making the table will offset the math operations in the previous solutins?...

Option Explicit

Private BinToDec As New Collection

Private Sub Form_Load()
    Dim bin() As String
    Dim dec As Integer
    Dim i As Integer
   
    ReDim bin(7)
    For dec = 0 To 7
        bin(dec) = "0"
    Next dec
    For dec = 0 To 255
        Debug.Print dec & ": " & Join(bin, "")
        BinToDec.Add dec, Join(bin, "")
        Select Case bin(7)
            Case "0"
                bin(7) = "1"
               
            Case "1"
                bin(7) = "0"
                i = 6
                While i > 0 And bin(i) = "1"
                    bin(i) = "0"
                    i = i - 1
                Wend
                bin(i) = "1"
        End Select
    Next dec
End Sub

Private Function BinToStr(binary As String) As String
    Dim i As Long, Count As Long
    Dim b() As Byte
    ReDim b(0 To Len(binary) / 8 - 1)
                             
    For i = 1 To Len(binary) - 7 Step 8
        b(Count) = BinToDec(Mid(binary, i, 8))
        Count = Count + 1
    Next i
       
    BinToStr = StrConv(b, vbUnicode)
End Function

Private Sub Command1_Click()
    MsgBox BinToStr("01001001001000000111001101110000011001010110111001110100001000000010010
00011000100110000001100000010000001100001011101000010000001010100011010000110100101101110
01101011010001110110010101100101011010110010000001100001011011100110010000100000011000010
11011000110110000100000010010010010000001100111011011110111010000100000011101110110000101
110011001000000111010001101000011010010111001100100000011011000110111101110101011100110111
100100100000011011000110100101101101011010010111010001100101011001000010000001100101011001
0001101001011101000110100101101111011011100010000001110100001011010111001101101000011010010
11100100111010000101110")
End Sub

 

by: gecko_au2003Posted on 2005-03-14 at 10:10:48ID: 13537248

I loved Idle_Minds method of using a lookup table for the conversion !! However PaulHews example of removing padding was great ! Thank you all !!

 

by: mgh_mgharishPosted on 2005-03-14 at 10:12:07ID: 13537257

IdleMind, that may work faster, but I feel that takes much memory. So I feel it is not a good idea to use collection.

 

by: aikimarkPosted on 2005-03-14 at 10:22:21ID: 13537331

mgh_mgharish,

Unfortunately, your solution is very similar to those in the original question
and suffers from
* bit-at-a-time processing
* character-at-a-time concatenation
* operation reduncancy (recalculation of same values)
* large character string operations

<<...but the code in the previous one is the best one>>
This question was my idea.
I'm looking for performance improvement suggestions.

=================================
gecko_au2003,

Let's stick with 8 bit characters and realize that things can be done in other
groupings of binary digits...Which reminds me of an appropriate geeky riddle:


Q: Why is Halloween like Christmas?

A: Because Oct 31 = Dec 25

 

by: mgh_mgharishPosted on 2005-03-14 at 10:31:00ID: 13537412

Yes.. of course..

>Unfortunately, your solution is very similar to those in the original question.
It is the original solution itself with For Loop removed.

When you are making a converter, I feel memory is one which should be taken care of, along with time, which is the most important one. Idle_Mind's solution will give the fastest running code, but lags in memory usage.

 

by: PaulHewsPosted on 2005-03-14 at 10:48:14ID: 13537567

Idle_Mind's is faster than mine by about 30%  Times in seconds for 10K iterations.

Mine 2.261719
IdleMind's 1.722656

> IdleMind, that may work faster, but I feel that takes much memory. So I feel it is not a good idea to use collection.

mgh_mgharish how much memory does it take up?  Not counting collection and string overhead,
256 strings * 16 bytes (8 chars unicode) for the key and 256 * 16 bytes (integer) for the values = 8K
By my reckoning, not a lot on systems with hundreds of megabytes of memory...
Of course it depends on the application.
It adds a little bit of work for a one time load (which doesn't have to be done on form_load, one could test if the
collection is nothing and then initialize it.)

Personally I think it's a great optimization.

 

by: PaulHewsPosted on 2005-03-14 at 10:49:06ID: 13537577

Memory is often sacrificed for performance.  That's the whole idea of using a lookup table...

 

by: aikimarkPosted on 2005-03-14 at 10:52:08ID: 13537600

Idle_Mind,

Very good.
* precalculate 256 table values for lookup
* use built-in hashing of collection for conversion
* byte-at-a-time processing
* single operation to convert back to string
* space/time tradeoff for performance

I'm not sure how much overhead a collection consumes in additional
memory per added item.  Also, I don't know if we might improve on
the collection hashing algorithm with a version of our own. (mod 256)
In order to compare, we'd need to run these top two contenders
through some iterations with different length strings.  You are correct
to state that the initial overhead of creating the collection lookup table
diminishes the more conversion is done, either longer strings or repeated
conversions of different strings.

 

by: aikimarkPosted on 2005-03-14 at 10:58:42ID: 13537658

Paul & Idle,

I must say that your responses were what I was expecting... clever and fast.

In fact, this has been a very rapid discussion thread.  I'm sad it ended so quickly.
We contributed much in just under 2 hours.  I didn't even submit any code because
your contributions were QUITE good enough.  Thank you.

and, lastly, thanks to gecko for posting the question and offering the points.

 

by: Idle_MindPosted on 2005-03-14 at 11:00:56ID: 13537688

Definite kudos to PaulHews for the use of StrConv() to convert the byte array to a string.
That alone is a huge improvement over concatenating strings using the typical x = x & y approach.

Need to remember to use StrConv() more often...

 

by: Idle_MindPosted on 2005-03-14 at 11:02:16ID: 13537700

I agree...thanx gecko for posting an interesting question.

It gets boring answering variations of the same basic questions over and over and over...   =)

 

by: Idle_MindPosted on 2005-03-14 at 11:08:26ID: 13537760

mgh_mgharish,

I suppose that in certain embedded systems with very little memory a lookup table might not the best choice.

Of course, in most embedded systems with few resources we don't use BASIC do we?

It all depends on your target system and requirements...

 

by: mgh_mgharishPosted on 2005-03-14 at 11:12:09ID: 13537792

Yes.. Thanks

 

by: aikimarkPosted on 2005-03-14 at 11:29:07ID: 13537973

(for posterity) Here's what I was thinking...

* build (0 to 1, 0 to 4369) lookup byte array.  
  This array is mostly sparse except for 16 positions corresponding
  to the possible nibble configurations (in hex).  The 16 significant
  positions will be equal to the low order and high order nibble values.
  &h00, &h10, &h20, &h30, &h40, &h50, &h60, &h70, etc.
  &h00, &h01, &h02, &h03, &h04, &h05, &h06, &h07, etc.
* use strconv() to convert the entire unicode string into a byte array
* use memory copy Windows API function to copy 8 bytes
  into a structure of two long integer variables
* xor the two long integer values with 1212696648 (&h48484848).
  This converts the two possible ASCII values, chr(48)="0" and chr(49)="1",
  into four 00 or 01 bytes.
* use the values in the two long integers to index into the
  lookup byte array.  No hashing required.
* the two lookup nibble values are ORed to create the byte value for the character.
* the strconv() function is used to create a unicode string

I use the most memory (8738 bytes) for my lookup table.  But my lookup table
can be generated in 16 iterations.

======================================
Note: I'm padding strings with "0" characters to make them a multiple of 8 characters,
rather than trimming to a length of 8.  I'm not sure I was clear on that earlier.

 

by: aikimarkPosted on 2005-03-14 at 12:03:23ID: 13538289

Paul & Idle & gecko,

What do you think?  I opined about your code.  Now it's your turn :-)

It is possible to only use one dimension of the lookup table and shift
the bits of the high order nibble by * 16.  It would cut my lookup table
memory requirement in half and only add one integer operation.

 

by: aikimarkPosted on 2005-03-14 at 12:45:58ID: 13538729

oops!

I should have done my coding before I posted my comment. :-(

My lookup table would need to be 16MB big :-o

I could still do the character construction with the lookup table
I originally proposed and index with
the nibbles converted to numeric values through a VB trick:
"&h" & Mid(inputstring,i,4) and "&h" & Mid(inputstring,i+4,4)
produce an acceptable range of nibble index values.

 

by: PaulHewsPosted on 2005-03-14 at 12:56:26ID: 13538861

I was just reading it.  I like the xor to return the 0/1 bytes.  Using that technique, a calculated
method (with a tiny lookup table for powers of two) performs almost as well as Idle_Mind's proposal.  With
the lookup table you describe, it should rip even faster than Idle_Mind's.  When you post the code, I'll test them side by side.

Including code for a new calculated method that uses your xor idea.

Private Function BinToStr3(bin As String) As String
    'new calculated method
    Dim i As Long, j As Long, Count As Long
    Dim strCompare As String
    Dim bytIn() As Byte
    Dim b() As Byte
    Dim bytOut() As Byte
    Static Power(7) As Byte
   
    'One time initialization
    If Power(7) <> 128 Then
        For i = 0 To 7
            Power(i) = 2 ^ i
        Next
    End If
   
    If Len(bin) Mod 8 <> 0 Then
        bin = Right$(bin, 8 * (Len(bin) \ 8))
    End If
   
    bytIn = StrConv(bin, vbFromUnicode)
    ReDim b(UBound(bytIn))
    ReDim bytOut(0 To Len(bin) / 8 - 1)
   
   
   For i = 0 To Len(bin) - 8 Step 8
        For j = 0 To 7
            If bytIn(i + j) Xor 48 Then
                bytOut(Count) = bytOut(Count) + Power(7 - j)
            End If
        Next j
        Count = Count + 1
   Next i
   
    BinToStr3 = StrConv(bytOut, vbUnicode)
   
End Function

Results:
My Original 2.273438
Xor 1.792969
Idle_Mind's 1.710938


 

by: gecko_au2003Posted on 2005-03-14 at 13:01:48ID: 13538921

I have never seen anything or done anything with regards to binary or decoding it or anything like that programitically. Personally I am learning a lot myself and the only reason I asked the 2 questions I did with binary was because of the question I came across that was asked to decode the binary which gave that message with regards to the lousy t shirt or w/e that message gave lol.
With regards to asking a question that was different and not variants of simmilliar questions, your welcome. I love learning new things and I guess I am attention defacet to some degree with regards to I dont like going over the same things more then a certain amount of times, especially once I understand how it is done. I think all this binary stuff will take quite some time for me to absorb and understand.
I wont be going through it straight away because of some personal things I am sorting out at this point in time :)

I have done a little bit of c++, java, java script, vbscript amongst other things and still have a lot to learn. Eventually I plan on getting books with regards to a lot of programming languages and learning them, not sure If I already mentioned this or not but that is my intentions with regards to programming along with most likely going on course(s) as well :)

I am just wondering if there as an easier, less straining way of doing this binary decoding that uses the least amount of memory / resources. Only reason I ask this is because If you have ever come across those 64k graphics demos that do extra ordinary graphics especially for the size of them, then you will know what I am talking about. If not then go to this url and try one or more of them out :

http://www.theprodukkt.com/demoscene.html

^^^ Who ever makes them little programs to do all them graphics, audio , etc is extremely and highly experienced in programming as far as I can tell :)

I thought they were really cool !

 

by: aikimarkPosted on 2005-03-14 at 13:24:43ID: 13539135

Paul,

Thanks for doing the testing.  It helps to have independent verification.

The reason for copying the input parameter to a local variable is that this seems
to run faster than referencing the parameter.  This may have something to do
with heap use and access.  You are welcome to test it both ways (strTemp and bin)

==================================
Option Explicit

Dim LookupTable(0 To &H1111) As Byte

Private Sub Form_Load()
    'LookupTable(&H0) = 0   'not necessary
    'initialize the single dimension lookup table
    'with nibble configurations
       LookupTable(&H1) = 1
      LookupTable(&H10) = 2
      LookupTable(&H11) = 3
     LookupTable(&H100) = 4
     LookupTable(&H101) = 5
     LookupTable(&H110) = 6
     LookupTable(&H111) = 7
    LookupTable(&H1000) = 8
    LookupTable(&H1001) = 9
    LookupTable(&H1010) = 10
    LookupTable(&H1011) = 11
    LookupTable(&H1100) = 12
    LookupTable(&H1101) = 13
    LookupTable(&H1110) = 14
    LookupTable(&H1111) = 15

    Debug.Print BinToStr("010010010010000001110011011100000110010101101110011101000010000000100100001
1000100110000001100000010000001100001011101000010000001010100011010000110100101101110011010110100
01110110010101100101011010110010000001100001011011100110010000100000011000010110110001101100
001000000100100100100000011001110110111101110100001000000111011101100001011100110010000001110
100011010000110100101110011001000000110110001101111011101010111001101111001001000000110110001
101001011011010110100101110100011001010110010000100000011001010110010001101001011101000110100
10110111101101110001000000111010000101101011100110110100001101001011100100111010000101110")

End Sub


Private Function BinToStr(bin As String) As String
    'code borrowed from PaulHews and modified for test
    Dim lngLoop As Long
    Dim Count As Long
    Dim strTemp As String
    Dim bytResult() As Byte
    ReDim b(0 To Len(bin) / 8 - 1)
    strTemp = bin
   
    For lngLoop = 1 To Len(bin) - 7 Step 8
        bytResult(Count) = LookupTable("&h" & Mid$(strTemp, lngLoop, 4)) * 16 + LookupTable("&h" & Mid$(strTemp, lngLoop + 4, 4))
        Count = Count + 1
    Next lngLoop
       
    BinToStr = StrConv(bytResult, vbUnicode)
                       
End Function

 

by: aikimarkPosted on 2005-03-14 at 13:46:28ID: 13539335

Paul,

Some comments and suggestions on your latest code offering:
1. move all the initialization and adjustment checks outside of the
conversion function, most likely to Form_Load.  I know this isn't
standard practice, but I'm trying to squeeze the most performance
out of our code suggestions.  There'll be two*10000 less If statements
executed.

'One time initialization
If Power(7) <> 128 Then

If Len(bin) Mod 8 <> 0 Then

2. replace the If inside the loop with a calculation.
For example, replace
If bytIn(i + j) Xor 48 Then
   bytOut(Count) = bytOut(Count) + Power(7 - j)
End If

with
bytOut(Count) = bytOut(Count) + (bytIn(i + j) Xor 48 ) * Power(7 - j)

3. Use an Integer or Long Integer variable (not part of an array to
store the intermediate power-of-two values.  Referencing the bytOut
array twice per loop can cost you.  After you've finished looping, assign
the sum to the bytOut(Count) position.

4. Set the innermost loop to values that eliminate subsequent addition

5. (optional) You might want to explore any difference it makes to use a byte/integer/Long
variable = 48 to do the XOR rather than the numeric literal.  Performance isn't
always better, but sometimes it is.

Example:

Dim lngSum as Long
Dim intPower as Integer

For i = 0 To Len(bin) - 8 Step 8
  lngSum = 0
  intPower = 7
  For j = i To (i+7)
    lngSum = lngSum + (bytIn(j) Xor 48) * Power(intPower)
    intPower = intPower -1
  Next j
 
  bytOut(Count) = lngSum

Next i

 

by: PaulHewsPosted on 2005-03-14 at 13:56:32ID: 13539441

Actually, it comes up about 3 hundredths of a second faster when I don't copy to strTemp... at least on my system.  ..Which
makes sense to me logically as well.  The array lookup is also the fastest, which makes sense as well, although I have to say that I
wouldn't have necessarily guessed that the conversion from "&hxxxx" string to integer wouldn't slow you down some.  :)

Instr lookup 2.28125
Xor 1.8125
collection lookup 1.710938
array lookup 1.253906    

 

by: Idle_MindPosted on 2005-03-14 at 14:00:56ID: 13539495

Lol...can we squeeze any more speed out of it?

Definitely some nice code.

I must say I would never have thought of or used the nibble approach myself...

Still trying to digest it... nibble, nibble, byte...

 

by: aikimarkPosted on 2005-03-14 at 14:01:26ID: 13539502

Paul,

Maybe you can use the tweaks I suggested to your code and beat my time.

Off to the races. :-)

 

by: aikimarkPosted on 2005-03-14 at 14:14:58ID: 13539647

Paul & Idle,

Want to see something REALLY SCARY/HAIRY?
If so, do a Google search for Q_20908880

I tackled an NP-Complete problem.  One of the techniques I used
was a direct table lookup in a sparse array.  Of course the arrays
for that problem solution were MUCH bigger than the 4369 bytes
I'm using for the LookupTable array.

Be prepared for a lengthy discussion thread and as many tricks as
I could use.  I've done a few presentations locally on the
NP-Complete Problem/Solution (case study).

========================================
If you look at the NPR stories on today's Morning Edition program,
you will see a link to a Don Knuth interview.  It's so rare to hear/see
any Comp Sci people interviewed in a non-technical media.

 

by: Idle_MindPosted on 2005-03-14 at 14:55:19ID: 13539986

Interesting fellow...that Don Knuth:
http://www.npr.org/templates/story/story.php?storyId=4532247

aikimark,

In your profile it says you were a "Software Instructor".  I someday want to teach computer science myself.  =)

Where/how did you teach and do you have any recommendations on how to get there (teaching computer science)?

 

by: aikimarkPosted on 2005-03-14 at 15:14:42ID: 13540141

Idle,

I have done far more mundane teaching than Computer Science teaching.  I teach
in corporate settings, so most topics are practical and skills rather than academic
and theoretical.

If you want to teach, then do the following:
* volunteer to teach some free courses at community centers and churches
* get a good reference or three
* offer to mentor beginners
* participate in local user groups by giving presentations and leading SIGs
* develop some training materials for formal classes (books and sample files)
* begin to network with other trainers (ASTD user groups)
* contact community colleges about teaching
* if you want to do a lot of training, join a training/consulting organization or
  hire someone to find work for you (training sales person).

 

by: PaulHewsPosted on 2005-03-14 at 15:33:03ID: 13540259

I made a mistake in timing all these in the IDE instead of compiling and testing that way...  Sometimes it doesn't
make much difference, but in this case, there was a huge difference in performance between the IDE
pseudocode and the compiled code... Well at least I did eventually think to compile it... :)

InstrLookup            1.7813
XorCalc                  0.2031
XorCalcStatic          0.1953
XorCalc2                0.1719
CollectionLookup     1.5000
ArrayLookup           0.9766

The InstrLookup and CollectionLookup are the losers; almost an order of magnitude slower.  The various XorCalc methods are pretty close.  
The optimizations you suggested work for the compiled code, although they slow things down in the IDE...

It proves what we should have known...  That byte arrays rule over any kind of string handling.  (I figure that the implicit string>integer
conversion is what slows down the ArrayLookup.)

The test code has been posted to my website:
http://www11.brinkster.com/notbono/programs.asp

Scroll down to Binary to String to download a zip file with the project and compiled executable.



 

by: gecko_au2003Posted on 2005-03-14 at 16:40:24ID: 13540643

Hi aikimark , I dont know if this is against EE rules or not however If it is ok with you and the EE rules, is there anyway you could send me an email ? Also I wanted to know since you were a software instructor and did other things as well, I was wondering if you had any contstructive or useful advice you could give me for learning programming, any resources you would recomend with regards to programming whether it be websites or books or pdf files ? I am extremely enthusiastic to learn programming and since you seem to know your stuff and have been a software instructor, etc. I would very much appreciate any info you could give me :)

Thank you so much

Kind regards

Gecko

P.S I am really glad I asked this question now because it seems to be one of the questions that I have asked that has taught me quite a bit as well as being interesting to participate in :)

Gotta love being a part of EE when you get questions like these huh lol.

Idle_Mind - I am just curious where you learnt and have learned all the stuff you know or any suggestions / reccomendations you could make to me as well with regards to what I asked aikimar above.

 

by: aikimarkPosted on 2005-03-14 at 17:38:03ID: 13541029

Paul,

Wonderful testing example.  Thanks.
If I'd been able to do what I wanted to do within a reasonably sized lookup array,
I might have been on par with the XorCalc___ versions.  Good catch with the
Compiled vs. IDE/debug environments.

Also, you might be tempted to tweak the compile options, but the only one that
seems to matter is the Favor Pentium Pro.  Others can actually slow the execution.

===============================
Here is about the closest variation on my original idea that I can create.  It does not
use a lookup table, but rather creates the byte as a direct construction.  It is the
second fastest (behind XorCalc2) on my PC.  Although not the fastest, it does contain
many tricks that can be used to speed up code.  Please add it to the code on your
web site.  Some notes as you read this:
1. CopyMemory allows me to grab 8 bytes of the byte array at a time
2. The dbl_struc structure permits me to have multiple long integer variables
as the target of the CopyMemory subroutine.
3. If I created a long integer array, I could move the entire bytearray with one
CopyMemory call.  I didn't do that this time.
4. The ntohl function is required, since Windows/Intel is a little-endian environment
and I need to preserve the byte order you would see if you did a Hex() function on
the long integers.
5. I had some trouble with the hexmask until I realized that &h30 = 48 ... duh!

* * * CORRECTION TO EARLIER COMMENT * * *
03/14/2005 11:29AM PST comment should read:
  into a structure of two long integer variables
* xor the two long integer values with 808464432 (&h30303030).
  This converts the two possible ASCII values, chr(48)="0" and chr(49)="1",
  into four 00 or 01 bytes.
* use the values in the two long integers to index into the

6. I tried a couple of different ways of directly constructing the bytes.  I've left the
trials in the code below commented out.  The changes made no difference in
performance.
  - I tried using two separate long integer variables instead of the structure variable.  
  - I tried using the XOR function as an alternative to addition

7. Constructing the byte requires 8 AND masks, 8 equality comparisons, and 8 multiplication
operations.  Since the (Windows) True boolean value is -1, I multiplied by the negative of
the number I really wanted.  By combining all of these operations in one statement
I do not encur the overhead of looping.

8. I had to widen the listbox in your sample project and I set the default property of the
command button = True.  This allows me to move the mouse completely off the form and
still launch the test driver code.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'In the General Declarations section of a new module
Type dbl_struc
    High4 As Long
    Low4 As Long
End Type

'In the General Declarations section of the form
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (dest As Any, _
    source As Any, ByVal bytes As Long)

Private Declare Function ntohl Lib "wsock32.dll" (ByVal a As Long) As Long
Private DblLong As dbl_struc
Const hexmask As Long = &H30303030


Public Function DirectConstruction1(bin As String) As String
    Dim lngLoop As Long
    Dim Count As Long
    Dim bytChars() As Byte

'    Dim lngHigh As Long
'    Dim lngLow As Long
   
    Dim bytResult() As Byte
    ReDim bytResult(0 To Len(bin) / 8 - 1)

    bytChars = StrConv(bin, vbFromUnicode)
   
    For lngLoop = 1 To Len(bin) - 7 Step 8
        CopyMemory DblLong, bytChars(lngLoop - 1), 8
        DblLong.High4 = ntohl(DblLong.High4) Xor hexmask
        DblLong.Low4 = ntohl(DblLong.Low4) Xor hexmask
'        lngHigh = ntohl(DblLong.High4) Xor hexmask
'        lngLow = ntohl(DblLong.Low4) Xor hexmask
       
        bytResult(Count) = (((DblLong.High4 And &H1000000) = &H1000000) * -&H80) + (((DblLong.High4 And &H10000) = &H10000) * -&H40) + (((DblLong.High4 And &H100) = &H100) * -&H20) + (((DblLong.High4 And 1) = 1) * -&H10) _
                + (((DblLong.Low4 And &H1000000) = &H1000000) * -&H8) + (((DblLong.Low4 And &H10000) = &H10000) * -&H4) + (((DblLong.Low4 And &H100) = &H100) * -&H2) + (((DblLong.Low4 And 1) = 1) * -&H1)

' = = = = = = = = = = = = = = = =
' = = = = Following Not Used = = = =        
'        bytResult(Count) = (((lngHigh And &H1000000) = &H1000000) * -&H80) + (((lngHigh And &H10000) = &H10000) * -&H40) + (((lngHigh And &H100) = &H100) * -&H20) + (((lngHigh And 1) = 1) * -&H10) _
'                + (((lngLow And &H1000000) = &H1000000) * -&H8) + (((lngLow And &H10000) = &H10000) * -&H4) + (((lngLow And &H100) = &H100) * -&H2) + (((lngLow And 1) = 1) * -&H1)
               
'        bytResult(Count) = (((lngHigh And &H1000000) = &H1000000) * -&H80) Xor (((lngHigh And &H10000) = &H10000) * -&H40) Xor (((lngHigh And &H100) = &H100) * -&H20) Xor (((lngHigh And 1) = 1) * -&H10) _
'                Xor (((lngLow And &H1000000) = &H1000000) * -&H8) Xor (((lngLow And &H10000) = &H10000) * -&H4) Xor (((lngLow And &H100) = &H100) * -&H2) Xor (((lngLow And 1) = 1) * -&H1)
' = = = = Preceding Not Used = = = =        
' = = = = = = = = = = = = = = = =
       
        Count = Count + 1
    Next lngLoop
       
    DirectConstruction1 = StrConv(bytResult, vbUnicode)

End Function

 

by: PaulHewsPosted on 2005-03-14 at 17:48:37ID: 13541085

aikimark, can you email me the changed test project?  That way I'll dump it on my site.  Just use the email address on my home page.

 

by: aikimarkPosted on 2005-03-14 at 17:56:56ID: 13541120

...and in case anyone is wondering it is also possible to substitute integer division for
the equality check in the byte construction statement:

        bytResult(Count) = (((DblLong.High4 And &H1000000) \ &H1000000) * &H80) + (((DblLong.High4 And &H10000) \ &H10000) * &H40) + (((DblLong.High4 And &H100) \ &H100) * &H20) + (((DblLong.High4 And 1) \ 1) * &H10) _
                + (((DblLong.Low4 And &H1000000) \ &H1000000) * &H8) + (((DblLong.Low4 And &H10000) \ &H10000) * &H4) + (((DblLong.Low4 And &H100) \ &H100) * &H2) + (((DblLong.Low4 And 1) \ 1) * &H1)


But division doesn't noticably change the performance of the routine relative to XorCalc2.

The problem with taking the lead is my need to address each of the 8 bytes and not being
able to use a lookup table that isn't millions of bytes big.  If I could reduce the number of
calculations I perform in the byte construction statement, I could get close to XorCalc2
performance.

 

by: aikimarkPosted on 2005-03-14 at 18:16:57ID: 13541180

Paul,

Email on its way.  I'd be interested in seeing the performance figures on your PC.
I'm running an AMD 800MHz with Win2000Pro and VB5.  My leaders' test figures
look like:

Test Routine      Run1      Run2      Run3      Avg
----------------------------------------------------------------------
XorCalc2            0.2891      0.2969      0.2891      0.2917
DirectConstr      0.3359      0.3281      0.3281      0.3307
XorCalc            0.3906      0.3828      0.4063      0.393233333
XorCalcStatic      0.3906      0.4063      0.3828      0.393233333

=======================================
Gecko,

I would recommend you find a forum in one of the following EE forums:
* EE Lounge
* Miscellaneous
* Programming

Let me know what suits you best and I will participate in the discussion or
question.  Look for an active forum.  What you want is lots of experts helping
rather than just me.  Maybe Paul or Idle might have some recommendation
on the best forum for your interest.

 

by: gecko_au2003Posted on 2005-03-14 at 18:20:29ID: 13541197

Programming is my favourite topic, not sure what I would ask because I asked in the past about resources and suggestions and got average responses but since you are or were a software instructor then I think you would have a better idea.

I have a intel P4 3ghz with H/T, 512 MB DDR 400 mhz RAM, 7200 RPM hard drive :) So not sure if that will make it go much faster, also I would need to know how to optimize the IDE / compiler as well as which code or codes you wanted me to test and time. BTW How do you get it to time how long each one takes, do you assign a labels caption to the time it takes  or how does it work ?

 

by: gecko_au2003Posted on 2005-03-14 at 18:22:11ID: 13541202

I havent recieved any email as of yet :) Any chance you could re send in 5 or 10 mins if I dont get it :) thanks !

~GO

 

by: aikimarkPosted on 2005-03-14 at 18:42:08ID: 13541304

GO,

The email was sent to PaulHews so he could put it up on his web site and more easily
incorporate my project changes.

If you want to see this, visit Paul's web site (see the link he provided).

 

by: gecko_au2003Posted on 2005-03-14 at 19:04:08ID: 13541402

I must be going blind lol because I couldnt see your email addy on his site. I got a URL to one of my questions YAY ! lol

 

by: aikimarkPosted on 2005-03-14 at 19:14:20ID: 13541429

GO,

You will not find my email address on Paul's web site.
What you WILL find is a link to this discussion thread (which you did find),
a link for a zip file containing the VB project and a compiled version of the
program.  You will also find an email link for Paul (not me).

 

by: gecko_au2003Posted on 2005-03-14 at 19:21:49ID: 13541462

oh ok, what did you think to my abriev GO, I just made that just as a joke cos I see people on here make abrievs for there nicks, I think Idle Mind was IM ( which in chat terminology means Instant Message) lol, sounds just like him LOL.

Anyway, If I did what IM Did then I would be GA , I think GO is still good but just wanted opinions on it :)

 

by: aikimarkPosted on 2005-03-15 at 03:13:47ID: 13543292

I eliminated six of the multiplication operations in my construction, and still
didn't manage to catch up to to the XorCalc2 leader.  In the following byte
construction statement, the difference of the exponents (maskbit - targetbit)
is the divisor.  This is exponent math.

        bytResult(Count) = (((DblLong.High4 And &H1000000) \ &H20000)) + (((DblLong.High4 And &H10000) \ &H400)) + (((DblLong.High4 And &H100) \ &H8)) + (((DblLong.High4 And 1)) * &H10) _
                + (((DblLong.Low4 And &H1000000) \ &H200000)) + (((DblLong.Low4 And &H10000) \ &H4000)) + (((DblLong.Low4 And &H100) \ &H80)) + (((DblLong.Low4 And 1)) * &H1)

 

by: aikimarkPosted on 2005-03-15 at 05:48:21ID: 13544344

gecko,

If GO is a joke then I'll refrain from using it.  If you want to use it as
your 'handle', then I have no problem addressing you that way...
Whatever makes you happy.  It doesn't matter to me.

One thing I would add is that "GO" is also a T-SQL command.  Be
careful about using that handle if you participate in the SQL Server
forum.

 

by: PaulHewsPosted on 2005-03-15 at 06:18:32ID: 13544599

I've updated the project on my site.  

 

by: aikimarkPosted on 2005-03-15 at 06:51:30ID: 13544930

Thanks Paul.

I found one redundant multiplication operation for the low-order bit.  
I removed it in the statement below.  I just sent you an email with this
statement as well.  I didn't know if you'd received the email.

       bytResult(Count) = (((DblLong.High4 And &H1000000) \ &H20000)) + (((DblLong.High4 And &H10000) \ &H400)) + (((DblLong.High4 And &H100) \ &H8)) + (((DblLong.High4 And 1)) * &H10) _
                + (((DblLong.Low4 And &H1000000) \ &H200000)) + (((DblLong.Low4 And &H10000) \ &H4000)) + (((DblLong.Low4 And &H100) \ &H80)) + (DblLong.Low4 And 1)

=========================
Not included in the code base was a different attempt to do a comparison of nibble values.
I used two Select Case statements and combined the associated low-order and high-order
nibble bit configurations into the byte for that iteration.  It wasn't qhite as fast as the
DirectConstruction1 routine.  If you want it, I'll send it to you.

Optimization Tip:
If you know the frequency of values, order the Select Case statment's Case clauses to
check for the most likely values first.  This minimizes the number of unsuccessful
value comparisons in the Select Case statement.
Example:
* For this test, I know that the decoded string is an English language sentence with mixxed
case aphabetic letters.  To optimize the Select Case statement for this highorder nibble,
I placed the lower case nibble values at the top and then the upper case nibble values,
and then the rest of the possible values.
* Since the low order nibbles values are evenly distributed, there was no advantage to
change the arrangement of the Case clauses.

==================================
I think this just about wraps up this discussion and test.  
Thanks to all.  This has been fun.

If you want to read about more VB performance enhancement, visit the VBSpeed site:
http://www.xbeat.net/vbspeed/index.htm

Individual statements and common techniquest are discussed.  Performance tests
are compared.  Maybe they would be interested in your link, Paul.  As far as I'm
concerned, they are welcome to the source code.  

They do have a page dedicated to a String-to-Bit conversion.
http://www.xbeat.net/vbspeed/c_StringToBit.htm

I think we have three different approaches that might be of interest to the VBSpeed
folks and warrant inclusion and (their) official testing.

 

by: aikimarkPosted on 2005-03-15 at 07:00:34ID: 13545048

Actually, the StringToBit page is dedicated to the opposite task of what we have
done and complements our work nicely.
http://www.xbeat.net/vbspeed/c_StringToBit.htm

 

by: gecko_au2003Posted on 2005-03-15 at 09:16:02ID: 13546591

ok thanks for the warning aikimark, I dont use SQL that much so I dont really participate in them that much but feel free to use GO as my handle :)

 

by: Idle_MindPosted on 2005-03-15 at 09:46:47ID: 13546898

>> Idle_Mind - I am just curious where you learnt and have learned all the stuff you know or any suggestions / reccomendations you could make to me as well with regards to what I asked aikimar above.

I'm principally a self-taught programmer since I was about 10 years old.  My dad was a computer programmer and we always had computers in the house.  I just picked it up and ran with it...

I've got 3/4ths of a CS degree done but I find it really hard to attend classes and pay attention because they move so s...l...o...w and don't challenge me in any way.  Maybe some day I'll go back and finish that silly degree...

As far as recommendations just always be open to different approaches and try to learn from others code.  Subscribe to questions that you don't know the answer to but are interested in so you can watch the answers unfold.  Answer the mundane questions...nothing can be substitued for actually doing the coding.  You should be able to see how different parts of a problem would be broken down and what kind of structure would be appropriate.  (String vs. Array, For..Next vs. While...Wend, Global Flag vs. Events, etc...) This just comes from experience and having to write code to solve common problems over and over...  Decomposition of a problem is the most important part and is where most developers get themselves into trouble.  If you can break problems down until you can see simple subs/functions that do ONE thing and that ONE thing WELL then you are in good shape.  You will have an easy to read and easy to maintain application.  The big picture becomes clearer as you write the small pieces and they fit together nicely like a jigsaw puzzle.  Always concern yourself with solving the problem first and making an interface (GUI) for it second.  Separation of engine and GUI is also difficult for many programmers.  If you can take your concept and move it to another application easily then you have done well.  

If you have VB.net, you really should spend some time trying to answer questions and looking at solutions in the VB.Net area.  VB6 is an OOP mutt and not really the best choice for good design building habits.  You will see completely different approaches to problems in the VB.Net area because the structure and capabilities of .Net are very different from that of VB6.
http://www.experts-exchange.com/Programming/Programming_Languages/Dot_Net/VB_DOT_NET/

 

by: gecko_au2003Posted on 2005-03-15 at 09:53:50ID: 13546964

That is my intention with regards to moving onto another language which is OOP and I am aware of vb 6 not being OOP well at least not fully. I want to get a full understanding of concepts and principles of programming with regards to everything from WMI, API's, subs, functions, variables, etc , etc. So that when I move on from visual basic 6 I have a good base / grounding so that moving on to the next level / step IE .NET and the framework and C# or C++ or even Java that I have a basic understanding of what I am doing when I am programming. If that makes any sense, not sure if that is a good way to go about it either but that is how I am approaching it, unless you have any better ideas with regards to doing it in a more structured way or if you just reccomend going straight onto .NET ? Anyway thanks ~IM :D

20120131-EE-VQP-002

3 Ways to Join

30-Day Free Trial

The Experts

98% positive feedback on 31,087 answers since March 2000. angeliii is a Microsoft Most Valuable Professional for his work with MS SQL Server & Develoment.

He has also proven his knowledge of Visual Basic Programming, PHP Scripting and Oracle Databases.

The Experts

97% positive feedback on 10,752 answers since July 2000. lrmoore has more than 18 years experience in the networking industry.

The six-time Mircosoft MVPs specialties include firewalls, virtual private networking, and network management.

Testimonials

"...and excellent source for support... Kind of like having your very own IT dept." Electriciansnet

Testimonials

"I was apprehensive at signing up at first. However... it has already made my life as an IT administrator much easier." JaCrews

Testimonials

"WOW! You guys have great, active, and knowledgeable people on here." moore50

Business Clients

Business Clients

In the Press

"If you’ve got a question... Experts Exchange can supply an answer.”

In the Press

"...an invaluable aid for both IT professionals and those who require tech support."

In the Press

"where IT professionals provide quick answers on just about any topic"

Business Account Plans

Loading Advertisement...