Open agamemnus opened 10 years ago
Hello Agamenus
In order to attend this issue we need a test case, can you upload a simple test that reproduces the issue?
All right. I made a small test case but it still contains somewhat sensitive code. What is the best email I can use to send you the test case?
All right... I will attach a non-sensitive version here.
<!DOCTYPE html>
<html lang="en">
<head>
<script type="text/javascript" src = "cocoon.min.js"></script>
</head>
<body>
<script type="text/javascript">
// 1) Path drawing is slower in Webview+ vs. Webview.
// 2) Clip is slower in Webview+ vs. Webview.
// 3) DrawImage inside of "apply_3d_effect" is slower in Webview+ vs. Webview.
var t1 = +new Date ()
for (var i = 0; i < 40; i++) {
var canvas1 = document.createElement ('canvas')
var ctx1 = canvas1.getContext ('2d')
canvas1.width = 340
canvas1.height = 270
var shape_string = "M 0.0000,250.3895 L 0.0000,250.3895 0.0000,0.0000 L 0.0000,0.0000 275.0000,0.0000 C 219.8988,147.4189 335.8291,44.0002 335.8291,110.0002 C 335.8291,176.0002 186.3356,7.3333 235.8444,275.0002 C 57.2933,243.0562 176.0000,193.7555 110.0000,193.7555 C 44.0000,193.7555 158.0330,250.6112 0.0000,250.3895 z"
//ctx1.save ()
canvas_draw_path ({
x : 0,
y : 0,
data : shape_string,
fillColor : 'rgba(0,127,0,1)',
strokeColor : 'rgba(63,63,63,1)',
lineCap : 'round',
strokeWidth : 0,
canvas : canvas1
})
//ctx1.clip ()
//apply_3d_effect ({canvas: canvas1, stroke_width: 1, cut_multiplier: 1, shape_string: shape_string}) <-- give me a good email to obtain this sekrit function.
}
alert (+new Date () - t1)
document.body.appendChild (canvas1)
// Create a simple SVG path from a string and draw it onto a canvas. Derived from kineticJS under MIT license.
function canvas_draw_path (init) {
var x = init.x || 0
var y = init.y || 0
var data_string = init.data
var canvas = init.canvas
var data_array = get_data_array_from_string (data_string)
draw_func (data_array, canvas)
function draw_func (data_array, canvas) {
var context = canvas.getContext('2d')
if (typeof init.strokeWidth != "undefined") context.lineWidth = init.strokeWidth
if (typeof init.strokeColor != "undefined") context.strokeStyle = init.strokeColor
if (typeof init.lineCap != "undefined") context.lineCap = init.lineCap
context.beginPath ()
context.translate (init.x, init.y)
for (var n = 0; n < data_array.length; n++) {
var c = data_array[n].command
var p = data_array[n].points
switch (c) {
case 'L' : context.lineTo (p[0], p[1]); break
case 'M' : context.moveTo (p[0], p[1]); break
case 'C' : context.bezierCurveTo (p[0], p[1], p[2], p[3], p[4], p[5]); break
case 'z' : context.closePath (); break
}
}
if ((typeof init.strokeWidth == "undefined") || (init.strokeWidth != 0)) context.stroke ()
if ((typeof init.fillPatternImage != "undefined") || (typeof init.fillColor != "undefined")) {
if (typeof init.fillPatternImage != "undefined") {
var pattern = context.createPattern(init.fillPatternImage, 'no-repeat')
if (typeof init.fillPatternOffset != "undefined") {
context.save ()
context.translate (-init.fillPatternOffset[0], 0)
context.translate (0, -init.fillPatternOffset[1])
}
context.fillStyle = pattern
} else {
// fillColor is subordinate to fillPatternImage.
context.fillStyle = init.fillColor
}
context.fill ()
}
if (typeof init.fillPatternOffset != "undefined") context.restore ()
}
function get_data_array_from_string (data_string) {
// Command string.
var cs = data_string
// Command chars.
var cc = ['M', 'L', 'C']
// Convert white spaces to commas.
cs = cs.replace (new RegExp(' ', 'g'), ',')
// Create pipes so that we can split the data.
for (var n = 0; n < cc.length; n++) {cs = cs.replace (new RegExp(cc[n], 'g'), '|' + cc[n])}
// Create the array.
var arr = cs.split('|')
var ca = []
// Init the context point.
var cpx = 0, cpy = 0
for (n = 1; n < arr.length; n++) {
var str = arr[n]
var c = str.charAt(0)
str = str.slice(1)
// Remove ,- for consistency.
str = str.replace (new RegExp(',-', 'g'), '-')
// Add commas so that it's easy to split.
str = str.replace (new RegExp('-', 'g'), ',-')
str = str.replace (new RegExp('e,-', 'g'), 'e-')
var p = str.split(',')
if (p.length > 0 && p[0] === '') p.shift()
// Convert strings to floats.
for (var i = 0; i < p.length; i++) {p[i] = parseFloat(p[i])}
while (p.length > 0) {
if (isNaN(p[0])) break // Case for a trailing comma before next command.
var cmd = null
var points = []
var startX = cpx, startY = cpy
switch (c) {
case 'L' :
cpx = p.shift ()
cpy = p.shift ()
points.push (cpx, cpy)
break
case 'M' :
// Subsequent points are treated as absolute lineTo.
cpx = p.shift ()
cpy = p.shift ()
cmd = 'M'
points.push (cpx, cpy)
c = 'L'
break
case 'C' :
points.push (p.shift(), p.shift(), p.shift(), p.shift())
cpx = p.shift ()
cpy = p.shift ()
points.push (cpx, cpy)
break
}
ca.push ({
command : cmd || c,
points : points,
start : {x: startX, y: startY}
})
}
if ((c === 'z') || (c === 'Z')) ca.push ({command: 'z', points: [], start: undefined})
}
return ca
}
}
</script>
</body>
</html>
Bump...
It would help if you could say something about this... like "we're working on it", or "the testcase looks fine on our end", etc..
@agamemnus I can't comment on the specifics of your code, but I've found in my projects that slow canvas speeds were directly related to my coding. It's frustrating because using a desktop browser it'll often run my "bad" code at an acceptable speed, but then when wrapped with the webview+ the issues present themselves on an actual device. I have fixed all of my canvas speed issues by improving my code. It might also be helpful to add that I use EaselJS (https://github.com/CreateJS/EaselJS/) for all of my canvas stuff.
Sure, and I managed to increase performance by batching the effects. It's still 4-5x slower in Webview+ versus Webview (not versus PC).
Hmm, that's strange. I've never seen the webview+ go slower than the native webview (even the improved 4.4.2 version). What I would do to debug the problem is use the Chrome profiler to debug the application on device and see what exactly is using the most cpu processing power.
It is all in the drawImage, but only happens with the clip operatIons and Bezier curves. The clip operation and Bezier curve commands themselves are not slower, but the drawImage is. I have a suspicion that webview+ sends canvas textures to the gpu and then back again unnecessarily for some reason.
It looks like setting a high shadowBlur value for a shadow makes Webview+ and Canvas subsequent related drawing operations extremely slow.... anyone working on this? :-(
Shadow and box-shadow are very expensive to use, especially on mobile devices. If I remember correctly the size of the shadow exponentially decreased performance as well. I think this is a much larger issue than the webview+. We actually had to entirely remove them from our app on mobile.
Ugh. Well, what doesn't make sense here is why Webview+ is so slow and Webview isn't, at least for that. For everything else Webview+ seems much faster. Could it be that Webview is using the CPU to compute the blurring and Webview+ is using the GPU? (and the GPU maybe can't handle it as well)
I wonder if there is a switch for that.
How many devices have you tested it on? Android 4.4.2 can be a bit deceiving because they improved the webview, but using any version before that the issues with the webview are very visible in comparison to the webview+.
I don't know if the webview+ uses it or not, but when I use crosswalk (https://crosswalk-project.org/) I have to specifically force the gpu by disabling the gpu black list --ignore-gpu-blacklist
. This might be a valid questions for @ludei. Here is the link to the list of chromium flags:
Ok, thanks. Just my Note 2, 4.4.2.. theoretically Webview+ is even more advanced than 4.4.2's Chromium. Possibly it's a bug in Chromium, but not sure how to rebuild with a different Chromium base.
So, this might be a Chromium bug, or at least partly... but it's not consistent across devices. Perhaps something to do with GPU hardware acceleration of shadows plus a Chromium bug somewhere? I made a bug report if you'd like to star it...
I'll keep this issue open until the next major release of Webview+ that may solve this problem.
About 4 times slower... 4 times.
To test.. I dunno, I dunno... I can send you my APK or zip file to test...
Android 4.4.2 here, Note 2.