AclEntryAfterInvocationCollectionFilteringProvider is very slow for 2 reasons:
1.) The hasPermission(Authentication, Object) method in AbstractAclProvider is called once for every object in the collection being filtered, which in turn calls aclService.readAclById(..). The net result is that if the Acl cache is empty (or doesn't yet contain Acls for the domain objects being checked) an Acl query to the database will occur for each item in the Collection. This is inefficient and gets very slow when filtering large collections. Since AclService supports looking up more than one Acl at a time, it makes more sense to collect a batch of ObjectIdentities and perform a lookup on the batch.
2.) CollectionFilterer which is used by AclEntryAfterInvocationCollectionFilteringProvider to remove objects from the Collection being filtered exhibits O(n^2) performance when the collection being filtered has only sequential access (i.e. LinkedList or ArrayList). This is because a Set of objects to be removed from the collection is collected during iteration, and then each is removed when getFilteredObject() is called.
I've written a AclEntryAfterInvocationCollectionBatchingFilteringProvider and a FastCollectionFilterer plus some unit tests to solve these problems. In our application when the AclCache is empty filtering ~3500 objects went from ~9sec down to ~2sec.