We have to continue to do the existing object check, even for blobs.  This is a safety measure to prevent a SHA-1 collision from corrupting the local repository.

Normally when an object is added to a repository we compute the SHA-1 for it, then check to see if the object exists.  If it does, we don't create the new object, we instead rely upon the existing content.  This prevents an object that has the same SHA-1 but different content from entering the repository, so that it at least continues to return older content as expected.

However, here we are keeping the pack file as-is in the repository.  That means we may wind up with another copy of an already existing object.  In order to ensure we will continue to return the same content, we need to compare byte-for-byte.

Its slow, yes.  But its a safety feature that should never trip (in theory), and is one that we have to keep.