Почему putImageData такой медленный?

Я работаю с относительно большим холстом, на котором нарисованы различные (сложные) вещи. Затем я хочу сохранить состояние холста, чтобы я мог быстро сбросить его до состояния, в котором он сейчас находится, позже. Для этого я использую getImageData и храню данные в переменной. Затем я рисую еще что-то на холсте и позже сбрасываю холст туда, где он был, когда я сохранил его состояние, используя putImageData.

Однако оказывается, что putImageData выполняется очень медленно. Фактически, это медленнее, чем просто перерисовка всего холста с нуля, что включает в себя несколько операций drawImage, покрывающих большую часть поверхности, и более 40 000 операций lineTo, за которыми следуют обводки и заливки.

Перерисовка холста размером примерно 2000 x 5000 пикселей с нуля занимает ~ 170 мс, при использовании putImageData требуется целых 240 мс. Почему putImageData такой медленный по сравнению с перерисовкой холста, хотя перерисовка холста включает заполнение почти всего холста с помощью drawImage, а затем повторное заполнение примерно 50% холста полигонами с помощью lineTo, обводки и заливки. Таким образом, практически каждый пиксель затрагивается хотя бы один раз при перерисовке.

Поскольку drawImage кажется намного быстрее, чем putImageData (в конце концов, часть drawImage для перерисовки холста занимает менее 30 мс). Я решил попытаться сохранить состояние холста, не используя getImageData, а вместо этого используя canvas.toDataURL, а затем создав изображение из URL-адреса данных, которое я вставил бы в drawImage, чтобы нарисовать его на холсте. Оказывается, вся эта процедура намного быстрее и занимает всего около 35 мсек.

Так почему же putImageData намного медленнее, чем альтернативы (с использованием getDataURL или простой перерисовкой)? Как я могу ускорить процесс? Есть ли и если, как вообще лучше всего сохранить состояние холста?

(Все числа измеряются с помощью Firebug из Firefox)

37
задан Daniel Baulig 11 August 2014 в 20:45
поделиться