Flex string never cleared from the memory --> It is cleared eventually - json

I have this weird problem for a while and try to solve it to look up on the net for proper solution but still I am clueless.
When I check my application's memory usage with flex profiler (4.6) the portion of String keep increasing and eventually reach the point of crash.
And I pin pointed where this increasing occurs from my application's source code.
It is the local string variable that I passed to Json.decode(). It never cleared.
All the instance of the json string that I got from the socket server remains in the memory til app crashes even if profiler says there is 0 path to the String.
I don't know how to clear these Strings. It only keeps growing.
Please help me. I have been struggled with this for a week now.
Thanks for any support in advance.
portion of my source code that I think the source of the leak is as following.
protected function evtserverReseved(event:ProgressEvent):void{
var tmpArr:ByteArray = new ByteArray();
var tempByteArray:ByteArray = new ByteArray();
socEvtServer.readBytes(tmpArr, 0, socEvtServer.bytesAvailable);
tempByteArray.writeBytes(leftOverMessageNotify, 0, leftOverMessageNotify.length);
tempByteArray.writeBytes(tmpArr, 0, tmpArr.length);
leftOverMessageNotify = new ByteArray();
parseByteArray(tempByteArray);
}
private function parseByteArray(rawArray:ByteArray):void{
if(( rawArray[0] == 0x30 || rawArray[0] == 0x31 ) && rawArray[1] == 0x00 ){
var log:String = "";
for(var i:int=0; i<16; i++){
if(rawArray[i]==0){
}else{
log += rawArray[i]-48;
}
}
sizeOfFullListNotify = uint(log);
commonFunction.printLog("Event Server eventNotify sizeOfFullListNotify=" + sizeOfFullListNotify);
rawArray.position = 16;
}
var tempIdx:uint = rawArray.position;
var tempLength:uint = rawArray.length;
if(sizeOfFullListNotify <= tempLength - tempIdx){
var tempArray:ByteArray = new ByteArray();
var tempLeftOver:ByteArray = new ByteArray();
var j:uint;
for(j=0; j <sizeOfFullListNotify ; j++){
tempArray[j] = rawArray[j+tempIdx];
}
var euckrString:Object = tempArray.readMultiByte( tempArray.length,"euc-kr").replace(" ","").replace("\n","");
//commonFunction.printLog("Total memory=" + flash.system.System.totalMemory +", Free memory=" + flash.system.System.freeMemory + ", Event Server eventNotify JSON 수신 data size=" +euckrString.toString().length+ ", body=" + euckrString.toString() );
var ob:Object = com.adobe.serialization.json.JSON.decode(euckrString.toString());
commonFunction.printLog("Total memory=" + flash.system.System.totalMemory +", Free memory=" + flash.system.System.freeMemory + ", Event Server eventNotify JSON data size=" +euckrString.length+ ", body=" + euckrString );
if(ob.method != null){
//gridBox.DT_HOUSE.addItemAt(ob,0);
gridBox.DT_HOUSE.push(ob);
totlaReceivedList++;
}else if(!(ob.result is String)){
//confirm for registerEventNotify
commonFunction.printLog("confirm for registerEventNotify");
}
if(sizeOfFullListNotify < tempLength - tempIdx){
for(var k:uint=0; k <tempLength-tempIdx-sizeOfFullListNotify ; k++){
tempLeftOver[k] = rawArray[k+j+tempIdx];
}
parseByteArray(tempLeftOver);
}else{
//leftOverMessageNotify = new ByteArray();
}
}else{
//leftOverMessageNotify = rawArray;
for(var i:int = 0 ; i<rawArray.length ; i++){
leftOverMessageNotify[i] = rawArray[i];
}
rawArray = null;
}
}
var euckrString:Object(String) is the portion that never cleared from the memory.
It keeps stacking till crashes.

Related

How to write a sequence of bytes to binary file using JScript?

I'm trying to write Array(1, 2) to binary file as bytes.
So output file should contain 00000001 00000010.
I understood that I have to use ADODB.Stream, but I haven't found any solution for such simple task.
var data = new Array(1, 2)
out = WScript.CreateObject("ADODB.Stream")
out.Type = 1
out.Open()
out.Write(data)
out.SaveToFile("output.bin", 2)
out.Close()
Code above gives error:
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
Any ideas how to convert data array to acceptable type?
You can use the WriteAll function described here: Reading and Writing Binary Files Using JScript. Copyright: Dr Alexander J Turner.
Please note, the Stream shall be of type text, and then you will need to do the text<->binary conversion.
I just tested all the code and it worked fine for me.
Here is a complete example:
var bf1 = new BinaryFile("C:/Temp/test.bin");
var outBuf = '';
for(var i=0, l=data.length; i<l; i++) {
outBuf += String.fromCharCode(data[i]);
}
bf1.WriteAll(outBuf);
The result looks like this:
EDIT:
I just did a more compact adaptation of the code, to avoid the hex conversion and the double loop:
// Codepage conversion table
var _c=[199,252,233,226,228,224,229,231,234,235,232,239,238,236,196,197,
201,230,198,244,246,242,251,249,255,214,220,162,163,165,8359,402,
225,237,243,250,241,209,170,186,191,8976,172,189,188,161,171,187,
9617,9618,9619,9474,9508,9569,9570,9558,9557,9571,9553,9559,9565,9564,9563,9488,
9492,9524,9516,9500,9472,9532,9566,9567,9562,9556,9577,9574,9568,9552,9580,9575,
9576,9572,9573,9561,9560,9554,9555,9579,9578,9496,9484,9608,9604,9612,9616,9600,
945,223,915,960,931,963,181,964,934,920,937,948,8734,966,949,8745,
8801,177,8805,8804,8992,8993,247,8776,176,8729,183,8730,8319,178,9632,160],
_w=[],
_r=[];
// Create forward lookup to write & reverse lookup to read
for(var i=0, l=256; i<l; i++) {
var c = (i<128) ? i : _c[i-128];
_w[i] = c;
_r[c] = i;
}
// Read binary data from disk
function binFileToArray(fileName, binArray){
var inStream = new ActiveXObject("ADODB.Stream");
inStream.Type = 2;
inStream.CharSet = '437';
inStream.Open();
inStream.LoadFromFile(fileName);
var inString = inStream.ReadText();
inStream.Close();
for(var i=0, l=inString.length; i<l; i++) {
binArray.push(_r[inString.charCodeAt(i)]);
}
}
// Write binary data to disk
function binArrayToFile(binArray, fileName){
var outStream = new ActiveXObject('ADODB.Stream');
var outString = '';
for(var i=0, l=binArray.length; i<l; i++) {
outString += String.fromCharCode(_w[binArray[i]]);
}
outStream.Type = 2;
outStream.CharSet = '437';
outStream.Open();
outStream.WriteText(outString);
outStream.SaveToFile(fileName, 2);
outStream.Close();
}
// TEST: read binary file from disk & write array back to disk
var testArray = [];
binFileToArray('c:/temp/test.bin', testArray);
binArrayToFile(testArray, 'c:/temp/test2.bin');
// both files equals

How to merge arrays by index AS3

Seeking a way to merge arrays by index like so:
var a1:Array = ["a", "b", "c"];
var a2:Array = ["1", "2", "3"];
var a3:Array = result: ["a", 1, "b", 2, "c", 3]
I've tried concat, push, splice... not getting close. Thanks.
function arrayMerge(arr1:Array, arr2:Array):Array {
var o:Array = new Array();
for (var i:int=0; i<Math.max(arr1.length, arr2.length); i++) {
if (i<arr1.length) o.push(arr1[i]);
if (i<arr2.length) o.push(arr2[i]);
}
return o;
}
Thanks Payam for answer and non-judgement. Here's how I applied your work:
var arr1:Array = ["question1", "question2", "question3"];
var arr2:Array = ["answer1", "answer2", "answer3"];
var o:Array = new Array();
for (var i:int=0; i<Math.max(arr1.length, arr2.length); i++) {
if (i<arr1.length) o.push(arr1[i]);
if (i<arr2.length) o.push(arr2[i]);
}
trace(o); //(question1,answer1,question2,answer2,question3,question3)
#AndyH :
payamsbr is right, but you may work with Vectors or Arrays
Perhaps tl; dr; but this is the principle.
If You want to understand something try those possibilities.
If you don't, just copy and paste some shorter code ;)
var v1:Vector.<String> = new <String>["a", "b", "c"];
var v2:Vector.<uint> = new <uint>[1, 2, 3]; // why do you use String here and not uint?
// if you want to convert a uint to a String, use myUint.toString();
function convertVectorToArray(v1:Vector.<String>,v2:Vector.<uint>):Array{
var mergedArray:Array = new Array();
if (v1.length != v2.length){
throw(new Error(" ***ERROR : the two Vectors or Arrays have not the same lenfgth!"));
}else{
for(var i:uint = 0; i <v1.length ; i++){
mergedArray.push(v1[i]);
mergedArray.push(v2[i]);
}
}
return(mergedArray);
}
function mergeVectors(v1:Vector.<String>,v2:Vector.<uint>):Vector.<Object>{
var mergedVector:Vector.<Object> = new Vector.<Object>();
if (v1.length != v2.length){
throw(new Error(" ***ERROR : the two Vectors or Arrays have not the same length!"));
}
for(var i:uint = 0; i <v1.length ; i++){
mergedVector.push(v1[i] as String);
mergedVector.push(v2[i] as uint);
}
return(mergedVector);
}
var mergedArray:Array = (convertVectorToArray(v1,v2));
var mergedVector:Vector.<Object> = (mergeVectors(v1,v2));
function listArray(arr:Array):String{
var str: String="";
if ((v1.length*2) != (v1.length + v2.length)){
throw(new Error(" ***ERROR : the two Vectors or Arrays have not the same length!"));
}else{
for (var i:uint = 0; i < arr.length ; i++){
str+="typeof(arr[" + i + "]) = " + (typeof(arr[i]) as String).toUpperCase() + ", value = " + arr[i] + "\n";
}
}
return str;
}
function listVector(vect:Vector.<Object>):String{
var str: String = "";
if ((v1.length*2) != (v1.length + v2.length)){
throw(new Error(" ***ERROR : the two Vectors or Arrays have not the same length!"));
}else{
for (var i:uint = 0; i < vect.length ; i++){
str+="typeof(vect[" + i + "]) = " + (typeof(vect[i]) as String).toUpperCase() + ", value = " + vect[i] + "\n";
}
}
return str;
}
trace(listArray(mergedArray));
trace(listVector(mergedVector));
You may add a sort() method if You need it (you didn't told about it)
And Always throw an Error if the 2 Arrays or Vectors don't have the same length!
Throwing an Error is the best way to understand if something goes wrong...
This will avoid You a lot of time if You need to debug Your code!!!
As You can see the output is the same, but if the Vector Class is used correctly, this is more efficient than an Array.
Output :
Since there's a Vector Class, I don't understand a lot of people who chose Arrays instead...
Of course Vector. is a nonsense, but I posted it anyway so You can figure You out the Vector Class.
Output is the same :
typeof(arr[0]) = STRING, value = a
typeof(arr[1]) = NUMBER, value = 1
typeof(arr[2]) = STRING, value = b
typeof(arr[3]) = NUMBER, value = 2
typeof(arr[4]) = STRING, value = c
typeof(arr[5]) = NUMBER, value = 3
typeof(vect[0]) = STRING, value = a
typeof(vect[1]) = NUMBER, value = 1
typeof(vect[2]) = STRING, value = b
typeof(vect[3]) = NUMBER, value = 2
typeof(vect[4]) = STRING, value = c
typeof(vect[5]) = NUMBER, value = 3
I forgot this easiest way if you really want an Array...
Quick done!
var ar1:Array = [1,2,3];
var ar2:Array = ["a","b","c"];
function merge(...arrays):Array {
var result:Array = [];
for(var i:int=0;i<arrays.length;i++){
result = result.concat(arrays[i]);
}
return result;
}
trace(merge(ar1, ar2));
// outputs : 1,2,3,a,b,c
Another possibility :
function populateObject(v1:Vector.<String>, v2:Vector.<uint>):Object{
var obj = new Object();
if ((v1.length*2) != (v1.length + v2.length)){
throw(new Error(" ***ERROR : the two Vectors or Arrays have not the same length!"));
}else{
for (var i:uint = 0; i < v1.length; i++){
obj[v2[i]] = v1[i];
}
}
return obj;
}
var o:Object = populateObject(v1,v2);
function listObject(someObj:Object):void{
var myObj:Object = someObj;
for (var i:String in someObj){
trace(someObj[i] + ": " + i);
}
}
listObject(o);
output =
a: 1
b: 2
c: 3
I think that You have a lot of possibilities to use here even it's my longer answer ;)
If You try those possibilities and understand them, this will certainty help You to think to find the best way to deal with Your issue.
But You may also copy and paste some shorter code.
I just wanted to show You that there's more than one answer.
If you understand this, You will be able to go further with coding.
Have fun ;)
Sincerely.
Nicolas
Best regards.
Nicolas.

Writing and saving XML with AS3

I want to create a XML file and fill it with generated data. Here is a code I have. There is no error but it does not create any file under same folder. It is a AIR Desktop project and if I change it to FileReference option that pops up a dialog box and can successfully save.
var objects = ["one","two","three"];
var values = ["1", "2", "3"];
var file = new File();
var fileStream = new FileStream();
file = File.applicationStorageDirectory.resolvePath("ayara.xml");
var myXmlTag = "<ayar>";
for(var lp:int = 0; lp < 1; lp++)
{
myXmlTag += "<Etkinlik>"
for(var i = 0; i < objects.length; i++)
{
myXmlTag += "<" + objects[i] + ">" + values[i] + "</" + objects[i] + ">";
}
myXmlTag += "</Etkinlik>"
}
myXmlTag += "</ayar>";
var xmlfinal:XML = XML(myXmlTag );
fileStream.openAsync(file, FileMode.WRITE);
fileStream.writeUTF(xmlfinal);
Am I missing something or executing things in wrong way? I have checked posts about handling XML files and there is nothing much different from that.

Web Audio playing back in Chrome but not Firefox

Firefox seems to be processing the audio but it won't play it back. This exact code works fine with Chrome. I'm seeing no errors from the console so I'm really at a loss. I'm thinking it has something to do with audioBuffer.getChannelData(0).set(audio); but I'm not sure. Anyone know why this audio won't play back in FF but will in Chrome? I'm running FF 27 right now.
window.AudioContext = window.AudioContext || window.webkitAudioContext;
var context = new AudioContext();
var init = 0;
var nextTime = 0;
var audioStack = [];
function toArrayBuffer(buffer) {
var ab = new ArrayBuffer(buffer.length);
var view = new Uint8Array(ab);
for (var i = 0; i < buffer.length; ++i) {
view[i] = buffer[i];
}
return ab;
}
socket.on('stream', function(data) {
audioStack.push(data);
//if ((init!=0) || (audioStack.length > 10)) { // make sure we put at least 10 chunks in the buffer before starting
init++;
scheduleBuffers();
//}
});
function scheduleBuffers() {
while (audioStack.length) {
var data = toArrayBuffer(audioStack.shift().data);
var audio = [];
audData = new Int16Array(data);
for (var i = 0; i < audData.length; i++) {
audio[i] = (audData[i]>0)?audData[i]/32767:audData[i]/32768; // convert buffer to within the range -1.0 -> +1.0
}
var source = context.createBufferSource();
var audioBuffer = context.createBuffer(1, audio.length , 44100);
source.buffer = audioBuffer;
audioBuffer.getChannelData(0).set(audio);
source.connect(context.destination);
if (nextTime == 0)
nextTime = context.currentTime + 0.05; /// add 50ms latency to work well across systems - tune this if you like
source.start(nextTime);
console.log('length: '+source.buffer.duration);
nextTime+=source.buffer.duration; // Make the next buffer wait the length of the last buffer before being played
};
}
Looking at this code:
source.buffer = audioBuffer;
audioBuffer.getChannelData(0).set(audio);
Can you try changing the order of these two lines? In other words, first set the channel data for audioBuffer and then assign it to source.buffer. Does that fix the problem for you?

How to remove/reload movieclip/graphic in Flash CS5 with AS3

I have a setupBoard(); and a setupBlocks(); in my function:
function init(e)
{
setupBoard();
removeEventListener(Event.ENTER_FRAME , init);
setupCat();
setupBlocks();
}
function setupBoard()
{
var columns:Array = new Array();
var i,j:int;
var _place:place;
for (i = 0; i < 11; i++)
{
columns = [];
for (j = 0; j < 11; j++)
{
_place = new place();
_place.thisX=i;
_place.thisY=j;
_place.thisDistance=Math.min(i+1,j+1,11-i,11-j)*11;
_place.y = 56 * i + 3;
_place.x = 5 + 71 * j + 35*(i%2);
_place.buttonMode=true;
_place.addEventListener(MouseEvent.CLICK, setBlock);
columns[j] = _place;
// SÆTTER TAL PÅ BRIKKERNE
_place.thisText.text = _place.thisDistance + " - " + _place.thisX + " : " + _place.thisY;
addChild(_place);
}
rows[i] = columns;
}
}
The "place" is the MovieClip
this function loads when the game launches and when the game is finish/completed..
the setupBoard, setup the board ofc, and the setupBlocks setup some movieclips, which contain some graphic.
Here's my question, how do I remove/reload all the blocks when the game enters that function again?
At the moment they are just placed upon each other, which I don't like at all.
If I understood correctly, what you want to do is remove all the previous blocks (from the last time you ran the setup function) when you run setup a second time.
To do that, you should create a function which loops your rows and columns Arrays, and for each Place object it find, it does the following: removes it from the stage, removes all Event Listeners, and finally sets it to null. Your function could look something like this (and you would call it just before calling setup again):
for (i = 0; i < rows.length; i++)
{
var column:Array = rows[i];
for (j = 0; j < column.length; j++)
{
var place:Place = column[j];
if (contains(place))
{
removeChild(place);
}
place.removeEventListener(MouseEvent.CLICK, setBlock);
place = null;
}
column = [];
}
row = [];
I just wrote that straight into the box, so it's not tested. But basically it does the three things necessary to get those objects removed from the view, and clears up anything that would stop them from being freed from memory by the garbage collector.
Hope that helps.
Debu