Because CVS doesn't have atomic commits, cvs2svn.py has the difficult job of deducing them. It does this by examining RCS files and looking for per-file revisions with identical log messages. If two RCS revisions have the same log message, and were committed at nearly the same time (say, within a couple minutes of each other), then cvs2svn.py places them into a common change “group”, and commits the change-group to a new Subversion repository as a single revision.
The previous explanation is a bit of a simplification; there's much more bookkeeping to do than that. In fact, cvs2svn.py does its work in multiple “passes”, creating large amounts of temporary data on disk. If you interrupt the script, you can pass the -p option to script later on, indicating which pass to resume with.
Invoking the script is simple:
$ svnadmin create /new/svn/repos $ cvs2svn.py -s /new/svn/repos /cvs/repos …
The conversion take anywhere from several minutes to dozens of hours, depending on the size of your CVS repository. When run on Subversion's own CVS repository (the first year of Subversion's history, before it became self-hosting), it takes about 30 minutes, and commits about 3000 revisions to the Subversion repository.