Exec a function as background task?

I want to execute a function several times in the background while there is a scene rotating in the update loop
The loop is i.e. working without jerks while there are textures loaded in the background (scene.background.needsUpdate = true;)

Is there a possibility to execute a function call from within the loop which is working also in the background and sets a variable to 1 when finished?
The update loop shall check that variable each frame until it is set to 1 and then display that what was created in the background.

Sounds like you want to run some logic in a web worker.

This kind of check is not required when using web workers since you can rely on event listeners instead.

1 Like

Until 5 Minutes ago I had no idea what web workers are and that such thing exists :wink:

Mugen87 - Thank you for this interesting hint. On first sight after looking it up at w3schools.com I get an idea what is meant.
Actually I want to start the generation of the threejs geometry text in the background - because the way I use it now makes the rotation of the mesh stop for half a second
Have to find out how it works and how to use it … but seems to be exact the thing I needed to know
:+1:

For this kind of job, new THREE.ImageBitmapLoader() is better choice for now. If all modern bowsers supported OffscreenCanvas, then Web Workers would be the first choice.

When applying texture at run time, three elements can cause bottleneck:

  • Downloading Image
  • Decoding image
  • uploading image to GPU.

UsuallyUploading Data To GPU is the main culprit that kills you FPS for few milliseconds.

Good answer :+1:
I may add the troika bitmap text system later as well.
But in my case its not about loading images but generating Text which makes the system a bit jerky as to be seen here

:wink:

That’s quite an interesting observation. In my experience the decode is way more costly. Decode is typically done on the CPU, and involves copying/moving a lot of data, in case of PNG for example that would be transformation and decompression, both of which are at least 1 data copy (more actually). Whereas uploading data to the GPU is a driver op, and a potential copy. On the hardware level PCIE is a pretty fast bus, I guess mobile devices would differ, but GPU/CPU interface should be pretty snappy there too.

1 Like

My bad, I misread your post. Looking at the source, I see you have alot going on the animation.
Since the font generated mesh is used only in 2D context, I suggest using a semi-transparent overlaid DIV, witch you can change its textContent.

To be honest I don’t script for mobiles, usually they get redirected to a friendly exit.

Any format that is supported by browser is done with CPU.
About cost factor, I would have agreed with you a decade ago, but todays browsers can decode an image file in mater of handful of milliseconds.

https://raw.githubusercontent.com/mrdoob/three.js/dev/examples/textures/terrain/grasslight-big.jpg

File size: 2.6Meg
Dimension: 2048x2048

Decode on my machine: 41ms

@ 60 FPS
On Chrome no effect on time between animation frames.

On FireFox there is single jump form 16.7 to 54 ms.

What do you say to that Alex?

1 Like

That’s about in line with what I have experienced too. There are variations depending on the OS, CPU and RAM, but generally - yes.

PNG is a lot more expensive to decode than JPEG though.

Why that matters - JPEG is a lossy compression format, so if you’re using that for your textures - you’re already not concerned with optimization. If quality mattered to you - you’d go with PNG, and if you wanted to save some GPU memory - you’d go with a compressed texture format (that doesn’t need to be decoded by the way). The only scenario, that I can imagine, where you’d use JPEG intentionally is when you really really want to save some bandwidth.

Even then, 41ms for 2048x204 RGB pixels, that would result in 12,582,912 bytes of decoded data. Uploading 12Mb of data to GPU, in my experience takes way less than 41ms.

1 Like

You mean 16,777,216

That was the time to decode the image, please pay attention to details.

Sorry in my experience is a foreign tongue to me. Perhaps it can be replaced with actual bench marks and data.

How long it takes for data to be transferred depends on:

  • Size of data
  • Device data transfer rate
  • Load on device at exchange

For that Jpeg to be loaded on a devices with transfer rate of 8 Gbps, it would take 16.77 milliseconds.

Not really, it’s slightly higher than jpegs at similar size and dimensions.

https://threejs.org/examples/textures/planets/earth_clouds_2048.png

Size 4.4 Meg, decoded in 48 ms
Again, with chrome no impact on main thread when swapping textures.

Good job V8 on multi threading

I feel like I a struck a nerve. Sorry about that.

Here’s what google says about 2048 pixels multiplied by 2048 pixels multiplied by 3 channels 1 byte each:
image

JPEG format does not carry transparency, at least to my knowledge, but hey - who knows, perhaps there are some provisions for that. I never seen them though.

…and a whole lot of other things, OS, driver, temperature in the room. I’m not sure I see the point of listing those things though.

I’ll answer one more point, as it seems to be a simple misunderstanding (at least I choose to interpret it as such). I said

And you seem to think that I misunderstood you, when you were talking about decode times, that I have taken it as you talking about upload times. I didn’t. I was making a claim that, if we take 41ms to be some reference decode time for a 2048x2048 image, then it’s safe to assume that upload time would be lower than the stated 41ms number.

Okay, so you insisted on numbers in a way that you did. So here they are:

I took a few samples just in case you claim this to be an outlier:
3.5
3.0
2.5
2.6
3.0

Hopefully, it’s clear that the cold run was 6.5, and the other ones were taken after that.
Data is randomized, to prevent caching shenanigans.

So, assuming the region of memory that you’re trying to upload is already mapped - it takes ~3ms

I am using the RGBA format here, because three.js recently axed RGB (kinda, sorta, for good(?) reasons). So multiply the resulting upload times by 3/4.

If you have something on the topic - please share. Otherwise, I don’t want to have a flame war, feel free to assume whatever you wish about my character and the quality of my claims.

You don’t know me, I don’t know you. I think you’re an interesting guy, you made a claim that was counter to my experience, so I wanted to know more, nothing else. Have a great day.

1 Like

During decoding process, image is converted to 32-bit bitmap. That means 2048×2048 image is turn to a pixel array of 4194304 elements. Each element presents a pixel having four slots for each channels [ 0 … 255 ]. If format does not support transparency, the forth slot is populated with 255.

In computer world add/remove data to end of block is cheap. Adding data to middle or beginning is expespensive. Removing every 4th element to save 25% in bandwidth just crazy.

Sorry man, the number you have posted are most likely the time in millisecond for creating Typed_Array data.

var tik = performance.now();
var _ab = new Uint8Array( 2048*2048*4 );
_ab.fill(255);
alert( Math.round( performance.now() - tik ) + ' ms' );

Compare these numbers with yours.
I think, I have spent enough time here, so I’ll make this my last post.