I found that the pattern from zx81
$re_dq_answer = '/="(?:[^"]|"")*"/'
results in backtracking after every single matched character. I found that I could adapt the pattern found at the very top of my question to suit my need.
$re_dq_orignal = '/="[^"\\\\]*(?:\\\\.[^"\\\\]*)*"/s';
becomes
$re_dq_modified = '/="([^"]*(?:""[^"]*)*)"/';
The 's' pattern modifier isn't necessary because the pattern does not using the \s metacharacter.
The longest string I have had to match was 28,000 characters which caused Apache to crash on a stackoverflow. I had to increase the stack size to 32MB (linux default is 8mb, windows is 1mb) just to get by! I didn't want every thread to have this large stack size, so I started looking for a better solution.
Example (tested on Regex101): A string (length=3,200) which required 6,637 steps to match using $re_dq_answer now requires 141 steps using $re_dq_modified. Slight improvement I'd say!