Performance tweaks

In Xojo there are a number of things you can do to improve the performance of your code.

There are various pragmas you can enable that can improve speed – I’d suggest only doing this once you code is fully debugged and known to be working properly as turning these checks of can mean IF you have a bug your application just crashes hard.

And there are other things you can do like lifting out code that repeatedly does lookups in arrays.

So instead of

dim something(1000) as String

// intervening code to load data into the array

for i as integer = 0 to something.ubound

   if something(i) = "abc" then
   elseif something(i) = "def" then
   elseif something(i) = "ghi" then
   end if
next

you might rewrite this as

dim something(1000) as String

// intervening code to load data into the array

// 1) eliminate repeatedly accessing the Ubound property
dim maximumIndex as integer = something.ubound 

for i as integer = 0 to maximumIndex

   // 2) eliminate repeatedly doing an array access
   dim thisItem as string = something(i)

   if thisItem = "abc" then
   elseif thisItem = "def" then
   elseif thisItem = "ghi" then
   end if

next

It would be nice if the compiler could/would do more optimization of code. There are a host of optimizations that you could apply manually like common subexpression elimination and loop invariant code motion.

But sometimes the biggest performance wins are not from tweaks like these. Often applying a different algorithm has a much bigger bang for the buck than anything.

When I worked at Xojo there were a couple areas where simply by inverting how some data was accessed in memory the entire process was sped up enormously.

Databases will do this and may use the MOST selective index to retrieve data first so the initial set of data is very tiny, instead of starting with the most broad set of data, and then winnowing it down further. By doing this they can decrease the amount of memory required and the amount of data to iterate though to satisfy whatever query you’ve executed.

When you have a performance issue I would START by reconsidering how the data is accessed and used and whether you can alter the algorithm to gain an initial big speed up by doing things in a different order.

And once you get the algorithm working the way you want then apply all the other tweaks to code to squeeze the most out of it.

And JUST to be clear make sure you do timings in a COMPILED and BUILT version NOT aa debug version using RUN as a debug version still has a lot of debug related code in it that can influence the results and MAY mislead you.

Structures vs Classes

While structures & classes may seem to be very similar in most respects there aren’t many cases when I would suggest you use a structure instead of a class.

A class with public member properties isnt that different from a structure in terms of how your code uses it.

The biggest difference is that for a class you must use new to get a new instance. With a structure you just declare it and use it.

Structures are handy for some things. If you have to read or write a specific binary file format you might use a structure. If you’re going to call some OS API via a declare then structures are useful. And if you’re reading or writing binary data to binary streams via sockets or other communication channels they are useful.

But there are downsides. Since structures are JUST data any methods to manipulate them have to go in a module. Unlike a class you cannot add methods to the structure itself. And so you end up using a very non-OOP style – maybe a module with the structure defined in there along with all the code that manipulates the structure.

Classes allow you to just bundle up the data and code into a single item and all the code that manipulates the class is part of the class – along with any hidden methods it might need that can be completely hidden from the outside world.

If your still using VB style syntax and creating a lot of structures I’d suggest you give using classes a try.

Once you get the hang of it you will appreciate how classes let you organize your code and data in a nice single item.

Operator_compare

Ever wanted to define a class, maybe a vector class, and make it possible to write code like

dim v1 as new Vector(1,1)
dim v2 as new Vector(2,2)

if v1 > v2 then
  // do something when v1 > v2
elseif v1 < v2 then
  // do something when v1 < v2
else
  // do something when v1 = v2
end if

Perhaps you have some other kind of class you’d like to define that has some kind of custom mechanism to compare itself to other instances – or even other data types.

If so you need to know how to implement operator_compare

First off operator_compare can ONLY be implemented in a Class. You cannot extend existing classes and add it to them.

It’s a method, or several methods, you add to a class that will be called whenever you use the comparison operators =, <, >, <=, >= and <> are used. Note that this has implications for your code if you are using = to check is one instance is the same instance as another. In that case you should probably use IS rather than =.

Beyond that operator_compare is pretty straight forward.

You define the method with that name, and the parameter is whatever type you wish to compare your instance, the “self” instance, to. So you can have many as each signature would be different. The return value is and integer that is

  • < 0 means SELF is “less than” the passed parameter
  • = 0 means SELF is “equal to” the passed parameter
  • > 0 means SELF is “greater than” the passed parameter

and you get to define what less than, equal to, and greater than mean.

So suppose our Vector class was defined as follows

Class Vector
   protected x as double
   protected y as double

   Public Sub Constructor(x as double, y as double)
      Self.x = x
      Self.y = y
   End Sub

   Function Operator_compare(other as vector) as Integer
      Dim a, b As Integer
      a = Self.x ^ 2 + Self.y ^ 2
      b = other.x ^ 2 + other.y ^ 2
      If a > b Then Return 1
      If a = b Then Return 0
      If a < b Then Return -1
    End Function
End Class

And now our original code from way back would work

dim v1 as new Vector(1,1)
dim v2 as new Vector(2,2)

if v1 > v2 then
  // do something when v1 > v2
elseif v1 < v2 then
  // do something when v1 < v2
else
  // do something when v1 = v2
end if

Now you could make Vectors compare themselves to Strings if you really wanted. I’m not sure what exactly that might mean – but you could. You might try implementing this as

Public Function Operator_compare1(other As string) as Integer
  Dim myRepresentation As String = "(" + Str(x,"-######.00") + "," + Str(y,"-######.00") + ")"
  
  If myRepresentation = other Then Return 0
  
  return -1
End Function

Again I’m not sure what this might truly mean but we’ll indicate that unless they are the exact same string the “self” is < the string value. Suppose you try to test this with

Dim v1 As New Vector(1,1)

If v1 = "(foo)" Then
  Break
Else
  Break
End If

And now you Vectors can be compared to Strings. With extra overloads of Operator_compare you can make your classes compare themselves to all sorts of your other classes & types.

Enjoy !

Method signatures

I know I’ve probably used this term a bunch in other blog posts but I don’t think I’ve ever explained what a method signature is.

In Xojo a “method signature” is the unique way Xojo identifies each method so it can know which method you are calling in your code.

So what does that include ?

First off it does NOT include the SCOPE. PRIVATE, PUBLIC, GLOBAL, and PROTECTED are scope modifiers – but they are not part of the signature of a method.

Attributes are also not part of the signature.

And, curiously enough, the return type is NOT part of the signature. While that determines where you can use the method (ie in an expression where a value is expected vs not) it is NOT part of the signature.

The signature includes only the name and parameter list.

It gets a LOT more confusing if your parameter lists have optional or default parameter values since the signature basically can be thought to be “variable” – but its still just the name and parameter list.

And if you ever get an error saying

There is more than one item with this name and it’s not clear to which this refers.

and the compiler has hilighted a method call then the likelihood is you have two signatures that can be treated the same and the compiler cannot figure out which one you really meant to use.

2019r3

I’ll admit that I really haven’t seriously touched R3 since most of its focus was on iOS and dark mode which isn’t something that matters to me.

The times I did start it I found it to still be slow like R2.1 and otherwise not many significant differences in the things I was trying.

Autocomplete is still glaringly bright in dark mode on macOS. I’m now wishing there was a way to turn autocomplete off its so hard on my eyes being in bold and bright white. It’s definitely NOT the code editors text color or any user selected color.

And the new default color set is harsh as well. Again its incredibly bright and in dark mode its too darned bright for my liking. Makes me really glad I made it so users could configure their own themes way back when 😛

But you be the judge. In the following pictures R3 is first and R1 is next. Both are set to use default colors. (To be honest the images do NOT show how bright those colors are here on all 3 monitors)

R3 in default colors in dark mode are very bright
R1 default colors are subdued in dark mode

Beyond that I haven’t used R3 for anything. I’m still seeing too many odd bugs being reported to make me comfortable moving any client projects to it. So I’m still using 2019r1.1 – basically the last version I contributed to 🙂

In the mean time I have managed to assemble lists of differences for various project types. These are all the differences I can discern between 2019r3 and 2019r1.1

macOS Console 64 bit

macOS Web 64 bit

macOS Desktop 64 bit

iOS 64 bit

I’ll see about compiling lists of differences on Windows & Linux as well

Note that this is changes and may simply indicate that some reorganization has taken place. For instance the HTMLViewer appears to have had many events removed but it appears the code is simply reorganized so that event handlers, for instance, are not handled in a Xojo stub and re-raised but are raised directly by the HTML Viewer plugin.

EDIT – I can see that I’ll need to update how this data is presented to make situations like the event handling on the HTMLViewer more clear. It appears that the old HTMLViewer had event handlers and event definitions so the HTMLViewer would handle the event and re-raise it so you could handle the event. This appears to have been reconfigured in 2019r3 – so the event is no longer handled by the HTMLViewer and re-raised but just not handled at all so the base class event can still be handled. To the end developer this change is invisible but in the overall framework set up it is readily apparent which is why my 2019r3 differences list includes the removal of all these events.

Overloading

No not your plate (despite it being right around American Thanksgiving)

Sometimes when you write your code its convenient to have several versions of “the same” method.

For instance, in Xojo you might look at the AddRow method on the Listbox class )in 2019r1.1) and see that it has several forms

ListBox.AddRow(ParamArray Item as String) 
ListBox.AddRow(items() as String) 
ListBox.AddRow() 

This is a great example of “overloading” – having one method with many different signatures. Each is unique and distinct from the others and the compiler doesn’t have to do conversions that might lead to ambiguous situations when you pass several strings to the method.

The same can be said for the classic Date class. It had several constructors like

Date.Constructor()
Date.Constructor(CopyDate as Date)
Date.Constructor(Year as Integer, Month as Integer = 1, Day as Integer = 1, hour as Integer = 0, minute as Integer = 0, second as Integer = 0)
Date.Constructor(Year as Integer, Month as Integer = 1, Day as Integer = 1, hour as Integer = 0, minute as Integer = 0, second as Integer = 0, GMTOffset as double)

Note the last two are VERY similar but vary in the very last parameter.

And you can also do this in your own classes & code.

You could easily add many constructors to your classes so you can create instances using a wide variety of parameters.

As long as each overload can unambiguously be called the compiler wont have any trouble with things.

Its usually the “unambiguous” part that gets people into trouble as they defer to using default values for parameters. For example, if I have the following class along with the constructors shown you may find you have issues – but only sometimes

Class TestClass
   Public Sub Constructor()
   End Sub
   Public Sub Constructor(foo as integer = 0)
   End Sub
End Class

If later I have code like

Dim c As New TestClass(1)

This will work without issue since TestClass only has one possible constructor that matches that signature. So things compile & run fine.

However if later I try to do

Dim c As New TestClass

I will now get a compile error saying

Window1.Open, line 1
There is more than one item with this name and it’s not clear to which this refers.
Dim c As New TestClass

The compiler cannot figure out whether I mean to call the constructor with no parameters, or the one that has a single parameter with a default value that I simply have left out. And so it gives up trying and you get a compile error.

Once you realize that the issue is that the compiler doesn’t know which method you meant you can address the problem. Perhaps in this case a constructor with a default value for the parameter makes no sense and so you’d remove that default value. Or you decide that you really only need the Constructor with the single parameter and default value since you can deal with it as if it were the no parameter version.

Often when I’ve encountered this problem it is a symptom of having optional or default values that, when omitted, make one method have the same signature as the other.

Careful out there and try not to confuse the compiler too much.

Operator_Convert

Operator_Convert is a very handy method to implement on a lot of classes. It not only lets you create a mechanism to make your classes convert themselves into other types but it also lets you create new instances FROM other data types.

So let’s start with the simple forms of operator_convert – the “convert TO” forms.

Suppose you have some class defined called “myClass”

Class myClass
End Class

and you want to make it easy to have this class write log messages to the DebugLog. You most certainly could write a “ToString” method as an explicit way to convert this class to a String

Class myClass
   Function ToString() as string
   End Function
End Class

and then in your code you’d use it like :

dim instance as new MyClass

// lots of intervening code

system.debuglog instance.ToString

And maybe this isn’t so bad. It IS explicit which is most times a good thing. Your code will have a certain clarity to it because of this style.

But there is another way to do much the same thing that is also effective – despite it being slightly hidden and magical like a variants ability to automatically convert itself to other data types by assignment. And this “magic” is operator_convert

In a class like our sample

Class myClass
   Function Operator_Convert() as string
   End Function
End Class

And now your usage could look like

dim instance as new MyClass

// lots of intervening code

system.debuglog instance

Since System.Debuglog takes a string as a parameter the compiler figures out that our class has a suitable Operator_convert method and will call that for us.

You can define many operator_convert functions that convert TO other datatypes and as long as they dont cause any ambiguity you will get the results you expect. You may get an ambiguous situation of you define a Convert To operator_convert for Integer, Int32 and/or Int64 since Integer is simply an alias to one of those types depending on whether you are building for 32 or 64 bit. There can be others but this is the most common.

There is another form for operator_convert – the “convert FROM” form.

In this case operator_convert behaves in many ways like a constructor called with a parameter. However one thing to remember is that Operator_convert is NOT a constructor! Its an initializer at best. If your class depends on constructors being called make sure when you use the convert FROM form you call your constructor !

For our sample class suppose we want to initialize it from a string.

Class myClass
   Function Operator_Convert() as string
   End Function

   Sub Operator_Convert(initializeWith as string)
      // if we rely on the constructor having been called 
      // then call the Constructor here !
       
      // now set our class up from whatever data is in the
      // parameter passed
   End Sub

End Class

and we could use it like

dim instance as MyClass = "123"

// lots of intervening code

system.debuglog instance

Something to note is that these conversions can appear to be hidden away from a casual reader so use them with care and consideration. Often explicit code, like the ToString example above aids a reader in understanding the code because its right there in front of them that you are asking the class to give you a string representation for some purpose.

Keep that in mind and use these with that in mind.

Enjoy !

Using interfaces (again)

A recent comment on my post about overriding prompted me to write this second post about interfaces and why you might use them. Its clear to me that I havent done a very good job of explaining why you should or would use them.

In some languages you can create classes that inherit from one other and one other only. Xojo is this way. Some others let you inherit from several superclasses but this has a set of issues that Xojo avoids by limiting things to single inheritance. Java is also this way and does not support multiple inheritance.

So what do you do in the case you have a class you’ve created and you want it to “inherit” from multiple other classes ? Suppose you have a class that needs to inherit from “InputStream” so it can be read from AND also needs to inherit from “OutputStream” so it can be written to ? Xojo has such a class – BinaryStream.

The way to achieve this is actually NOT to try & inherit from two super classes but to make the InputStream and OutputStream into interfaces and then have your class implement both interfaces. In fact this IS what BinaryStream does – it implements both the Readable and Writeable interfaces so you can read from it and write to it.

You implement the methods on each interface and then any other methods on your code that takes a Readable parameter you can pass a BinaryStream to, since BinaryStream IsA Readable. And any of your code that takes a Writeable parameter you can also pass the BinaryStream to since it IsA Writeable.

As well you can extend interfaces just like any other class.

So its perfectly legal to write a method like

Sub DoREadableStuff(extends instance as Readable)

just as you would for any other type in Xojo.

This gives you a lot of flexibility in how you use & implement interfaces.

About the only thing you might run into is what to do if you have two interfaces that you want a class to implement and they have methods that you have to implement that are named the same ?

As long as the full signature of the methods, method name and all parameters, are unique this isnt a problem as you can implement both and you will just appear to have 2 or more overloads of the same method just taking different parameters.

But what if they have the same parameters ?

If you just add both interfaces then you will have to methods with the same name and the same parameters and Xojo will not compile your program any more because its ambiguous which one would be used when.

And this is where a little used aspect of Xojo comes into use.

Lets set up a small example so you can follow along as that will make things much clearer.

Start a new desktop project.

To the project add

  • a class named class1
  • a class interface named interface1
  • add a method to interface1 named Connect
  • a second class interface named interface2
  • add a method to interface2 also named Connect

Now we’re going to make it so class1 implements both interface1 and interface2. Click on Class1 and make sure the Inspector is showing. Click on the Interfaces button in the Inspector. Select both Interface1 and Interface2. I often also select the “insert #pragma error” in each method option at the bottom of the pane.

Click OK and empty stubs for all the methods in Interface1 and Interface2 will be added to Class1. And note we do have 2 connect methods.

If you try to run or analyze the project you will get a “duplicate method definition” error – this is exactly as expected since we have two identical signatures (method name and parameters)

And now we’ll fix this. What we need to tell Xojo is that “this method implements the Connect method from interface1 and this other method implements the Connect method from Interface2”.

Right click on the first Connect method. And select the “Show Implements” option from the contextual menu. Notice that when you do this an extra field shows up in the Inspector.

This extra field is used for exactly what we just stated – telling Xojo which Connect method each of the Connect overloads actually implement. So for the first one we’ll put in the field Interface1.Connect. Then click the second Connect method and in the field put Interface2.Connect

You’d think we’re done at this point because those two method now say which method from which interface they implement. However, they are still exact duplicates and the compiler will still complain about that. So rename the first one Interface1Connect and the second Interface2Connect. I’ve renamed this way JUST for clarity for this example. You could rename them anything you liked that doesnt cause other errors.

And now for the proof that this works.

In our sample applications Window1.Open event (or opening for those using 2019r2 and newer) lets put in the following code



Dim i As interface1 = New Class1
break
i.Connect

Dim j As interface2 = Interface2(i)
break
j.Connect

Recall that a Class1 IsA Interface1 because it implements that interface. And that it is also an Interface2 because it also implements that interface. If you run this code now you wont get any errors BUT it is hard to see that it is doing exactly what we’ve told it to.

If you run & step INTO each call to Connect you will see that because in the first case i IsA Interface1 that stepping into i.Connect does indeed call Interface1Connect – the exact method we said implemented the Interface1.Connect method.

And when you get to the second break statement and step into j.Connect you will see that, because j IsA Interface2 that this call to Connect will end up in Class1’s Interface2Connect method – the one set said implemented Interface2.Connect.