EFS runs on a system of IO credits, these credits are generated constantly throughout the day based on the amount of space you are using in EFS.
Every time you read or write to an EFS volume you consume these credits. If you have no IO credits in your balance, reads and writes will wait until you do.
I think it's somewhat likely, you've managed to use up all your credits, and the background IO keeps depleting your credits, keeping performance horrendous.
You can check the number of credits an EFS volume has by checking cloudwatch.
Just to clarify this a little more. If you were only using 1GiB on an EFS disk, any time you read/wrote at a rate exceeding 50KiB/s you would burn through credits, and any time you read/wrote a rate lower than 50KiB/s you would generate credits.
In comparison by having 10GiB in an EFS disk you would be able to sustain 500KiB/s.
I'm utilising EFS with one service, and found I had to generate roughly 80GiB of raw useless data, which just sits on the EFS disk to generate enough IO credits to allow my application to use the share.
I set up a cloudwatch alarm to notify me if my credits ever fall below a threshold, to give me time to add some more 'useless data' to the EFS disk to allow me to sustain usual performance.
I recommend reading Amazon's official suggestions on EFS throughput scaling if you think this effects you.
Edit:
AWS now supports provisioned throughput for EFS, although that doesn't save any money from above approach and requires an understanding of expected throughput, or overestimating usage. Details of this are covered in the linked documentation.