You can do:
my $num_users = $users->count;
The object is also numerically overloaded to return the count:
my $num_users = $users + 0;
For reference, see https://metacpan.org/module/DBIx::Class::ResultSet#count.
UPDATE: On why resultset needs to issue a separate query to get the count.
Note the main description of the resultset class:
A ResultSet is an object which stores a set of conditions representing a query. It is the backbone of DBIx::Class (i.e. the really important/useful bit).
No SQL is executed on the database when a ResultSet is created, it just stores all the conditions needed to create the query.
...
The query that the ResultSet represents is only executed against the database when these methods are called: "find", "next", "all", "first", "single", "count".
In other words, the resultset doesn't have the count until it queries for it.
When you iterate through the resultset using next
it will keep a stash of the records it has read from the database, but it will discard those records as it gives them to you, which means it can't give you the count from what it has read. You need to ask for them to be cached if you want to do that.
my $resultset = $schema->resultset('Artist')->search( undef, { cache => 1 } );
my @records = $resultset->all;
my $count = $resultset->count; # this uses the count of the cached records