There are three expensive calls with GroupAttributeFilter.getResults().
For the first, I've noticed in our environment, the substring query is the very least expensive part of this operation since that is just one query. What's more expensive is that for each result, there's a separate query for the group data in grouper_groups. We should see some performance improvements if this can be combined into one query that does a join between grouper_attributes and grouper_groups.
For the second, about 50% of the time spent in the call PrivilegeHelper.canViewGroups() is spent executing MemberFinder.findBySubject() within GrouperAccessAdapter.hasPriv(). Caching the Member object should provide improvements.
For the third, assuming the query is executed from the root stem, most of the time is spent in the Group.getParentStem() call within Stem.isChildGroup(). To save time in cases where the query is executed from the root stem, does it make sense to add a check for isRootStem() before calling Group.getParentStem()?
There may be more areas that can be improved here, but these are the main ones I've found so far.