Efficiency Question regarding RaiseEvent in a Loop

[quote=66266:@Kem Tekinay]Your code is literally the same as this:

FirstOctetDec = Inbound32BitWord.Left( 1 ).Val
SecondOctetDec = Inbound32BitWord.Mid( 9, 1 ).Val
ThirdOctetDec = Inbound32BitWord.Mid( 17, 1 ).Val
FourthOctetDec = Inbound32BitWord.Mid( 25, 1 ).Val

They will all either be 0 or 1.

There is no advantage that I can see for you to use a MemoryBlock over 4 integer variables. The question is (what neither I nor, I think, Tim understands), why you need the binary representation at all? What are you doing with the bits you count? .[/quote] There are a few functions that I am using to compare Network Mask Octet against a Subnet Mask Octet to see which bits fall through. I only know how to do that bit by bit in binary form.

You’d just AND each octet of the IP to its corresponding octet in the mask, wouldn’t you?

Mike, this

 n2 = SubnetMask2Dec
  Select Case n2
  Case 0
    m2 = 0
  Case 128
    m2 = 1
  Case 192
    m2 = 2
  Case 224
    m2 = 3
  Case 240
    m2 = 4
  Case 248
    m2 = 5
  Case 252
    m2 = 6
  Case 254
    m2 = 7
  Case 255
    m2 = 8
  End Select

Can be written as

dim i, mask as integer

n2 = SubnetMask2Dec
m2 = 8
mask = 254
for i = 1 to 8
   if (mask and n2) <> n2 then exit
   m2 = m2 - 1
   mask = bitwise.shiftleft(mask, 1)
next

So, for example, with 192.168.1.1/255.255.255.0, an AND of each octet to its mask would give me 192.168.1.0. With 172.172.200.19/255.255.128.0, I’d get 172.168.128.0. Subtract each octet of the mask from 256 to find the range of each IP octet. With the latter example, that would tell me that I could go from 172.172.128.0 thru 172.172.255.255.

No?

Are you on a Mac? If yes, have you used Instruments? It’s a waaaayyyy more better profiler than the one Xojo has.

Didn’t follow all of this thread, but I think this code:

Dim DecimalAddress as String = Str(FirstOctet) + "." + Str(SecondOctet) + "." + Str(ThirdOctet) + "." + Str(FourthOctet)

might be slow. Try this instead:

dim DecimalAddressParts() as string=Array(Str(FirstOctet),Str(SecondOctet),Str(ThirdOctet), Str(FourthOctet))
dim DecimalAddress as String =join(DecimalAddressParts,".")

Kem thank you for all of your feedback. I am rewriting in decimal today. :wink: Thank you again.

I am on Mac and I haven’t tried instruments yet. THanks for the tip!

Tim/Kem thank you as the bitwise function is exactly what I was trying to “recreate” in my non efficient attempt of integer --> string(binary) --> integer. The basis of this simple set of code will replace two functions for me :slight_smile:

This does the Binary 1+0 comparison for every bit (bitwise.BitAnd).

Quite the detour, but the learning experience has been great. Thanks all!

  dim network1, network2, network3, network4, Subnet1, subnet2, subnet3, subnet4 as integer
  
  Network1 = 10
  Subnet1 = 255
  
  network2 = 20
  Subnet2 = 255
  
  network3 = 5
  subnet3 = 255
  
  network4 = 1
  subnet4 = 0
  
  Dim Results1 as Integer = Bitwise.BitAnd(Network1,Subnet1)
  Dim Results2 as Integer = Bitwise.BitAnd(Network2,Subnet2)
  Dim Results3 as Integer = Bitwise.BitAnd(Network3,Subnet3)
  Dim Results4 as Integer = Bitwise.BitAnd(Network4,Subnet4)
  MsgBox "Results: " + Str(Results1)+"."+Str(Results2)+"."+Str(Results3)+"."+Str(Results4)

Use And instead of Bitwise.BitAnd. They do the same thing, but the latter is a method, so it is slower.

  Dim Results1 as Integer = Network1 And Subnet1

Kem thank you as I didn’t catch that last post. I read it but I didn’t expect AND to actually compare :slight_smile: Thank you!

I always viewed/used AND as logic in IF statements :slight_smile: awesome.

Yeah, once upon a time, And, Or, and Xor only did boolean comparisons, hence the need for the Bitwise functions. Later, they were changed to do double-duty as bitwise operators, but many didn’t realize.

Now we just need operators for ShiftLeft and ShiftRight and we’d be set.

Funny as I am playing with bitwise.shiftleft now :slight_smile: That would be nice not having to be married to the bitwise function for shifting bits.

Awesome, I have been testing bitwise.bitXOR which appears to add bits together for me.

Decimal 10 + Decimal 1 = Decimal 11

which bitwise is doing

00001010 + 00000001 = 00001001

I needed a way just to add one bit at a time so this works nicely.

Again, use Xor instead of Bitwise.Xor.

But Xor will cancel bits out, so make sure it’s not Or you want instead. (And it actually should be And if you’re talking about applying the subnet mask).

Will do and thanks again Kem.

Mike, since you got me interested, I wrote these two methods. Feel free to use any part, if it helps.

Protected Function ToMemoryBlock(stringValue As String) As MemoryBlock
  // Converts a string representation of an address or mask to a MemoryBlock
  
  dim parts() as string = stringValue.SplitB( "." )
  dim mb as new MemoryBlock( 4 )
  
  dim lastIndex as integer = parts.Ubound
  if lastIndex > 3 then lastIndex = 3
  
  for byteIndex as integer = 0 to lastIndex
    mb.Byte( byteIndex ) = parts( byteIndex ).Val
  next
  
  return mb
  
End Function

Protected Function ValidSubnetMask(mask As String, ByRef maskMB As MemoryBlock) As Boolean
  // Validates a subnet mask as valid.
  // Returns a MemoryBlock of the mask as bytes, but only if it's valid
  
  dim r as Boolean = true
  
  // Make sure it's just digits and periods
  dim rx as new RegEx
  rx.SearchPattern = "[^\\d.]"
  if rx.Search( mask ) <> nil then // Contains something other than digits or periods
    r = false
  end if
  
  if r and mask.CountFieldsB( "." ) <> 4 then
    r = false
  end if
  
  if r then
    maskMB = ToMemoryBlock( mask )
    
    // Do the validation of the octets
    if maskMB.Byte( 0 ) <> 255 then
      
      r = false
      
    else
      
      static validOctets() as UInt32 = Array( &b00000000, &b10000000, &b11000000, &b11100000, &b11110000, &b11111000, &b11111100, &b11111110 )
      for i as integer = 1 to 3
        if i <> 3 and maskMB.Byte( i ) = 255 then continue // Last octet can't be 255
        if maskMB.Byte( i - 1 ) = 255 then
          if validOctets.IndexOf( maskMB.Byte( i ) ) <> -1 then continue
        else // The previous value is something less then 255 so this has to be 0
          if maskMB.Byte( i ) = 0 then continue
        end if
        
        // If we get here, can't be valid
        r = false
        exit
      next i
      
    end if // maskMB.Byte( 0 ) <> 255
  end if
  
  if not r then
    maskMB = nil
  end if
  
  return r
End Function

Awesome thanks Kem! I rewrote many of my functions with only converting from IP Decimal format to a 32bit decimal word and performing all functions against that. It works very well and fast, however when I get to the array/listbox loading I am still trying to increase efficiencies there. Ill check out your code so I can add it in :slight_smile: Thank you again!

This is my loop that runs all subnet iterations. I dramatically decreased its size and complexity.

  // Get ClassFull Boundary Starting Point
  NetworkSubnetID = fGetClassFullNetwork(Input_StartIP_32BitDecimalWord,Input_SubnetMask_32BitDecimalWord)
  
  BitsStolen = SubnetPrefixLength - ClassFullSubnetPrefix
  CalculateLoopEnd = 2^BitsStolen
  
  for y = 0 to CalculateLoopEnd //  2^ Number of Stolen Bits on that class
  
    HostFirst_32BitDecimalWord = NetworkSubnetID+1
    ReverseSubnetMask = Bitwise.OnesComplement(Input_SubnetMask_32BitDecimalWord)
    BroadCastID_32BitDecimalWord = NetworkSubnetID+ReverseSubnetMask
    HostLast_32BitDecimalWord  = BroadCastID_32BitDecimalWord-1
    NetworkSubnetID = BroadCastID_32BitDecimalWord+1
    
  Next y

BTW are there any speed differences with Xojo using For/Next, While/Wend, Do/Loop? I will try a few of the tonight to see if I can increase that speed a bit. Thanks again!