Android Question Speed difference between Reflection library and For...Next

Tom_707

Member
Licensed User
How much of a speed penalty is there when using the reflection library?

For example, which of the following two methods is faster, and by how much? Is it negligible and doesn't make a difference, or is one method much better than the other?

Finding the correct View using reflection:
B4X:
Dim refView As Reflector
Dim v As View

'Views have previously been assigned Tags
refView.Target = Activity
For Counter = 0 To 1000
   v = refView.RunMethod2("FindViewWithTag", Counter, "lang.java.int")
   v.Width = 100dip
Next


Finding the correct View by iterating through all Views:
B4X:
Dim v As View

'Views have previously been assigned Tags
For Counter = 0 To 1000
   For Each v As View In Activity.GetAllViewsRecursive
      If v.Tag = Counter
         v.Width = 100dip
         Exit
      End If
   Next
Next
The "For Counter = 0 To 1000" loop is just there to magnify the speed difference. The real code will not have this.
 

stevel05

Expert
Licensed User
Longtime User
You can add the code to your tests to time it yourself for example:

B4X:
Dim refView As Reflector
Dim v As View

Dim StartTime as Long = DateTime.Now

'Views have previously been assigned Tags
refView.Target = Activity
For Counter = 0 To 1000
   v = refView.RunMethod2("FindViewWithTag", Counter, "lang.java.int")
   v.Width = 100dip
Next

Log(DateTime.Now - StartTime)

Will give you the time in milliseconds. Don't forget to test it in release mode.
 
Last edited:
Upvote 0

agraham

Expert
Licensed User
Longtime User
Reflection is normally a SL___OW process as it has to look up the required method from a list of those supported by the object then assemble the parameters and invoke the method. I guess you haven't run it as the correct name is findViewWithTag as Java is case sensitive.

Worrying about speed of execution is a premature optimisation. You should write nice, neat, understandable and well commented code and only be concerned when a problem arises. As a matter of style you should only use Reflection when necessary - after all you are writing in B4X not Java.
 
Upvote 0

Tom_707

Member
Licensed User
You can add the code to your tests to time it yourself for example:

B4X:
Dim refView As Reflector
Dim v As View

Dim StartTime as Long = DateTime.Now

'Views have previously been assigned Tags
refView.Target = Activity
For Counter = 0 To 1000
   v = refView.RunMethod2("FindViewWithTag", Counter, "lang.java.int")
   v.Width = 100dip
Next

Log(DateTime.Now - StartTime)

Will give you the time in milliseconds. Don't for get to test it in release mode.
Thanks @stevel05.
 
Upvote 0

Tom_707

Member
Licensed User
Reflection is normally a SL___OW process as it has to look up the required method from a list of those supported by the object then assemble the parameters and invoke the method. I guess you haven't run it as the correct name is findViewWithTag as Java is case sensitive.

Worrying about speed of execution is a premature optimisation. You should write nice, neat, understandable and well commented code and only be concerned when a problem arises. As a matter of style you should only use Reflection when necessary - after all you are writing in B4X not Java.


Thanks @agraham. Appreciate your advice.

It's a pity "findViewWithTag" is not available in B4X. I think it would be really useful, and it doesn't seem like something that would be too difficult to implement.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
It's a pity .... is not available in B4X
Erel has to choose a balance between what is useful to most people and populating the language with stuff that is esoteric. It's a tightrope he has walked very well (in my opinion) for the last sixteen years in his products. The Reflection and JavaObject libraries (and more recently in-line Java) exist to let those with sufficient knowledge to break those bounds if necessary.
 
Upvote 0

Tom_707

Member
Licensed User
This is a "preoptimization" thread.
Does it matter if it takes 0.1ms or 0.5ms to find a view? No user will ever see the difference.

If you want quick and elegant access to specific views then add them to a Map. Very simple to do.


I ran the following code twice:
B4X:
    Dim refView As Reflector
    Dim strCounter As String
    Dim lbl As Label
    Dim StartTime As Long

    lbl.Initialize("")
    Activity.LoadLayout("Console")
    refView.Target = scvConsole.Panel
    For Counter = 0 To 10000
        Dim lblView As Label

        lblView.Initialize("")
        strCounter = Counter
        lblView.Tag = strCounter
        scvConsole.Panel.AddView(lblView, 0, Counter, 100dip, 30dip)
    Next
    StartTime = DateTime.Now
    For Counter = 0 To 10000
        strCounter = Counter
        lbl = refView.RunMethod2("findViewWithTag", strCounter, "java.lang.Object")
        lbl.Width = 150dip
    Next
    Log("R:" & (DateTime.Now - StartTime))
    StartTime = DateTime.Now
    For Counter = 0 To 10000
        strCounter = Counter
        For Each v As View In scvConsole.Panel.GetAllViewsRecursive
            If v.Tag = strCounter Then
                v.Width = 150dip
                Exit
            End If
        Next
    Next
    Log("F:" & (DateTime.Now - StartTime))


And got the following results:
B4X:
R:9779
F:17499
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
R:9685
F:17229
So if reflection is dog SL.....OW as @agraham says, then it shows how in-efficient it is to use a For...Next loop to iterate through all the Views. Which seemed obvious from the beginning. I'll try using a Map and see how that compares.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
So if reflection is dog SL.....OW as @agraham says, then it shows how in-efficient it is to use a For...Next loop
I didn't mean to imply in any paticular situation that Reflection would necessarily be slower - I meant in general. Here you are comparing using Reflection to call a single, native code, probably optimised, method against using many calls in a compiled loop. I still think this is totally unecessary, just code it the obvious understandable way, move on and come back to optimise it later when the app is finished if necessary.
 
Upvote 0

Tom_707

Member
Licensed User
I didn't mean to imply in any paticular situation that Reflection would necessarily be slower - I meant in general. Here you are comparing using Reflection to call a single, native code, probably optimised, method against using many calls in a compiled loop. I still think this is totally unecessary, just code it the obvious understandable way, move on and come back to optimise it later when the app is finished if necessary.


Sorry, I didn't mean to malign your library, or reflection. I just assumed that using reflection was really slow, based on what you wrote. And because you created the library, you obviously would have a really good understanding of its speed performance.

I think your library is brilliant, and use it whenever there is something I can't achieve in B4X directly.
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
Sorry, I didn't mean to malign your library,
I didn't for a moment think you were.

use it whenever there is something I can't achieve in B4X directly.
That was its original purpose, but it has become less important over the years as B4A has grown in capability, in particular with in-line Java, and Android performance has improved both with faster CPUs being available and with the switch from an interpreted virtual machine to a JIT capable virtual machine somewhere about Honeycomb.
 
Upvote 0

Tom_707

Member
Licensed User
This is a "preoptimization" thread.
Does it matter if it takes 0.1ms or 0.5ms to find a view? No user will ever see the difference.

If you want quick and elegant access to specific views then add them to a Map. Very simple to do.


I added the following code:
B4X:
    StartTime = DateTime.Now
    For Counter = 0 To 10000
        strCounter = Counter
        lbl = mapViews.Get(strCounter)
        lbl.Width = 150dip
    Next
    Log("M:" & (DateTime.Now - StartTime))


And here are the results:
B4X:
R:10366
F:17328
M:9
*** Service (starter) Create ***
** Service (starter) Start **
** Activity (main) Create, isFirst = true **
** Activity (main) Resume **
R:9581
F:17391
M:8


10ms using Maps vs 10s & 18s for the other two methods. The difference is absolutely staggering!!!
 
Last edited:
Upvote 0
Top