Bonjour

J'ai un worker, qui dessine une image sur des canvas.

C'est un code simplifié, en vrai je passe à mon worker l'url du png qu'il doit dessiner à chaque postMessage.

index.html
Code html : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
 
        <link rel="stylesheet" href="https://cdn.webix.com/edge/webix.css" type="text/css">
        <script src="https://cdn.webix.com/edge/webix.js" type="text/javascript"></script>
 
    </head>
<body>
 
 
 
    <style>
        
    body {
        overflow: hidden;
    }
 
    </style>
 
    <div id="anchor" style="position:absolute"></div>
 
    <script>
    
        let world = // fold
        { 
            _frames : 0,
            _now : undefined,
            _before : new Date(),
 
            update:function() {
                
                // do some things
                
                world._now = new Date();
                
                if (world._now - world._before > 1000) {
                    $$("framerate").define("value", world._frames);
                    $$("framerate").refresh();
                    world._before = world._now;
                    world._frames = 0;
                } else {
                    world._frames++;
                }
                
            },
 
            loop:function() {
                
                world.update();
                
                requestAnimationFrame(world.loop);
            },
        };
        
        webix.ready(function() {
                
            // window avec text en haut à droite
            webix.ui( // fold
            {
                view:"window",
                head:false,
                autofit:true,
                zIndex:2000,
                body:{
                    id:'framerate',
                    view:"text", 
                    value:"", 
                    readonly:true,
                    labelWidth:0,  
                    width:100,
                    tooltip:'FPS',
                },
                css:{
                    'background-color': 'transparent !important',
                    'box-shadow': 'none !important'
                },
                borderless:true,
                
            }).show({ x:window.innerWidth-108, y:7 });
    
            world.loop();
            
            var worker = new Worker('./vorker.js');
            
            worker.postMessage({type:'preload', arr:[{key:"myKey", url:'url_de_mon_png'}]})
            
            // je prépare les canvas en amont pour être bien sûr que ce n'est pas ça qui fait chuter mes FPS
            let canvases = [];
            let data = [];
                        
            for (let i=0; i<2000; i++) {
                canvases[i] = document.createElement('canvas');
                document.getElementById("anchor").appendChild(canvases[i]);
                canvases[i].style.position = "absolute";
                canvases[i].style.left = Math.random() * 500 + "px";
                canvases[i].style.top = Math.random() * 500 + "px";
                data.push(canvases[i].transferControlToOffscreen());
            }
            
            document.onkeydown = function checkKey(e) {
                
                if (e.keyCode == 65) // A
                    worker.postMessage({type:'draw', canvases:data, key:"myKey"}, data);
                
            }
        });
        
 
    </script>
 
</body>
</html>

vorker.js
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
self._preloadedImages = [];
 
self.addEventListener('message', async event => {
 
    if (event.data.type === 'preload') // fold
    {
        let toLoad = event.data.arr.length;
 
        for (let i=0; i<event.data.arr.length; i++) {
 
            fetch(event.data.arr[i].url)
                .then(function (response) {
                    return response.blob();
                })
                .then(function (blob) {
                    return createImageBitmap(blob);
                })
                .then(function (imgBitMap) {
                    self._preloadedImages[event.data.arr[i].key] = imgBitMap; 
                    toLoad -= 1;
                    if (toLoad == 0) 
                        console.log('loaded');
                })
            }
    } 
 
    else if (event.data.type === 'draw') 
    {
        let t = new Date();
 
        let canvases = event.data.canvases;
 
        const img = self._preloadedImages[event.data.key];
 
        for (let i=0; i<canvases.length; i++) {
 
            let canvas = canvases[i];
 
            canvas.width = img.width;
    	    canvas.height = img.height;
 
            canvas.getContext('2d').drawImage(
                img,
                0,                                              // soruce image X
                0,                                              // sourice image y
                img.width,                                      // source width
                img.height,                                     // source height
                0,                                              // destination x
                0,                                              // destination y
                img.width,                                      // destination width
                img.height                                      // destination height
            );
        }
 
        console.log('temps wrker', new Date() - t);
 
    }
});
Sur des petites opérations, le worker fait très bien le travail, mais si j'ai 2000 images à dessiner (environ des images de 60x60.. Pour l'instant !), le framerate de mon thread principal est affecté, j'ai des baisses jusqu'à 20 FPS. J'ai déjà essayé de passer les offscreenCanvas en amont également, en pensant que c'était le passage en référence de data qui mettait la pagaille, mais en fait non.

Serais-je arrivé à la limite des workers, déjà ?