Button Bars as Layout level calculations...are there performance advantages?

Hi All,

Button Bars (FileMaker 14 and above) provide Layout Level calculations. Cool!

There are lots of use cases where Button Bars calculations can replace field calculations…
Has anyone done performance comparisons?

  • I would imagine that Button Bars calcs (using FMPA/FMG) might have less network traffic than field calcs
  • On the other hand, Button Bars calcs might have slightly more layout XML to render that layout fields

Thoughts?

1 Like

Great question. Don't have any answers. I can imagine that we could find advantages for both approaches if we tried hard enough :smiley:

Personally, I'm using calculations on the layout level in any object via the "hide object when" calculation dialog.

1 Like

somebody WireShark it!

1 Like

+1

1) Regarding network traffic:

My bet would be that, by far, the determining factor for overhead would be the calculation content itself, and not the mechanism which invokes the calculation. Given a button bar calc and a calculated field on the same layout, with the same calculation, I would anticipate the difference in generated network traffic to be comparable.

2) Regarding the button bar having more layout XML to define it:

I would agree this would seem likely to be the case, but I would only expect such additional overhead to be experienced around once per session, presumably when the layout information is downloaded to the client.

The above, however, is just speculation. I'd be happy to hear any arguments, suggestions, or evidence to the contrary.

-steve

4 Likes

What would be interesting to see is the comparison when FileMaker downloads 20 fields for the schema, and 20 button-bars vs FileMaker downloading 40 fields. Is there any benefit the first call to cache the structure? Is there any benefit on subsequent calls? I'm with you, all speculation until it's measured. Now, to find the time.

1 Like

great insight Steve - for layout calculations if printing isn't required an empty placeholder field or just a a merge-var auto-setting itself via conditional formatting could be comparable to button bars and be possibly leaner?

Hi @FileKraft

Great points. Yes -- my guess would be that, out of all the options mentioned so far, the button bar would be the heaviest in terms of data stored in the layout to define its rendering.

Earlier in this thread I neglected to mention that I used to love using the placeholder feature for this purpose, and, even when button bars were added to FMP, I still preferred it for a while, because I felt it would probably be leaner.

The progression of my own personal use of these techniques has gone something as follows:

Using merge variables, as you've described:

  • I believe I used the Hide Object When calculation to set the variable's value, instead of a conditional formatting calc.
  • I never did this in the body of a list view layout or in a portal row, because I did not find it to be 100% reliable.
  • I pretty much used it only in non-mission-critical settings, because I was always concerned that an under-the-hood change to how FMP renders layout objects would break the technique, and I didn't want another developer to inherit that from me.

Using placeholder fields as you've described:

  • When the Placeholder feature was introduced, I was crazy with delight because it felt like a solid way to have a layout-based display calc, that would work in form view, list view, and portals.
  • Basically, I thought it was a "sleeper" gem, and I was surprised not to hear about many other developers using it in this way.

Then the Button Bar was introduced:

  • While I acknowledged that this was one more option at our disposal for a layout display calc, I did not warm up to it at first, because I did not like the idea of having to use a button object to display my text when I did not need a script attached. It went against the grain of my sense of efficiency, and part of this was because, again as you've suggested, it felt less lean to me than a placeholder field (though I never checked).

  • With time, I eventually switched to using a script-less button bar segment, my reasoning being:

    • It did not require an empty field to attach the display to.
    • Conditional formatting was less cumbersome than with the placeholder field.
    • I was willing to consider the possibility that, while the button bar is probably a heavier option than the placeholder in terms of defining the object on the layout, the difference between these two objects might not be significant enough of a performance aspect to pursue if I did not have a high count of them on the layout.

Another aspect of these techniques that I consider:

A measure of how widespread the need for the displayed calculation is.

  • If I have some kind of calculation function that I am only going to need to display on one layout of a large solution, I am more likely to want that calculation out of the schema, and coded closer to (or at) the layout level.

  • If I have the same calculation function but I need to display it on many layouts within the solution, I am going to want to centralize that function, and not code it into every button bar.

In such a case I might still use a button bar calc, but I'd centralize the function's logic into a custom function.

If I am on a team that values older and simpler approaches, I might concede that it would be less cryptic for the next developer if I don't use a button bar that points to a custom function -- perhaps I could live with the calculation in the table, provided that it does not store a large amount of text that makes the record too heavy to pull across the network. Doing so would not be my first choice, however.

Personally, I am partial to the custom function approach:

Many examples that I have for this sort of feature are of the nature where a combination of status codes stored in the table is being translated into some more meaningful text to display to the user. I'd very much rather have that sort of "translation" logic outside of the schema, and instead keep it in a custom function where I find it easier to maintain, and also where it has the sort of separation from the data that I appreciate.

All the best & thank you for chiming in,

-steve

3 Likes

thank you for your brilliant review Steve - validating my observations precisely ..

1 Like

In this case I use global stored fields. Their content is calculated in layout related scripts. Those scripts are attached to the navigation for granular execution.

The fields reside in - my naming/convention - view tables, one row with only global fields serves all users. They are useful e.g. for sums if every user has its own foundset etc.

I choose this way because calculations become slow in server environments with millions of rows per table. On the other side everything is in tables and scripts - thus no problem for fellow developers, in bigger solutions there are up to 5 of them working on the same set of data/files.

2 cents from Holger

2 Likes

Sheesh... it was like reading an auto-biography. Pretty close to the same path for me.

2 Likes

As per @steve_ssh, we are moving to pulling data to layouts/records for local reference, often in a global field.

Typically, we're now using JSON, usually created using ExcecuteSQL, hence removing the need for TO links. Ironically, we've a very old legacy system that is starting to crawl that uses global fields, but with 5 conditional format conditions that remain necessary for functionality.

We're building the JSON at the moment and then may move from global fields to a button bar. If we have time, we'll use both and see if there is any noticeable difference in performance.

We've recently spent a lot of time on Bill of Material systems and varying cost ranges. Pulling the cost range data at the time the product is selected has resulted in a massive speed improvement compared to the old TOG references, as quantities are varied.

As previously stated, FileMaker is a bit of a minefield at the moment. There are many things you can do, but shouldn't.

Regards
Andy

Here is a rough summary of the thread, outlining the various way to implement various forms of "layout level calculations":

At the moment it is an open issue as to which of the choices below are most performant in various FileMaker platform deployments:

  • Client-Server
  • Web Direct

One of the thoughts/questions that prompted my original post, was how to maximize performance in a client-server environment…based on the hypothesis that network traffic is the likely the most important component to optimize. If an implementation only makes local calls to cached data and does NOT need to make a network call (with associated latency), then performance can be improved by making technically well informed decisions.

Some calculation will always requite a call to FileMaker Server. Other types might...or might not. Thus, the search for best practices!

At some point we all might jump to Wireshark Jumping the shark - Wikipedia

Button Bars

Pluses:

  • Offers states (hover, etc), and the ability to include a button or popover button (for example, to click for more information)
  • Could use a single name spaced $$var to contain multiple values that are parse out using the calculation engine
  • Easy to set/fix width and height

Minuses:

  • Might be heavier layout XML than other choices
  • Might not elegantly fit all use cases

Placeholder text

Pluses:

  • Might be lighter layout XML than a button bar
  • Could use a single name spaced $$var to contain multiple values

Minuses:

  • Requires a field, guaranteed to be empty (Should this be a global field?)

$$merge vars

Pluses:

  • Lightweight layout XML

Minuses:

  • Fills up the Data Viewer because it does not have full access to the calculation engine to parse a single $$var

Hide Object when

Pluses:

  • Might be more performant
  • Might offer a cleaner UI
  • Good for binary use cases

Minuses:

  • Does not scale well beyond binary choices

Global fields

Pluses:

  • Has a wide scope that $$var. Can be used (referenced) in a multi-file solution

Minuses:

  • Required fields

Thoughts?

5 Likes

Thanks for starting that list @tonywhitelive.

Merge Variables
Single $ variables work perfectly well in merge variables in Form View. They do not work in views that require the same variable to be displayed simultaneously, ie, list view, preview, table view. In other words, expect them to be rendered in exactly the same way as double dollar variables.

Hide Object when
The hide object calculation has the advantage that it appears to be given priority in layout rendering decisions. This makes it useful for more general purposes, such as populating variables using LET statements.

1 Like

here I would add redraw issues, you have to add more scriptsteps to ensure your change in data is rendered to the display

...
for Button Bars I would call it more of a hack, it's just not my way of programming using this as a workaround, for me it looks like a matter of feature request if one needs special behaviour added to the objects used for displaying content. But that is only my opinion :slight_smile:

...
as for Hide Object: I hate having different views of the same layout with extra white space when objects are hidden and the calculatio is "hidden" in the inspector but again this is only a personal preference

2 more cents for the weekend
Holger

1 Like

the very same here!

The exception being using name bucket variables. Same variable, different repetition. This allows for mostly dynamic display where records essentially retrieve their own variable.

2 Likes

Wait, I thought variable reps didn't work in merge variables.

I know you can do this within button bars though.

Correct. I was thinking more along the lines of the button-bar and not specifically a merge variable.

1 Like

Ah, I got really excited for a second and thought I was finally gonna learn the secret to displaying merge variable repetitions. DRAT!

Button bars are super cool though. Lately I'm really into using them to display ad hoc virtual list data. One advantage they have over virtual list fields is that the virtual list format does not have to be decided in advance. And you can use the same exact virtual list records to show data from different virtual lists at the same time (in portals for example).

One virtual list might be $$VL.people:

{"name": "Josh", "height": "8 feet"}
{"name": "Bijou", "height": "1 foot"}

and another might be $$VL.cars:

{"make": "Subaru", "model": "Forester"}
{"make": "Honda", "model": "Civic"}

And the button bar calculations can be totally dynamic (calculations below were fixed based on @steve_ssh ‘s next comment thanks mang!*)
1st portal would have button bars with:

JSONGetElement (
    GetValue ( $$VL.people ; VirtualList::n ) ;
    "name" 
)

2nd would be:

JSONGetElement (
    GetValue ( $$VL.cars ; VirtualList::n ) ;
    "make" 
)

I'm with all ya'll I've grown fonder and fonder of them for dynamic layout elements.

2 Likes

Hey @jwilling,

I love the example, but I must admit, I am confused by something that I hope you'll explain to me.

I was expecting to see the button bar calc be something like:

JSONGetElement (
    GetValue ( $$VL.people ; VirtualList::n ) ;
    "name"
) 

My thought was that the source variables, e.g. $$VL.people, are storing return-delimited lists of small JSON objects. Hence, the call to GetValue, along with the VL index from VirtualList::n, would grab one target object, and then the target value would be extracted with a path that is as simple as "name" or "make".

In other words, I'm trying to wrap my head around why there might be the added step of including an array index in the JSON path, and the only reason I could see would be if the source variables were storing a JSON Array instead of a CR-delimited list. But in such a case, I would not expect to see the use of GetValue.

Can you (or anyone) clue me in on what I am overlooking? It's morning here, and no caffeine yet, so maybe I'll see it 30 minutes from now. I'll come back to it... Thank you,

Sincerely,

-steve

3 Likes