It's not easy to tell in the absence of test data how big this hash is, or how many time these loops iterate, but given the sizes of the data files mentioned in the OP, and the timing information you've supplied above, it appears that they may be substantial. #### The next thing I looked at was the section of code where you 'band pass' filter the matches into a temporary array. #### Finally (for now), you use this construct: %{ $sets{ $fasta_id }[ $setscounter ] } = (); To empty arrays in several places. Whilst there is nothing wrong with this, I think it is clearer, and may be slightly quicker to use undef $sets{ $fasta_id }[ $setscounter ] };