Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending ByteArray from Worker cause Adobe Scout show incorrect memory consumption #402

Closed
itlancer opened this issue Jul 22, 2020 · 2 comments

Comments

@itlancer
Copy link

Problem Description

Sending ByteArray from Worker to main thread cause Adobe Scout show incorrect memory consumption.
Adobe Scout shows enormous memory allocations but actually it fake - Task Manager and other tools show that all fine, memory didn't increase.
This issue cause that we cannot profile and debug properly our applications that uses Workers.

It has been tested with multiple AIR versions (even with latest AIR 33.1.1.190), with different Windows, Android, iOS and macOS devices with different OS versions and latest Scout 1.1.3.354121.
Same problem in all cases.

Related issue (not the same): #347

Steps to Reproduce

Launch code below. It just start Worker that send to main thread big (just to see it clearly) ByteArray every second.
You should use Adobe Scout with enabled "Start sessions for ActionScript Workers" to see what happening:
image

Application example with sources and Scout .flm files attached.
scout_memory_bug.zip

package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.system.MessageChannel;
	import flash.system.Worker;
	import flash.system.WorkerDomain;
	import flash.utils.ByteArray;
	import flash.utils.setInterval;
	
	public class ScoutMemoryBug extends Sprite {
		private var toWorkerChannel:MessageChannel;
		private var fromWorkerChannel:MessageChannel;
		
		public function ScoutMemoryBug() {
			if (Worker.current.isPrimordial) {
				trace("start main");
				addEventListener(Event.ADDED_TO_STAGE, addedToStage);
			} else {
				startTimer();
			}
		}
		
		private function startTimer():void {
			trace("start worker");
			const worker:Worker = Worker.current;
			
			toWorkerChannel = worker.getSharedProperty("from");
			fromWorkerChannel = worker.getSharedProperty("to");
			
			setInterval(function():void {
				trace("send message");
				const byteArray:ByteArray = new ByteArray();
				for (var i:uint = 0; i < 10000000; i++){
					byteArray.writeFloat(100);
				}
				
				toWorkerChannel.send(byteArray);
				byteArray.clear();
				byteArray.length = 0;
			}, 1000);
		}
		
		private function addedToStage(e:Event):void {
			removeEventListener(Event.ADDED_TO_STAGE, addedToStage);
			
			const worker:Worker = WorkerDomain.current.createWorker(loaderInfo.bytes, true);
			
			toWorkerChannel = Worker.current.createMessageChannel(worker);
			fromWorkerChannel = worker.createMessageChannel(Worker.current);
			
			worker.setSharedProperty("to", toWorkerChannel);
			worker.setSharedProperty("from", fromWorkerChannel);
			
			fromWorkerChannel.addEventListener(Event.CHANNEL_MESSAGE, fromWorkerChannel_channelMessage);
			
			if (worker != Worker.current) {
				worker.start();
			} else {
				startTimer();
			}
		}
		
		private function fromWorkerChannel_channelMessage(e:Event):void {
			trace("receive message");
			
			const messageChannel:MessageChannel = e.currentTarget as MessageChannel;
			const byteArray:ByteArray = messageChannel.receive() as ByteArray;
			
			trace("bytes:", byteArray.length);
			
			byteArray.clear();
			byteArray.length = 0;
		}
	}
}

Actual Result:
In Adobe Scout (for both: main thread and Worker) you will see enormous memory consumption by "ByteArrays" and "Other". About 7-8 GB RAM after 1 minute. But via Task Manager (or any other similar tools) you can see that there is no any memory leaks - application consumes stable ~130 MB RAM (for Windows device).
image

Expected Result:
Adobe Scout show non memory leaks because all ByteArrays cleared after sending/receiving.

Known Workarounds

none

@ajwfrost
Copy link
Collaborator

This is happening due to the signal from the runtime to say that a byte array has been allocated, but no corresponding report to say it's been deleted. There appear to actually be two problems:

  1. when a new reference to an existing buffer is created, it's reporting a new allocation (but we should only report the allocation if the new memory buffer was requested i.e. where the initial buffer object is set up)
  2. when the byte array is received by the worker in the message handler, there's another copy being made but this isn't being flagged on the destruction of this due to the allocation happening in a different thread

So we should be able to sort this out, the only slight caveat is that we can't properly track memory allocations that are done on one thread and are released on another; but we can do enough to make the Scout numbers add up. And a lot of that would happen in a single frame anyway so you'd not notice anything looking at frame-by-frame numbers...

thanks

@itlancer
Copy link
Author

itlancer commented Aug 1, 2022

Fixed with AIR 33.1.1.926.
Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants