Whenever I use iterators in update loops I have memory leak issues.
For example, here:
class Manager extends FlxState {
public var array: Array<Int>;
override public function create():Void {
array = new Array();
}
public override function update() {
super.update();
/////////////////////////////////////////////////////
//
// ISSUE IS HERE
// If for(item in array) line is present there's a memory
// issue.
//
/////////////////////////////////////////////////////
for(item in array) var noop:Int = 0 /* Do nothing */;
}
}
When this is run I will get a constant memory increase that goes on forever. This is how it looks in HaxeFlixel's debugger:
However, If I iterate using a simple loop like this:
for(i in (0...array.length)) var noop:Int = 0;
It will be fine:
Why is this happening and what am I doing wrong?
Thanks.
It was happening because the iterator is allocating memory for the iterator.
After a while the memory is collected by the garbage collector.
I did a stress test using 1000 arrays
class Manager extends FlxState {
public var arrays: Array<Array<Int>>;
override public function create():Void {
arrays = new Array();
for (i in (0...1000)) arrays.push(new Array());
}
public override function update() {
super.update();
for (array in arrays)
for (i in array)
var noop:Int = 0;
}
}
And eventually memory was collected:
Related
I was looking into Haxe abstracts and was very interested in building an abstract that would wrap a class and unify it to, in my case, an Int.
#:forward()
abstract Abs(Op)
{
public inline function new(value:Int = 0, name:String = "unnamed" )
{
this = new Op();
this.value = value;
this.name = name;
}
#:to
private inline function toInt():Int
{
return this.value;
}
}
class Op
{
public var value:Int = 0;
public var name:String = "no name";
public function new()
{
}
}
The problem I ran in to is when defining a #:from method - it has to be static and can take only one parameter - a new value. So whenever I set the abstract's instance value from the #:from method I will have to create a new instance of the abstract, thus resetting all the variables.
Basically what I'm talking about is this:
var a = new Abs(5, "my abs"); // value is 5; name is "my abs"
a = 100; // value is 100; name is reset to "unnamed" but I want it to be preserved
As much as I could find out we cannot overload the = operator in abstracts other than through implicit casting with a #:from method and I haven't found a way to really achieve this with macros.
If you have any ideas on how this can be done, please provide a minimalist example.
It depends what you want to do, but if you use this:
var a = new Abs(5, "my abs");
var myInt:Int = a;
It will use the abstract Abs.toInt function.
#:to
private inline function toInt():Int
{
return this.value;
}
The other way around also works:
var million = 1000000;
var myAbs:Abs = million;
It will use the static Abs.fromInt function.
#:from
static inline function fromInt(value:Int)
{
return new Abs(value, "what");
}
This is because it uses the implicit cast. http://haxe.org/manual/types-abstract-implicit-casts.html
Try it yourself: http://try.haxe.org/#Ae1a8
Is that what you are looking for?
Lets suppose I have following mbean:
public interface ExampleMBean {
public float lastHourMean();
}
with following implementation:
import java.util.*;
public class Example implements ExampleMBean {
private Map<Date, Long> dates = new HashMap<Date, Long>();
#Override
public float lastHourMean() {
return calculateMean(getTimesFromLastHour(dates));
}
public void addDate(Date date, Long time) {
dates.put(date, time);
removeOldDates();
}
Map<Date, Long> getTimesFromLastHour(Map<Date, Long> dates) {
//return dates from last hour....
}
float calculateMean(Map<Date, Long> lastHourCalls) {
Collection<Long> values = lastHourCalls.values();
int n = values.size();
if (n > 0) {
long sum = 0L;
for (Long time : values) {
sum = sum + time;
}
return sum / values.size();
} else {
return 0;
}
}
public void removeOldDates() {
//...removes dates before one hour ago from a Map "dates"..
// to avoid buffer overflow
}
}
Mbean is registered as follow:
MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
ObjectName objectName = new ObjectName("com.javacodegeeks.snippets.enterprise:type=Hello");
Example sampleBean = new Example();
mBeanServer.registerMBean(sampleBean,objectName);
Now, instance of this Mbean is used in many functions in multithreaded applications in this way:
sampleBean.addDate(new Date(), time);
The question is if a functions addDate(Date, Long) and removeOldDates are thread safe and if not - how to make this appliaction thread safe ?
This is not thread-safe in any way or manner. Not only is interleaving possible, you're not even guaranteeing that any changes to the map are visible to other threads.
To make it thread-safe you may want to replace your map with a ConcurrentLinkedQueue, since what you've described is a lot more like a queue than a map. This will fix concurrency issues and also improve your performance, since it's already sorted.
on trying to monitor object sizes, string objects are not shown in the profiled results.
Can anyone tell me wat is the procedure to make them shown in results....
public class calling extends called {
called myobj3 = new called();
called myobj4 = new called();
public void function() {
myobj3.d="Plz";
myobj3.e="Help";
myobj4.d="Thank";
myobj4.e="You";
myobj3.act();
myobj4.act();
}
public static void main(String [] args) {
System.out.println("calls an object from called.java");
calling obj = new calling();
obj.function();
}
}
class called {
public String d;
public String e;
public void act() {
System.out.println(d+e);
}
}
memory profile Retained size Shallow Size
[Unreachable] called 40 40
[Unreachable] called 40 40
Perhaps, your objects have been collected or scheduled for collection (unreachable). In which point do you capture memory snapshot?
Disclaimer: I'm a YourKit developer.
okay. so i have a function and i've passed a parameter through it called objectName.
no i have no idea how to do this or explain it. so here goes.
public function moveObject(ObjectName):void{
//objectName now holds "myName" which is an object also
//i would now like my variable called myNamePosition to equal 10
//so it would need to grab the value of objectName which is myName:Object.
//turn it into a string of some kind - myName:string
//add "Position" to the end of it so its myNamePosition
// make it equal to 10
trace(myNamePosition);
}
The functions parameters passed through would change so i cant actually use "myName". but rather "objectName".
Thanks
Example:
package
{
import flash.display.MovieClip;
public class astest extends MovieClip
{
public function astest()
{
init();
}
private var myNamePosition:int;
private function init():void
{
moveObject({myName:{}})
}
public function moveObject(objectName:Object):void
{
var propName:String;
for(propName in objectName)
break;
trace(propName);
propName+="Position";
trace(propName);
this[propName] = 10;
var propValue:* = this[propName];
trace(propValue);
}
}
}
output:
myName
myNamePosition
10
Is it what you need?
I have the following scenario. The managed code will initialize lots of object of a class which is a wrapper around an unmanaged struct. There are two approaches that I can do for this. One is to have a managed class wrapper that just has a pointer to the unmanaged object. The other is to have a full fledged managed class and create the unmanaged object when required to call into unmanaged methods. I have provided both the methods below. I was told that if I use the approach 1(having a pointer to unmanged object), the GC will have lots of issue knowing about the unmanaged portion and it is better to do approach 2. Does someone tell me which is better or if there is some other approach that is even better. My concern with Approach 2 is that there are copying to and fro everytime a unmanaged method is called. I am not sure if the GC issue outweighs it.
EDIT- the first approach has a ref class and the second has a value class. The reason the second is value is so that it can be added to lists more efficiently
In unmanaged:
struct A_UNMANAGED
{
int a;
int b[20];
};
void GetData(A_UNMANAGED& a); // populates A
In managed (First Approach)
public ref class A_MANAGED
{
A_UNMANGED* ap;
public:
property System::UInt32 a
{
System::UInt32 get() { return ap->a; }
void set(System::UInt32 value) { ap->a = value; }
}
property array<System::UInt32>^ b
{
array<System::UInt32>^ get() { return ap->b; }
void set(array<System::UInt32>^ value) { b = value; } // assume this copy works
}
internal:
void GetData()
{
GetData(ap);
}
};
In managed (Second Approach) (EDIT: updated to ref. Assume all the garbage collection and pointer creation is written correctly)
public value class A_MANAGED
{
System::UInt32 a;
array<System::UInt32>^ b;
public:
property System::UInt32 a
{
System::UInt32 get() { return a; }
void set(System::UInt32 value) { a = value; }
}
property array<System::UInt32>^ b
{
array<System::UInt32>^ get() { return b; }
void set(array<System::UInt32>^ value) { b = value; }
}
internal:
void GetUnmanaged(A_UNMANAGED& obj1)
{
obj1.a = a;
pin_ptr<System::UInt32> bp = &b[0];
memcpy(obj1.b, bp, 20);
}
void GetData()
{
A_UNMANAGED obj2;
GetUnmanaged(obj2);
GetData(obj2);
// copy from obj2 to member variables
}
};
No, the 1st snippet it the canonical way. The garbage collector only moves the pointer, it doesn't move the pointed-to object. That one should have been allocated with malloc() or the new operator, it cannot be moved.
There are otherwise several serious problems in your code. You don't seem to allocate the memory for A_UNMANAGED unless GetData() takes its argument by reference. GetData() is never called. This must normally be a ref class (not ref value) so you can provide a destructor and a finalizer to release the memory. The b property setter will bomb your program with a StackOverflowException. Be sure to study the language before tackling this project.
Check this answer for sample code.
As Hans said, the first way is the usual approach (though personally, I think P/Invoke would be more succinct in this particular case...). However, your A_MANAGED::b implementation will not work, which would be obvious if one were to try simply compiling it. Try this instead:
public ref class A_MANAGED
{
A_UNMANAGED* ap;
public:
A_MANAGED() : ap(new A_UNMANAGED() ) { }
~A_MANAGED() { this->!A_MANAGED(); }
!A_MANAGED() { delete ap; ap = nullptr; }
property int a
{
int get() { return ap->a; }
void set(int value) { ap->a = value; }
}
property array<int>^ b
{
array<int>^ get()
{
using System::Runtime::InteropServices::Marshal;
array<int>^ arr = gcnew array<int>(20);
Marshal::Copy(System::IntPtr(ap->b), arr, 0, 20);
return arr;
}
void set(array<int>^ value)
{
using System::Runtime::InteropServices::Marshal;
Marshal::Copy(value, 0, System::IntPtr(ap->b), 20);
}
}
internal:
void GetData()
{
::GetData(*ap);
}
};
And then there's the usual caveat about returning arrays from properties: it's a bad idea. Unless you really want to maintain parity with the unmanaged class' public interface, b should really be a pair of set/get functions rather than a property.