How the render loop works is basically like this:
1. Process any messages/actions etc, and update the UI state accordingly.
2. Increment the frame timer for animation etc.
3. Run through all controls and process them. This updates visibility states, updates animation states, updates any sizing, infolabels, colors, starts loading any background textures, or loads on-thread any textures for controls that don't bg load and computes dirty regions.
4. Render if required by dirty-regions (no regions, no render).
Note that number 3 in particular happens once a frame
even if nothing changes on screen. Dirty regions just saves having to bother rendering everything again, it doesn't save having to work out if anything has changed.
Visible conditions:
Generally they're evaluated for each control every app loop. So one simple way to reduce them is if they can be done on a group, then do it on the group rather than on each control in the group. There is a cache, however, so they're only actually "worked out" once per frame. e.g. the "Control.HasFocus(10)" is worked out only once, and the result (true/false) is stored. Thus, by reducing them to be done on a group rather than on all controls in the group, what you're doing is saving the lookups into that cache, and the function calls etc. that result. As we move forward, the cache will become more efficient as more variables move to being updated only as needed, rather than every frame.
Some visible conditions are faster than others. Anything that involves some sort of a string processing is slow whereas anything that is basically just a "look up this" where "this" is a boolean state is normally not too bad. Obviously this is a massive generalisation.
Info labels are not cached per frame, so two or more controls using them will look them up separately. Variables, though, are cached, i.e. they're only evaluated once per frame, so a variable that takes the place of a bunch of the same info label lookups might be more efficient (only might, as you're still looking up that variable multiple times).
Images/textures
The texture managers store a single instance of each texture. Those textures are then shared between controls. Thus, the loading is only ever done once - it's essentially free to use the same texture multiple times on the same window (other than render + setup costs). So icon and it's reflection is a single load (though you're typically diffusing the reflection, so if the diffuse isn't loaded it's 2 anyway).
ID numbers
Generally, IDs should be used where it makes sense. If it doesn't make sense, leaving them blank doesn't hurt in any way. i.e. you need an ID if you're referencing a control or listitem. You don't if you're not. For controls, it's slightly more efficient to not have an ID for controls that don't need one (generally anything that you don't navigate to, or don't need to lookup for conditionals). This is because we use a map for ID lookup so all the "no id" controls get dumped into a bucket that is effectively ignored, meaning the map size is smaller, so lookup is quicker.
Maybe we should wiki-fy this
Cheers,
Jonathan