I will make a guess that each bullet creates a new object (as I mentioned). In C++ and the like, first you have to allocate memory from the heap, then you have to instantiate it. Then each of them have to be cycled through for their movements. Then when they are done they get removed and flushed from the system. Not a problem when there's a few going on, or it does a bunch of them during a loading screen or something, but when it's happening constantly this is the sort of thing you get.
Of course it could just be the sheer number of objects and each bullet has to do a test to see if it hit something that could have been tiny, small, medium, large, or huge sized, and depending on if it's rotated.... not sure what kinds of calls are needed to the DirectX API for assigning them and having it draw them out....