473,387 Members | 1,771 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

Expressions in C#...

Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
....
//objects are created and initalized here...
....
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri
Sep 4 '06 #1
66 2816
Hi!

The fix for the problem is to write the expression as:

d = 2*c;
a = MyFun(d)*b;

That is to explicitely allocate the temporary variable....
But of course, that is not really a fix, it just points to
the problem...

Thanks!
Atmapuri


"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri

Sep 4 '06 #2
Sounds curious; can you reproduce this in simple (yet complete), postable
code?

Is it possible that MyFun is return an MyOjbects [sic] instance that
genuinely has the same length as b (100)? Equally, depending on whether
these are structs or classes, it might be that you are (in the non-shown
code) accidentally changing properties of the operands, and this behaviour
is a side-effect?

Marc
Sep 4 '06 #3
That's actually very, very wrong. Something else is going on here. The
temporary variable that is created as a result of calling 2 * c isn't being
GC'ed because the reference is held on the stack (through the parameter)
when you pass it to MyFun.

It is most definitely something else. Without seeing the code for the
class where the operator is overloaded, as well as the code for MyFun, it's
impossible to say.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri

Sep 4 '06 #4
Hi!
Sounds curious; can you reproduce this in simple (yet complete), postable
code?
Could be a tough job. The garbage collector is not deterministic....
Is it possible that MyFun is return an MyOjbects [sic] instance that
genuinely has the same length as b (100)? Equally, depending on whether
these are structs or classes, it might be that you are (in the non-shown
code) accidentally changing properties of the operands, and this behaviour
is a side-effect?
The code inside the loop works for 100 iterations and than fails?
This is C#. It should be impossible especially because the next
iteration does not depend upon the previous...

Struct works fine and classes fail...

Regards!
Atmapuri

Sep 4 '06 #5
Hi!

It would be very difficult for me to post the code.
Can you think of anything why this would occur
considering that:

It works with struct but not with classes. I noticed
that the compiler copies the struct before passing it
to the function.

MyObjects has a finalizer declared. And the only
way I can imagine for the Length to be set to zero
is if that finalizer has been called on the temporary
object created by 2*c, before the object was used.

Thanks!
Atmapuri

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:%2****************@TK2MSFTNGP03.phx.gbl...
That's actually very, very wrong. Something else is going on here.
The temporary variable that is created as a result of calling 2 * c isn't
being GC'ed because the reference is held on the stack (through the
parameter) when you pass it to MyFun.

It is most definitely something else. Without seeing the code for the
class where the operator is overloaded, as well as the code for MyFun,
it's impossible to say.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
>Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri


Sep 4 '06 #6
It should be impossible especially because the next
iteration does not depend upon the previous...
In your example, with classes, it really, really *does*; the variables b & c
are declared and initialised *outside* of the loop, so if you are causing
side-effects in the objects then it will persist between iterations, and can
(when some critical condition [determined by the exact foobar] is met) cause
it to bomb. *Especially* for classes. For structs (without "ref" usage), the
memory contents will be cloned when passing between stack contexts, so any
side effect in the memory will only live as long as that stack - which
probably explains why structs appear to work. You just "get lucky" with
structs, in that they don't propegate bugs as readily. But the bug may still
be there. I reckon that at some point you are monkeying with the contents of
the class without cloning it first. As an example of a possible foobar
(operator with operand side-effects):

SomeClass operator *(SomeClass lhs, SomeClass rhs) {
lhs.Length *= rhs;
return lhs
}

This should be:

SomeClass operator *(SomeClass lhs, SomeClass rhs) {
SomeClass result = lhs.Clone();
result.Length *= rhs;
return result;
}

Marc
Sep 4 '06 #7
Why do you think, the result depends on garbage collection?
The result of an operator shouldn't depent on instances ont referenced
(directly or inderectly)
by the operands. So it shouldn't depend on the existence of objetcs eligable
for collection.

"Atmapuri" <di*@community.nospamschrieb im Newsbeitrag
news:e1**************@TK2MSFTNGP03.phx.gbl...
Hi!
>Sounds curious; can you reproduce this in simple (yet complete), postable
code?

Could be a tough job. The garbage collector is not deterministic....
>Is it possible that MyFun is return an MyOjbects [sic] instance that
genuinely has the same length as b (100)? Equally, depending on whether
these are structs or classes, it might be that you are (in the non-shown
code) accidentally changing properties of the operands, and this
behaviour
is a side-effect?

The code inside the loop works for 100 iterations and than fails?
This is C#. It should be impossible especially because the next
iteration does not depend upon the previous...

Struct works fine and classes fail...

Regards!
Atmapuri

Sep 4 '06 #8
Hi!
In your example, with classes, it really, really *does*; the variables b &
c
b and c are not modified inside of the loop and also not inside
of the operator. That is certain. This also does not account for
undeterministic
nature of the problem. If I debug the stuff, it works fine... It only
fails when being run free... only after about 100 iterations...
and only if the temporary variable is not assigned explicitely, but
the expression is passed directly to the function as a parameter.
(I double tested that...)
SomeClass operator *(SomeClass lhs, SomeClass rhs) {
lhs.Length *= rhs;
return lhs
}

This should be:

SomeClass operator *(SomeClass lhs, SomeClass rhs) {
SomeClass result = lhs.Clone();
result.Length *= rhs;
return result;
}
That is a deterministic case.. that will fail in the first loop.

Thanks!
Atmapuri
Sep 4 '06 #9
Hi!
Why do you think, the result depends on garbage collection?
The result of an operator shouldn't depent on instances ont referenced
(directly or inderectly)
by the operands. So it shouldn't depend on the existence of objetcs
eligable for collection.
The iteration count at which the error happens is not fixed...
The loop will execute fine 100x and fail on 101 for example.
That points to the garbage collector, because the time at which
the garbage collector is run is determined by the CLR.

And it is a predictive pattern. Whenever you have a expression
passed directly to the function without assigning its result first to the
local variable. (which should not matter).

Thanks!
Atmapuri
Sep 4 '06 #10
Without seeing the code for the things I mentioned, it's nearly
impossible. You might as well post it, otherwise, no one will be able to do
much but offer conjecture at this point.

--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
Hi!

It would be very difficult for me to post the code.
Can you think of anything why this would occur
considering that:

It works with struct but not with classes. I noticed
that the compiler copies the struct before passing it
to the function.

MyObjects has a finalizer declared. And the only
way I can imagine for the Length to be set to zero
is if that finalizer has been called on the temporary
object created by 2*c, before the object was used.

Thanks!
Atmapuri

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote
in message news:%2****************@TK2MSFTNGP03.phx.gbl...
> That's actually very, very wrong. Something else is going on here.
The temporary variable that is created as a result of calling 2 * c isn't
being GC'ed because the reference is held on the stack (through the
parameter) when you pass it to MyFun.

It is most definitely something else. Without seeing the code for the
class where the operator is overloaded, as well as the code for MyFun,
it's impossible to say.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
>>Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri



Sep 4 '06 #11
Hi,

if your class has a finalizer and you supose the problem is because of
GC-timing you could try to debug when the finalizer ist called.

If the problem doesn't occur with structsit could be a problem
with sides effects. You should never change the operands inside
a operator. Also MyFunc looks like a Method that computes a
new value and shouldn't change the argument in any way.

BTW, why are you using a finalizer at all?
Finalizer should only clean up unmanaged resources. Managed
resources will be finalized themselves if they are referenced only by
objects eligable for finalization.
Maybe you try to clean smoething up wich shouldn't be and thereby
destroy something.

hth

"Atmapuri" <di*@community.nospamschrieb im Newsbeitrag
news:%2****************@TK2MSFTNGP02.phx.gbl...
Hi!

It would be very difficult for me to post the code.
Can you think of anything why this would occur
considering that:

It works with struct but not with classes. I noticed
that the compiler copies the struct before passing it
to the function.

MyObjects has a finalizer declared. And the only
way I can imagine for the Length to be set to zero
is if that finalizer has been called on the temporary
object created by 2*c, before the object was used.

Thanks!
Atmapuri

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote
in message news:%2****************@TK2MSFTNGP03.phx.gbl...
> That's actually very, very wrong. Something else is going on here.
The temporary variable that is created as a result of calling 2 * c isn't
being GC'ed because the reference is held on the stack (through the
parameter) when you pass it to MyFun.

It is most definitely something else. Without seeing the code for the
class where the operator is overloaded, as well as the code for MyFun,
it's impossible to say.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
>>Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri



Sep 4 '06 #12
Hi!

Could it be a problem if I call GC.Collect from inside a
class constructor?

Thanks!
Atmapuri

"Nicholas Paldino [.NET/C# MVP]" <mv*@spam.guard.caspershouse.comwrote in
message news:%2****************@TK2MSFTNGP03.phx.gbl...
That's actually very, very wrong. Something else is going on here.
The temporary variable that is created as a result of calling 2 * c isn't
being GC'ed because the reference is held on the stack (through the
parameter) when you pass it to MyFun.

It is most definitely something else. Without seeing the code for the
class where the operator is overloaded, as well as the code for MyFun,
it's impossible to say.
--
- Nicholas Paldino [.NET/C# MVP]
- mv*@spam.guard.caspershouse.com

"Atmapuri" <di*@community.nospamwrote in message
news:ej**************@TK2MSFTNGP04.phx.gbl...
>Hi!

I noticed a very funny behaviour when overloading operators
on objects in C#:

MyOjbects a,b,c,d;
...
//objects are created and initalized here...
...
b.Length = 100;
c.Length = 100;

for (i = 0; i < 10000; i++)
{
a = MyFun(2*c)*b;
}

Inside the overladed multiplication operator, I check:

if (Op1.Length == Op2.Length) throw....

And the exception triggers after about 100 iterations...!!?
Somehow the internal objects of the temporary variable
created by 2*c passed to MyFun are being
garbage collected (nullified) before the temporary variable is used for
the first time...

Are there some known issues with this?

Thanks!
Atmapuri


Sep 4 '06 #13
That is a deterministic case.. that will fail in the first loop.

My example was for demonstration only, to illustrate what I meant be
side-effects.
b and c are not modified inside of the loop and also not inside
of the operator. That is certain.
Well, without the operator code I couldn't (and still can't) see this, but
you'll have
to excuse me for looking for the straightforward explanations first. A
demonstrable
example would be the ideal, but I gather that isn't going to happen...

Since finalizers are involved, and since we have (seemingly) exhausted the
simple
options, then it is possible that you are racing the GC; does this article
help any?

http://blogs.msdn.com/cbrumme/archiv.../19/51365.aspx

Marc
Sep 4 '06 #14

"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you only
can answer.

Willy.
Sep 4 '06 #15
Hi!

I did not think it was possible, but heck :) Here is the complete
source that gives reproducable error at least on my machine.
After you run it, you should get an exception Length = 0 indicating
that the problem is present..
public class Vec1
{
public int Length;
public Vec1()
{
Length = 100;
}
}
public class Vector1
{
internal Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}

~Vector1() //finalizer
{
Dispose(false);
}

public void CreateFromCache()
{
if (Data == null)
{
Data = new Vec1();
VecIterCount++;
if ((VecIterCount % GCInterval) == 0)
{
GC.Collect(GCGeneration);
VecIterCount = (VecIterCount % GCInterval) + 1;
}
}
}

public Vector1(int aLength)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}
}

//This functions must be called in a loop:

private double MyFunction(int Iterations)
{
double a = 1;
Vector1 xx, x, res;
x = new Vector1(100);
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x*x;
res = Vec1Math.Sqrt(-0.5 * a * xx) * xx * Vec1Math.Exp(4 *
Math387.INVTWOPI * x);
}
return Environment.TickCount - counter;
}

//here is the main event

private void button1_Click(object sender, System.EventArgs e) {

iters = 1000000;
for (int i=0;i<=5;i++)
{
Function(iters);
iters /= 10;
Refresh;
}

It takes on my machine about 5 seconds before the error surfaces...
It may be that due to different loads, the time will be different on
other machines... Increase the Iters count if it finishes too quick
or does not trigger a Length = 0 exception... The loop must run
at least for a few seconds... This was done on Pentium M 1.7GHz
and VS2005.

Thanks!
Atmapuri
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OT****************@TK2MSFTNGP04.phx.gbl...
>
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you only
can answer.

Willy.



Sep 4 '06 #16
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP02.phx.gbl...
Hi!

It would be very difficult for me to post the code.
Can you think of anything why this would occur
considering that:
Since you obviously won't post the code, here are some observations.

The chances that this is a framework bug are small.
The chances that the design is flawed is quite high.

You haven't expained
1. What are MyOjbects?
2. What is Length for? Is that what gets multiplied?
3. What does MyFun() do? Does it modify the input or just pass it
through
4. Why are you throwing an exception if the Lengths are equal?
5. Given your example operator * must be overloaded at least one
more time to handle multiplication by a constant

At a minimum, you should post the code for the * operator, and a
simplified MyFun() or there is really nothing more that we can do.

Here is a quick sample that that does what you showed...but no error
Obviously, since you didn't show MyFun, Or the guts of any of your
multiplication operators this is very simple.

Oh,well
Good luck
Bill

using System;

namespace Stupidhead
{
public class TEST
{
public static MyObject MyFun(MyObject param)
{
// Console.WriteLine("MyFun(MyObject({0}))",param.Len gth);
return param;
}

public static void Main(string[] args)
{
MyObject a = null;
MyObject b = new MyObject();
MyObject c = new MyObject();

b.Length = 100;
c.Length = 100;
for (int i = 0; i < 1000000; i++)
{
a = MyFun(2*c)*b;
// Console.WriteLine("---------------------");
}
}
}

public class MyObject
{
private long length;
public long Length {get{return length;} set{length = value;}}

public static MyObject operator *(MyObject lhs, MyObject rhs)
{
if(lhs.Length == rhs.Length)
Console.WriteLine("ooops");
MyObject tmp = new MyObject();
tmp.Length = lhs.Length * rhs.Length;
// Console.WriteLine("operator *(MyObject({0}), MyObject({1})) =
{2}", lhs.Length, rhs.Length, tmp.Length);
return tmp;
}

public static MyObject operator *(long k, MyObject rhs)
{
MyObject tmp = new MyObject();
tmp.Length = k * rhs.Length;
// Console.WriteLine("operator *(constant({0}), MyObject({1})) =
{2}", k, rhs.Length, tmp.Length);
return tmp;
}

public static MyObject operator *(MyObject lhs, long k)
{
MyObject tmp = new MyObject();
tmp.Length = lhs.Length * k;
// Console.WriteLine("operator *(MyObject({0}), constant({1})) =
{2}", lhs.Length, k, tmp.Length);
return tmp;
}
}
}



Sep 4 '06 #17
The code you have posted doesn't compile. What is the class Math387? What is
"Refresh;" ?

These were compile errors.
But, in gods sake, my dear, oh, no, oh, ...why did you implement a Dispose
method that just sets a field to zero??
And why did you implement a finalizer? What's the CreateFromCache() ??
Where's the cache? Why are you calling GC.Collect on every 200th call to the
CreateFromCache method???

Maybe you should tell us what are you trying to do in the first place. This
code is uncompilable and ununderstandable.

"Atmapuri" <di*@community.nospamwrote in message
news:uQ**************@TK2MSFTNGP03.phx.gbl...
Hi!

I did not think it was possible, but heck :) Here is the complete
source that gives reproducable error at least on my machine.
After you run it, you should get an exception Length = 0 indicating
that the problem is present..
public class Vec1
{
public int Length;
public Vec1()
{
Length = 100;
}
}
public class Vector1
{
internal Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}

~Vector1() //finalizer
{
Dispose(false);
}

public void CreateFromCache()
{
if (Data == null)
{
Data = new Vec1();
VecIterCount++;
if ((VecIterCount % GCInterval) == 0)
{
GC.Collect(GCGeneration);
VecIterCount = (VecIterCount % GCInterval) + 1;
}
}
}

public Vector1(int aLength)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}
}

//This functions must be called in a loop:

private double MyFunction(int Iterations)
{
double a = 1;
Vector1 xx, x, res;
x = new Vector1(100);
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x*x;
res = Vec1Math.Sqrt(-0.5 * a * xx) * xx * Vec1Math.Exp(4 *
Math387.INVTWOPI * x);
}
return Environment.TickCount - counter;
}

//here is the main event

private void button1_Click(object sender, System.EventArgs e) {

iters = 1000000;
for (int i=0;i<=5;i++)
{
Function(iters);
iters /= 10;
Refresh;
}

It takes on my machine about 5 seconds before the error surfaces...
It may be that due to different loads, the time will be different on
other machines... Increase the Iters count if it finishes too quick
or does not trigger a Length = 0 exception... The loop must run
at least for a few seconds... This was done on Pentium M 1.7GHz
and VS2005.

Thanks!
Atmapuri
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OT****************@TK2MSFTNGP04.phx.gbl...
>>
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you
only
can answer.

Willy.




Sep 4 '06 #18
Hi!
The code you have posted doesn't compile. What is the class Math387?
It declares a constant. You should delete it.
"Refresh;" ?
Refresh is a method of Winform. It is suppose to affect
the speed of loops... You are suppose to:

1.) Create a new project.
2.) Place a button on the form.
3.) Double click the button.
4.) Fill in the on_button event.
5.) Paste in the rest of the code
These were compile errors.
But, in gods sake, my dear, oh, no, oh, ...why did you implement a Dispose
method that just sets a field to zero??
And why did you implement a finalizer? What's the CreateFromCache() ??
Where's the cache? Why are you calling GC.Collect on every 200th call to
the CreateFromCache method???
Maybe because 50.000 lines of code is missing?

Thanks!
Atmapuri
Maybe you should tell us what are you trying to do in the first place.
This code is uncompilable and ununderstandable.

"Atmapuri" <di*@community.nospamwrote in message
news:uQ**************@TK2MSFTNGP03.phx.gbl...
>Hi!

I did not think it was possible, but heck :) Here is the complete
source that gives reproducable error at least on my machine.
After you run it, you should get an exception Length = 0 indicating
that the problem is present..
public class Vec1
{
public int Length;
public Vec1()
{
Length = 100;
}
}
public class Vector1
{
internal Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}

~Vector1() //finalizer
{
Dispose(false);
}

public void CreateFromCache()
{
if (Data == null)
{
Data = new Vec1();
VecIterCount++;
if ((VecIterCount % GCInterval) == 0)
{
GC.Collect(GCGeneration);
VecIterCount = (VecIterCount % GCInterval) + 1;
}
}
}

public Vector1(int aLength)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}
}

//This functions must be called in a loop:

private double MyFunction(int Iterations)
{
double a = 1;
Vector1 xx, x, res;
x = new Vector1(100);
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x*x;
res = Vec1Math.Sqrt(-0.5 * a * xx) * xx * Vec1Math.Exp(4 *
Math387.INVTWOPI * x);
}
return Environment.TickCount - counter;
}

//here is the main event

private void button1_Click(object sender, System.EventArgs e) {

iters = 1000000;
for (int i=0;i<=5;i++)
{
Function(iters);
iters /= 10;
Refresh;
}

It takes on my machine about 5 seconds before the error surfaces...
It may be that due to different loads, the time will be different on
other machines... Increase the Iters count if it finishes too quick
or does not trigger a Length = 0 exception... The loop must run
at least for a few seconds... This was done on Pentium M 1.7GHz
and VS2005.

Thanks!
Atmapuri
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OT****************@TK2MSFTNGP04.phx.gbl...
>>>
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl.. .
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you
only
can answer.

Willy.





Sep 4 '06 #19
Hi!
Since you obviously won't post the code, here are some observations.
If you would have read a few posts down, you would have found it.
Oh,well
Good luck
Thanks :) When you have very large projects with many dependancies
it can be a great challenge to extract a small and simple test case.
It can also be very time consuming and finding a workaround is
much simpler. So its not that I dont want to post immediately, but the
possible
work needed usually makes me shy in such cases and any
shortcuts I can get are most welcome...

Best Regards!
Atmapuri
Sep 4 '06 #20
"Atmapuri" <di*@community.nospamwrote in message
news:u2****************@TK2MSFTNGP05.phx.gbl...
Hi!
>Since you obviously won't post the code, here are some observations.

If you would have read a few posts down, you would have found it.
I saw it right after I posted...It wasn't complete but it was enought to
find your problem.
The problem in your code is ~Vector1() [~Outer() in the sample below]
You assume that since the Outer object is being GCed it is safe to
assume that nobody holds a reference to the inner object.
This is a bad assumption.
In the sample program below this is demonstrated by the call
Func(outer.Inner);
We pass a reference to the inner object to Func.
GC is kicked off while inside of func (by the call to Outer outer = new
Outer(); )
outer is fair game for GC but Inner is still alive.

I don't know if your real example requires ~Vector1().
If not...let the framework handle it

Good Luck
Bill
Here is a short but complete program that demonstrates your problem
-------------------------
using System;
public class Inner
{
public int Value = 100;
}

public class Outer
{
public Inner Inner;

public Outer()
{
Inner = new Inner();
}

~Outer() {Inner.Value = 0;}
}

public class Test
{
public static void Main()
{
for (int i=0;i<=10000000;i++)
{
Outer outer = new Outer();
Func(outer.Inner); // since outer is not referenced again it is
fair game for GC
// outer.Inner.Value++; // This statement can fix the problem by
referencing outer
}
}

public static void Func(Inner Inner)
{
Outer outer = new Outer(); // this line triggers the GC to occur
eventually
if (Inner.Value == 0){ throw new Exception("Ooops"); }
}
}


Sep 4 '06 #21
Hi!
I saw it right after I posted...It wasn't complete but it was enought to
find your problem.
We pass a reference to the inner object to Func.
GC is kicked off while inside of func (by the call to Outer outer = new
Outer(); )
outer is fair game for GC but Inner is still alive.
That is not the reason. You can comment out GC.Collect and
the error still happens, but it is much harder to make it trigger.
You have to run it for extensive times and it will happen...

The GC anyway keeps the reference count that references
the same object. According to the post of one of MVP's
the object reference is kept on the stack and that reference
will not be collected until the procedure ends.

So, the problem here is that the object itself is not collected
but its finalizer is called.... It looks to me at least as a finalizer
bug.... What I need to know for certain is if this problem goes
100% away if Vector1 is a struct and the finalizer is moved
to the internal object.

As for your example, as soon as you have assigned the
object to local variable before passing it to the function, you
worked around the problem. For example.

temp = 2*c;
a = Func(temp);

Works fine.... But

a = Func(2*c)

fails.... But that seriously affects the use of expressions...
(Should not).
I don't know if your real example requires ~Vector1().
If not...let the framework handle it
Yes it absolutely does. A part from that, have you heard of
any major library that makes extensive use of overloaded
operators? There are two types of problems:

1.) Heavy load on the garbage collector and discuraged by
Microsoft. This was one of the first articles on .NET and
how not to write performance code...
The bigger the object, the bigger the problems..
2.) Expression bugs...?!! Maybe...:)

Thanks!
Atmapuri
Sep 5 '06 #22
Hi,

why you are cleaning up the Data inside the Vector1 class.
In the implicit cast operator you return a reference to the very!!! same!!!
instance
of that class. Then in Dispose(bool) (called by the finalizer) you set the
length to zero. This may change an instance referenced by another variable.

In the two lines, where the Exception is thrown you check for vector.Length
== 0.
I suppose x.Length was set to 0 in the finalizer of a Vector1-Instance.

1. You should really think, if you have to change Data.Length in the
Dispose-Method.
2. You really shouldn't cleanup Data inside of the Finalizer.
Since Vec1 is a managed class it will be cleaned up automatically at that
point if it is
not referenced by another field.
3. A cast operator really shouldn't return an inner instance of a mutable
class.

HTH

"Atmapuri" <di*@community.nospamschrieb im Newsbeitrag
news:uQ**************@TK2MSFTNGP03.phx.gbl...
Hi!

I did not think it was possible, but heck :) Here is the complete
source that gives reproducable error at least on my machine.
After you run it, you should get an exception Length = 0 indicating
that the problem is present..
public class Vec1
{
public int Length;
public Vec1()
{
Length = 100;
}
}
public class Vector1
{
internal Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}

~Vector1() //finalizer
{
Dispose(false);
}

public void CreateFromCache()
{
if (Data == null)
{
Data = new Vec1();
VecIterCount++;
if ((VecIterCount % GCInterval) == 0)
{
GC.Collect(GCGeneration);
VecIterCount = (VecIterCount % GCInterval) + 1;
}
}
}

public Vector1(int aLength)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}
}

//This functions must be called in a loop:

private double MyFunction(int Iterations)
{
double a = 1;
Vector1 xx, x, res;
x = new Vector1(100);
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x*x;
res = Vec1Math.Sqrt(-0.5 * a * xx) * xx * Vec1Math.Exp(4 *
Math387.INVTWOPI * x);
}
return Environment.TickCount - counter;
}

//here is the main event

private void button1_Click(object sender, System.EventArgs e) {

iters = 1000000;
for (int i=0;i<=5;i++)
{
Function(iters);
iters /= 10;
Refresh;
}

It takes on my machine about 5 seconds before the error surfaces...
It may be that due to different loads, the time will be different on
other machines... Increase the Iters count if it finishes too quick
or does not trigger a Length = 0 exception... The loop must run
at least for a few seconds... This was done on Pentium M 1.7GHz
and VS2005.

Thanks!
Atmapuri
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OT****************@TK2MSFTNGP04.phx.gbl...
>>
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl...
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you
only
can answer.

Willy.




Sep 5 '06 #23
Sorry, but I have to agree with Bill; you are simply using finalizers wrong
here.
Short version; you don't need finalizers here. They are not helping you *at
all*, and are biting you hard on the hand. Lose them.

Longer version:
In particular, a finalizer should *not* be talking to CLR references that it
holds; in your case you /are/ being bitten by the inner object still bing in
use, but you are actually lucky you didn't get hit by the other gotcha:
accessing a heap item that has already been finalized and canned.

Finalizers are a last-chance for cleaning up managed resources. Generally
this should be done via IDisposable, but finalizers are offered to attmpt to
give the module developer a chance to at least cope with bad programmers
downstream. Elligible GC objects are destroyed in an undefined sequence -
they have to be, otherwise it could never clean up loops of
mutually-referenced objects - hence if your object is abandoned there is
every chance that "Data" has already been expunged.

Dispose and finalizers are *not* intended as a place to deconstruct your
objects (clearing any collections, etc) - leave the GC alone, it will deal
with this for you; in fact, attempting to do this can actually *increase*
memory usage, as it could well be that some class's Clear() method actually
allocates a new internal collection - so you may well be creating objects
unnecessarily.

The only real-life case I have found of legitimately using a finalizer on a
pure managed object goes as follows; its sole purpose is to chastise
developers who fail to call Dispose! (I think there may have been some #if
DEBUG PP-directives etc, but...):

public abstract class GrumpyDisosable : IDisposable {
public void Dispose() {
GC.SuppressFinalize(this);
Dispose(true);
}
public GrumpyDisosable() {}
~GrumpyDisosable() {
// coded here to prevent hiding by override; note can't use
ToString() as
// may reference destroyed objects
Debug.WriteLine("You abandoned me! Can we say \"commitment
issues\"?", GetType().FullName);
Dispose(false);
}
protected virtual void Dispose(bool disposing) {}
}
Sep 5 '06 #24
sorry - I dropped an "un" and broke the entire meaning!

Finalizers are a last-chance for cleaning up **UN**managed resources

Typically this means old-style handles to files, UI, sockets, etc.
Sep 5 '06 #25
Hi!
Finalizers are a last-chance for cleaning up **UN**managed resources
They are the "only" way to clean them up within expressions.

Regards!
Atmapuri

Sep 5 '06 #26
Hi!

All the complaints about the way the code
is written have to do with missing code. What you dont
understand is not neccessary without meaning...

The CLR is managed and should not be failing if all
its objects are managed no matter what....

Thanks!
Atmapuri

"Christof Nordiek" <cn@nospam.dewrote in message
news:uS**************@TK2MSFTNGP05.phx.gbl...
Hi,

why you are cleaning up the Data inside the Vector1 class.
In the implicit cast operator you return a reference to the very!!!
same!!! instance
of that class. Then in Dispose(bool) (called by the finalizer) you set the
length to zero. This may change an instance referenced by another
variable.

In the two lines, where the Exception is thrown you check for
vector.Length == 0.
I suppose x.Length was set to 0 in the finalizer of a Vector1-Instance.

1. You should really think, if you have to change Data.Length in the
Dispose-Method.
2. You really shouldn't cleanup Data inside of the Finalizer.
Since Vec1 is a managed class it will be cleaned up automatically at that
point if it is
not referenced by another field.
3. A cast operator really shouldn't return an inner instance of a mutable
class.

HTH

"Atmapuri" <di*@community.nospamschrieb im Newsbeitrag
news:uQ**************@TK2MSFTNGP03.phx.gbl...
>Hi!

I did not think it was possible, but heck :) Here is the complete
source that gives reproducable error at least on my machine.
After you run it, you should get an exception Length = 0 indicating
that the problem is present..
public class Vec1
{
public int Length;
public Vec1()
{
Length = 100;
}
}
public class Vector1
{
internal Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}

~Vector1() //finalizer
{
Dispose(false);
}

public void CreateFromCache()
{
if (Data == null)
{
Data = new Vec1();
VecIterCount++;
if ((VecIterCount % GCInterval) == 0)
{
GC.Collect(GCGeneration);
VecIterCount = (VecIterCount % GCInterval) + 1;
}
}
}

public Vector1(int aLength)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
CreateFromCache();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Right.Length;
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
if (vector.Length == 0) throw new Exception("Length is zero");
return vector;
}
}

//This functions must be called in a loop:

private double MyFunction(int Iterations)
{
double a = 1;
Vector1 xx, x, res;
x = new Vector1(100);
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x*x;
res = Vec1Math.Sqrt(-0.5 * a * xx) * xx * Vec1Math.Exp(4 *
Math387.INVTWOPI * x);
}
return Environment.TickCount - counter;
}

//here is the main event

private void button1_Click(object sender, System.EventArgs e) {

iters = 1000000;
for (int i=0;i<=5;i++)
{
Function(iters);
iters /= 10;
Refresh;
}

It takes on my machine about 5 seconds before the error surfaces...
It may be that due to different loads, the time will be different on
other machines... Increase the Iters count if it finishes too quick
or does not trigger a Length = 0 exception... The loop must run
at least for a few seconds... This was done on Pentium M 1.7GHz
and VS2005.

Thanks!
Atmapuri
"Willy Denoyette [MVP]" <wi*************@telenet.bewrote in message
news:OT****************@TK2MSFTNGP04.phx.gbl...
>>>
"Atmapuri" <di*@community.nospamwrote in message
news:%2****************@TK2MSFTNGP04.phx.gbl.. .
| Hi!
|
| Could it be a problem if I call GC.Collect from inside a
| class constructor?
|

Please post your code, it makes no sense to ask further questions you
only
can answer.

Willy.





Sep 5 '06 #27
>The CLR is managed and should not be failing if all
its objects are managed no matter what....
....
They are the "only" way to clean them up within expressions.
If the objects are managed, you shouldn't be using finalizers. With perhaps
the one example I already mentioned.

Marc
Sep 5 '06 #28
For ref, I have varified that your code does crash as you describe.

Removing the unnecessary finalizer fixes it, as does moving the finalizer to
the Vec1 class, so that Vec1 cleans *itself* up when the GC decides it is
genuinely out of scope.

If there /is/ a genuine need for finalizer here, then it isn't apparent in
your code, and possibly it isn't quite following a robust pattern. But I
simply can't fault the CLR here - it is doing its job very well.

Marc
Sep 5 '06 #29

"Atmapuri" <di*@community.nospamwrote in message
news:uQ**************@TK2MSFTNGP03.phx.gbl...

Well, you introduced a bug in your code , let me try to explain how you did
...

| protected virtual void Dispose(bool disposing)
| {
| if (Data != null)
| {
| Data.Length = 0;
| }
| }
|
| ~Vector1() //finalizer
| {
| Dispose(false);
| }
|
| public static implicit operator Vec1 (Vector1 AValue)
| {
| return AValue.Data;
| }

On return, the instance of Vector1 referenced by AValue becomes eligible for
collection (the JIT took care of that when loading the class), this is great
you don't need this instance any longer, you return a reference to a Vec1
instance, so far so good.
When the GC kicks-in, the Vector1 instance reference moves to the finalizer
queue, where it get's picked-up by the finalizer thread in order to run it's
finalizer, and here you set Data.Length=0... BINGO. Keep in mind that the
finalizer thread runs in // with your user code!!!
| public class Vec1Math
| {
| public static Vector1 Exp(Vec1 x)
| {
On entry, x holds a reference to a Vec1 instance no matter what......
| Vector1 vector = new Vector1(0);
| vector.Length = x.Length;
but he!, if the GC/finalizer ran before you reach this point, the value of
Length will be 0 (se above) and you will throw.

The reason for this all is an "incorrect" implementation of the Dispose
pattern, whenever you implement a finalizer you should take special care not
to create side effects when touching references co-owned by other object
instances. Implementing finalizers should be avoided at all costs, it's
realy hard to do correctly and in most cases it's not needed at all. Note
that I don't see any reason why you implement a disposable pattern, but I'm
affraid you say that this is only part of a 50 KLoc program :-)

Willy.


Sep 5 '06 #30
>"Atmapuri" <di*@community.nospamwrote in message
>news:u1**************@TK2MSFTNGP04.phx.gbl...
>>Bill wrote
We pass a reference to the inner object to Func.
GC is kicked off while inside of func (by the call to Outer outer =
new Outer(); )
outer is fair game for GC but Inner is still alive.

That is not the reason. You can comment out GC.Collect and
the error still happens, but it is much harder to make it trigger.
You have to run it for extensive times and it will happen...
Did you happen to look at the sample program that I attached????
There is no call to GC.Collect...I cleaned up the problem down to it's
essence. The exception is quite reproducable.
I suggest you take my sample and play with it in order to convince
yourself.
The GC anyway keeps the reference count that references
the same object. According to the post of one of MVP's
the object reference is kept on the stack and that reference
will not be collected until the procedure ends.
I don't believe that your statement is accurate.
The GC starts from LIVE code and builds a tree of all live references.
Since the outer object is not referenced after the method call and it is
not passed into the method call, there is no LIVE reference to the outer
object....valid for GC.
So, the problem here is that the object itself is not collected
but its finalizer is called....
Incorrect, it was GCed because there were no live references to it.
It looks to me at least as a finalizer
bug.... What I need to know for certain is if this problem goes
100% away if Vector1 is a struct and the finalizer is moved
to the internal object.
Why do you NEED the finalizer????
Is there unmanaged resources in the REAL version of Vec1???
If not....stop doing it.
If so...consider the "using" paradigm.
As for your example, as soon as you have assigned the
object to local variable before passing it to the function, you
worked around the problem. For example.
I suggest you look at the sample I sent with Inner and Outer classes (my
second post)
>
temp = 2*c;
a = Func(temp);

Works fine.... But

a = Func(2*c)

fails.... But that seriously affects the use of expressions...
(Should not).
Both versions have the bug (in the finalizer)
The one version makes the problem more likely to occur, The other is a
timebomb.
If the GC kicks off during the method....Booom
>I don't know if your real example requires ~Vector1().
If not...let the framework handle it

Yes it absolutely does. A part from that, have you heard of
any major library that makes extensive use of overloaded
operators? There are two types of problems:
The overloaded operators are not the problem. They are simply triggering
the GC which exposes the real problem.

Take a look at the sample program.
Play with it.
Your finalizer is flawed.

Here it is again
Here is a short but complete program that demonstrates your problem
-------------------------
using System;
public class Inner
{
public int Value = 100;
}

public class Outer
{
public Inner Inner;

public Outer()
{
Inner = new Inner();
}

~Outer() {Inner.Value = 0;}
}

public class Test
{
public static void Main()
{
for (int i=0;i<=10000000;i++)
{
Outer outer = new Outer();
Func(outer.Inner); // since outer is not referenced again it is
fair game for GC
// outer.Inner.Value++; // This statement can fix the problem by
referencing outer
}
}

public static void Func(Inner Inner)
{
Outer outer = new Outer(); // this line triggers the GC to occur
eventually
if (Inner.Value == 0){ throw new Exception("Ooops"); }
}
}



Sep 5 '06 #31
Hi!
realy hard to do correctly and in most cases it's not needed at all. Note
that I don't see any reason why you implement a disposable pattern, but
I'm
affraid you say that this is only part of a 50 KLoc program :-)
:) Thanks for the detailed explanation. Now I understand...

Thanks!
Atmapuri
Sep 5 '06 #32
Hi!

Looking to find a workaround:
Would using a struct instead of class make any difference
in that case? Would the temporary struct object also be immedatilly
invalidated by the garbage collector?

Are value types handled differently? The struct itself of course
can not have a finalizer, but an object inside of the struct
could have one that would implement a finalizer...

With struct I could not trigger an error in any case...and it appears
to work, but as I mentioned before, it has to work for sure...

Thanks!
Atmapuri
Sep 5 '06 #33
I don't think you're making it very clear what you are trying to work
around. From the disclosed information, the correct "workaround" is to ditch
the finalizers (not sure if you are still including these in your schemes).
To suggest an appropriate solution it is *essential* to understand broadly
what you are trying to do. For instance, disposable structs are a nightmare,
as they are so easily cloned (accidentally) - and then which one do you
dispose? double disposal (on different struct instances) would become a real
issue. Structs referencing an object will, when cloned, still reference the
same object instance, etc.

Ah, go on... tell us what you are trying to achieve...

Marc
Sep 5 '06 #34

"Atmapuri" <di*@community.nospamwrote in message
news:ek**************@TK2MSFTNGP03.phx.gbl...
| Hi!
|
| Looking to find a workaround:
| Would using a struct instead of class make any difference
| in that case? Would the temporary struct object also be immedatilly
| invalidated by the garbage collector?
|
| Are value types handled differently? The struct itself of course
| can not have a finalizer, but an object inside of the struct
| could have one that would implement a finalizer...
|
The object inside the struct would be an instance of Vec1 right? Well what
stops you to implement a finalizer in Vec1?? But again, what are you trying
to achieve, what would you ever need to do in Vec1's destructor???

a dirty hack meant to solve a problem which should'n even exist (a bug
introduced by YOU)... could look like this:

public class Vec1
{
internal Vector1 vRef; // store a reference to the containing instance
of Vector1
...

in Vector1.CreateFromCache you set the reference...
....
Data.vRef = this;
...

| With struct I could not trigger an error in any case...and it appears
| to work, but as I mentioned before, it has to work for sure...
|
| Thanks!
| Atmapuri
|
|

Please try to answer these simple questions:
why must the value (Length) be reset?
if you have a valid reason for this (but honestly I don't see any), why
are you relying on a non-deterministic destructor to do this? You are never
sure when it will be done, nor if it will ever be done.

The only workaround is - get rid of this Dispose pattern altogether -, you
don't need it, it put extreme high pressure on the GC which slows down your
code for no good reason (well, I don't see any).

Willy.


Sep 5 '06 #35
Hi!
The object inside the struct would be an instance of Vec1 right?
I would implement another Vec1Container that would have the finalizer
and a pointer to Vec1 and Vector1 would only point to Vec1Container.
When struct Vector1 would be released from the stack, the finalizer
will get its chance..

I was thinking that struct's are allocated on the stack and not on the heap
and the stack is not cleared up until the expression has been evaluted.
This is not the same as for objects, where only the reference is stored
on the stack...
a dirty hack meant to solve a problem which should'n even exist (a bug
introduced by YOU)... could look like this:

public class Vec1
{
internal Vector1 vRef; // store a reference to the containing
instance
of Vector1
That would not work, because the finalizer would never get called,
because the Vec1 has a second reference that is never set to nil until
the end of app life.
Please try to answer these simple questions:
why must the value (Length) be reset?
if you have a valid reason for this (but honestly I don't see any), why
are you relying on a non-deterministic destructor to do this? You are
never
sure when it will be done, nor if it will ever be done.
With critical finalizers you are... Besides, my finalizer is very very
short.
That means that it will always be executed and if the app is destroyed
before that happens... no problem...
The only workaround is - get rid of this Dispose pattern altogether -, you
don't need it, it put extreme high pressure on the GC which slows down
your
code for no good reason (well, I don't see any).
The unmanaged resource is unmanaged memory. When you write expressions
you create a lot of temporary objects especially if you execute in a loop.
This gives great pressure on the garbage collector. One other problem
is that the garbage collector allocates memory over great spans of memory
which is not very close together and thus can not be cached by the CPU.

So, the idea is to allocate unmanaged memory and have that memory
preallocated
in a pool. Each time you allocate an object, it simply obtains a pointer
from the pool. Each time you free an object (via finalizer), the pointer
is released to the pool.

I was running some tests and due to tighter memory pool, the
performance gains of vectorized against plain function
for the function posted are around 5x and
that despite the fact that I call GC.Collect inside the
constructor every now and then...

The proper solution to this problem however would be to introduce
proper reference counted classes that have their destructors called
by the IL immediately after the function ends if their reference count
is 0. But this is only something that Microsoft can do...
..
Thanks!
Atmapuri


Sep 5 '06 #36
Atmapuri <di*@community.nospamwrote:
Finalizers are a last-chance for cleaning up **UN**managed resources

They are the "only" way to clean them up within expressions.
Then you shouldn't be allocating unmanaged resources within
expressions. Non-deterministic release of unmanaged resources is almost
always a bad idea. Implement IDisposable and use the resources in a
controlled way.

Not that I can see any unmanaged resources in your code in the first
place...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #37
Atmapuri <di*@community.nospamwrote:
All the complaints about the way the code
is written have to do with missing code. What you dont
understand is not neccessary without meaning...
But you should listen to all the suggestions and consider that your
design is quite probably very flawed.
The CLR is managed and should not be failing if all
its objects are managed no matter what....
The CLR isn't failing. Your code is failing. Your finalizer is
modifying an object which is referenced elsewhere. The finalizer is
being called at a perfectly reasonable time - it's just that the
finalizer is doing unreasonable (or at least undesirable) things.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #38
Atmapuri <di*@community.nospamwrote:

<snip>
The proper solution to this problem however would be to introduce
proper reference counted classes that have their destructors called
by the IL immediately after the function ends if their reference count
is 0. But this is only something that Microsoft can do...
See http://discuss.develop.com/archives/wa.exe?A2
=ind0010A&L=DOTNET&P=R28572

for an in-depth post about why .NET doesn't use reference counting.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #39
Jon Skeet [C# MVP] wrote:
Atmapuri <di*@community.nospamwrote:
>The proper solution to this problem however would be to introduce
proper reference counted classes that have their destructors called
by the IL immediately after the function ends if their reference count
is 0. But this is only something that Microsoft can do...

See http://discuss.develop.com/archives/...OTNET&P=R28572

for an in-depth post about why .NET doesn't use reference counting.
Java does not use reference counting in any of the
big current implementations.

Memory leaks and poor performance.

PHP and Python uses reference counting. And it works fine
for them. But they have a sligtly different scope and
their "framework" is written in C.

Arne
Sep 5 '06 #40
Hi!
for an in-depth post about why .NET doesn't use reference counting.
It has isolated itself from the subjects that do require deterministic
finalization to run efficiently.

One of the key flaws in the conclusions
made in that discussion is this assumption:

Assuming that everything is an object what is the cost of the reference
counting on the smallest (4byte) object?

Reference counting is actually very efficient for "large" objects
and GC looses there... Why would you want to reference count
an integer value?

Few more false statements:
1.) With reference counting you can only pass variables by reference.
I have code that does not do that in C++
2.) Copy constructors are needed.
Nop. See Delphi 2006. It does it perfectly... It allows you to
implement reference counting on records, without copy
constructors and with the ability to pass variables by value.

a := b;

does an actual deep copy but there is no copy constructor.

Thanks!
Atmapuri
Sep 5 '06 #41
Arne Vajhøj <ar**@vajhoej.dkwrote:
See http://discuss.develop.com/archives/...OTNET&P=R28572

for an in-depth post about why .NET doesn't use reference counting.
Java does not use reference counting in any of the
big current implementations.
Indeed.
Memory leaks and poor performance.
I use Java all the time and see neither of them.
PHP and Python uses reference counting. And it works fine
for them. But they have a sligtly different scope and
their "framework" is written in C.
By "it works fine for them", how do they deal with cyclic references
etc?

Did you read the post I referenced above?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #42
Jon Skeet [C# MVP] wrote:
Arne Vajhøj <ar**@vajhoej.dkwrote:
>>See http://discuss.develop.com/archives/...OTNET&P=R28572

for an in-depth post about why .NET doesn't use reference counting.
Java does not use reference counting in any of the
big current implementations.

Indeed.
>Memory leaks and poor performance.

I use Java all the time and see neither of them.
No. Because Java does not use reference counting.

If it did you would see them.
>PHP and Python uses reference counting. And it works fine
for them. But they have a sligtly different scope and
their "framework" is written in C.

By "it works fine for them", how do they deal with cyclic references
etc?

Did you read the post I referenced above?
Yes. Well - most of it - there was no so much new in it.

I think the bottom line is that the problems are not
a big problem in the context those languages are
primarily used in.

Python has an optional cycle detector to detect cyclic
references.

Arne

Sep 5 '06 #43
Atmapuri <di*@community.nospamwrote:
for an in-depth post about why .NET doesn't use reference counting.

It has isolated itself from the subjects that do require deterministic
finalization to run efficiently.
Well, it's forced deterministic finalization to be manual, and C# has
made this easier for most scenarios with the "using" statement.

Is .NET the perfect environment for every type of task? No, and I don't
think anyone seriously claims it is. That doesn't mean it's made any
bad design decisions (it has, but not in this area IMO) - it just means
that there's a balancing act involved.
One of the key flaws in the conclusions
made in that discussion is this assumption:

Assuming that everything is an object what is the cost of the reference
counting on the smallest (4byte) object?

Reference counting is actually very efficient for "large" objects
and GC looses there... Why would you want to reference count
an integer value?
You're assuming the cost is in memory. Reference counting is still
inefficient in *time* if references to the object are frequently
used/discarded. (I believe someone modified Rotor to be reference
counted, and found that it was costly in a significant number of
scenarious.)
Few more false statements:
1.) With reference counting you can only pass variables by reference.
I have code that does not do that in C++
Where was that statement? I can't find it on a quick scan through...
2.) Copy constructors are needed.
Nop. See Delphi 2006. It does it perfectly... It allows you to
implement reference counting on records, without copy
constructors and with the ability to pass variables by value.
Well, as far as I can see the copy constructor discussion is limited to
stack allocated local value types. It would be perfectly possible to
have reference types being reference counted without copy constructors,
and the post doesn't say otherwise.
a := b;

does an actual deep copy but there is no copy constructor.
Actually no copy constructor, or just none explicitly defined?
Something's got to be doing the copying - does it matter whether we
call that a copy constructor or not? How deep should the copy be?
Should something in the system "know" that for strings, you don't need
to copy the data, because strings are immutable - a reference copy
would be enough?

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #44
Arne Vajhøj <ar**@vajhoej.dkwrote:
Memory leaks and poor performance.
I use Java all the time and see neither of them.
No. Because Java does not use reference counting.

If it did you would see them.
Ah. I see. Your post wasn't really clear about it - I thought you meant
that Java *did* have memory leaks and performance problems because it
doesn't use reference counting.
PHP and Python uses reference counting. And it works fine
for them. But they have a sligtly different scope and
their "framework" is written in C.
By "it works fine for them", how do they deal with cyclic references
etc?

Did you read the post I referenced above?
Yes. Well - most of it - there was no so much new in it.

I think the bottom line is that the problems are not
a big problem in the context those languages are
primarily used in.
Sure - and that context is fairly different to .NET, I believe.
Python has an optional cycle detector to detect cyclic
references.
Hmm... one of these days I must get round to learning Python. And
Smalltalk. Oh for more time on my hands...

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 5 '06 #45

"Atmapuri" <di*@community.nospamwrote in message
news:ex**************@TK2MSFTNGP04.phx.gbl...
| Hi!
|
| The object inside the struct would be an instance of Vec1 right?
|
| I would implement another Vec1Container that would have the finalizer
| and a pointer to Vec1 and Vector1 would only point to Vec1Container.
| When struct Vector1 would be released from the stack, the finalizer
| will get its chance..
|
| I was thinking that struct's are allocated on the stack and not on the
heap
| and the stack is not cleared up until the expression has been evaluted.
| This is not the same as for objects, where only the reference is stored
| on the stack...
|
| a dirty hack meant to solve a problem which should'n even exist (a bug
| introduced by YOU)... could look like this:
| >
| public class Vec1
| {
| internal Vector1 vRef; // store a reference to the containing
| instance
| of Vector1
|
| That would not work, because the finalizer would never get called,
| because the Vec1 has a second reference that is never set to nil until
| the end of app life.
|

That's why a said a dirty hack, that solves the problem you illustrate with
the sample you posted.

| Please try to answer these simple questions:
| why must the value (Length) be reset?
| if you have a valid reason for this (but honestly I don't see any),
why
| are you relying on a non-deterministic destructor to do this? You are
| never
| sure when it will be done, nor if it will ever be done.
|
| With critical finalizers you are... Besides, my finalizer is very very
| short.

No, they are still non deterministic, and can only be used in hosted
environments!
But still you don't answer the other (most important) questions.

| That means that it will always be executed and if the app is destroyed
| before that happens... no problem...
|
| The only workaround is - get rid of this Dispose pattern altogether -,
you
| don't need it, it put extreme high pressure on the GC which slows down
| your
| code for no good reason (well, I don't see any).
|
| The unmanaged resource is unmanaged memory.

But your finalizer does not release unmanaged memory, it moifies an shared
object instance , and this is not what you should do i a finalizer.
When you write expressions
| you create a lot of temporary objects especially if you execute in a loop.
| This gives great pressure on the garbage collector. One other problem
| is that the garbage collector allocates memory over great spans of memory
| which is not very close together and thus can not be cached by the CPU.
|

This is not true, I suggest you read something about how the GC is working.
Short living objects aren't out-living the Gen0 part of the GC heap
(provided they don't have finalizers), the CLR tries to keep the size of
Gen0 more or less the same as the size of the L2 cache of the CPU the CLR
runs on (but there are othe heuristics, like high allocation frequency which
makes that the Gen0 grows beyond that size). Of course finalizable objects
(like yours) will survive the next GC collection and will end on Gen1, this
way you are disturbing the optimum circumstances for the GC to do it's job.
Anyway, the Gen0 is always empty after a GC run and follows the Gen1 and
Gen2 parts in the heap, that means that the Gen0 is always at the start of a
large piece of contigious free memory, new object allocations are adjacent
in Gen0 and are in sequence of their allocation time, so they never span a
large area.
| So, the idea is to allocate unmanaged memory and have that memory
| preallocated
| in a pool. Each time you allocate an object, it simply obtains a pointer
| from the pool. Each time you free an object (via finalizer), the pointer
| is released to the pool.
|
Not sure what you are talking about, managed objects cannot be allocated in
unmanaged memory, they always end in the GC heap.

| I was running some tests and due to tighter memory pool, the
| performance gains of vectorized against plain function
| for the function posted are around 5x and
| that despite the fact that I call GC.Collect inside the
| constructor every now and then...
|
| The proper solution to this problem however would be to introduce
| proper reference counted classes that have their destructors called
| by the IL immediately after the function ends if their reference count
| is 0. But this is only something that Microsoft can do...
| .

By the IL? You must be kidding, right?

Willy.
Sep 5 '06 #46
Hi!

You have not commented if the alternative workaround is fail safe:
| I would implement another Vec1Container that would have the finalizer
| and a pointer to Vec1 and Vector1 would only point to Vec1Container.
| When struct Vector1 would be released from the stack, the finalizer
| will get its chance..
|
| I was thinking that struct's are allocated on the stack and not on the
heap
| and the stack is not cleared up until the expression has been evaluted.
| This is not the same as for objects, where only the reference is stored
| on the stack...
But your finalizer does not release unmanaged memory, it moifies an shared
object instance , and this is not what you should do i a finalizer.
In my full source code it does..
This is not true, I suggest you read something about how the GC is
working.
Short living objects aren't out-living the Gen0 part of the GC heap
(provided they don't have finalizers), the CLR tries to keep the size of
Gen0 more or less the same as the size of the L2 cache of the CPU the CLR
runs on (but there are othe heuristics, like high allocation frequency
which
makes that the Gen0 grows beyond that size). Of course finalizable objects
(like yours) will survive the next GC collection and will end on Gen1,
this
way you are disturbing the optimum circumstances for the GC to do it's
job.
Anyway, the Gen0 is always empty after a GC run and follows the Gen1 and
Gen2 parts in the heap, that means that the Gen0 is always at the start of
a
large piece of contigious free memory, new object allocations are adjacent
in Gen0 and are in sequence of their allocation time, so they never span a
large area.
In theory :). I did my tests. I ran the math function with different vector
lenghts: 10,100,1000,10000 etc.. and timed them.

If CPU cache would have been used, then the speed at 10..10000 elements
would be up to 6x higher as with 100000 elements long vectors
which can not fit in the cache. But guess what... There was no dip,
absolutely
no gain. The curve decayed exponentially towards longer vectors...
You can check that exponential decaying curve yourself. The source is
attached below...

And with my "weird" design the performance gain over the garbage
collected vectors was 400% for lengths between 500 and 3000.

So the GC and CPU cache pairing in this case gives 0.0.
| So, the idea is to allocate unmanaged memory and have that memory
| preallocated
| in a pool. Each time you allocate an object, it simply obtains a pointer
| from the pool. Each time you free an object (via finalizer), the pointer
| is released to the pool.
|
Not sure what you are talking about, managed objects cannot be allocated
in
unmanaged memory, they always end in the GC heap.
Unless you use the Marsall.AllocHGlobal.
| I was running some tests and due to tighter memory pool, the
| performance gains of vectorized against plain function
| for the function posted are around 5x and
| that despite the fact that I call GC.Collect inside the
| constructor every now and then...
|
| The proper solution to this problem however would be to introduce
| proper reference counted classes that have their destructors called
| by the IL immediately after the function ends if their reference count
| is 0. But this is only something that Microsoft can do...
| .

By the IL? You must be kidding, right?
If the SafeHandle class would have its Dispose method called
when its compiler managed reference count would fall to zero,
that would merge the best of both worlds.
Delphi implements a reference counter and when the
procedures exits, it checks if the reference count for local variables
is zero and frees them...

That would be piece of cake to implement for SafeHandle in IL.

Regards!
Atmapuri

public class Vec1
{
private int fLength;
public double[] Data;
public Vec1()
{
Length = 100;
}
public int Length
{
get
{
return this.fLength;
}
set
{
Data = new double[value];
fLength = value;
}
}
}
public class Vector1
{
public Vec1 Data;
static private int VecIterCount = 0;
static private int GCInterval = 200;
static private int GCGeneration = 0;

protected virtual void Dispose(bool disposing)
{
if (Data != null)
{
Data.Length = 0;
}
}
public Vector1(int aLength)
{
Data = null;
Data = new Vec1();
Data.Length = aLength;
}

public Vector1(Vec1 Src)//: base(IntPtr.Zero, true)
{
Data = null;
Data = new Vec1();
Data.Length = Src.Length;
}

public static implicit operator Vec1 (Vector1 AValue)
{
return AValue.Data;
}

public int Length
{
get
{
return this.Data.Length;
}
set
{
this.Data.Length = value;
}
}

public static Vector1 operator *(Vector1 Left, double Right)
{
Vector1 vector = new Vector1(Left.Length);
double[] SrcLeft, Dst;
SrcLeft = Left.Data.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = SrcLeft[i] * Right;
}
return vector;
}
public static Vector1 operator *(double Left, Vector1 Right)
{
Vector1 vector = new Vector1(Right.Length);
double[] SrcRight, Dst;
SrcRight = Right.Data.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = Left * SrcRight[i];
}
return vector;
}
public static Vector1 operator *(Vector1 Left, Vec1 Right)
{
Vector1 vector = new Vector1(Left.Length);
double[] SrcLeft, SrcRight, Dst;
SrcLeft = Left.Data.Data;
SrcRight = Right.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = SrcLeft[i] * SrcRight[i];
}
return vector;
}
public static Vector1 operator *(Vec1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(Left.Length);
double[] SrcLeft, SrcRight, Dst;
SrcLeft = Left.Data;
SrcRight = Right.Data.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = SrcLeft[i] * SrcRight[i];
}
return vector;
}
public static Vector1 operator *(Vector1 Left, Vector1 Right)
{
Vector1 vector = new Vector1(0);
vector.Length = Left.Length;
double[] SrcLeft, SrcRight, Dst;
SrcLeft = Left.Data.Data;
SrcRight = Right.Data.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = SrcLeft[i] * SrcRight[i];
}
return vector;
}
}

public class Vec1Math
{
public static Vector1 Exp(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
double[] Src, Dst;
Src = x.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = Math.Exp(Src[i]);
}
return vector;
}

public static Vector1 Sqrt(Vec1 x)
{
Vector1 vector = new Vector1(0);
vector.Length = x.Length;
double[] Src, Dst;
Src = x.Data;
Dst = vector.Data.Data;
int Len = vector.Length;
for (int i = 0; i < Len; i++)
{
Dst[i] = Math.Sqrt(Src[i]);
}
return vector;
}
}

//The function benchmarked

private double MaxwellExpression1(int Iterations)
{
double a = 1;
Vector1 xx, res1;
res1 = null;
int counter = Environment.TickCount;
for (int i = 0; i < Iterations; i++)
{
xx = x1 * x1;
res1 = Math.Sqrt(4 * Math387.INVTWOPI * a) * a * xx *
Vec1Math.Exp(-0.5 * a * xx);
}
int result = Environment.TickCount - counter;
return result;
}

Iternations count was: 10,100,1000,10000,100000,1000000
Short vectors are not faster than long vecors, which prooves that
CPU cache is not being leveraged at all..

Sep 6 '06 #47
Hi!
You're assuming the cost is in memory. Reference counting is still
inefficient in *time* if references to the object are frequently
used/discarded. (I believe someone modified Rotor to be reference
counted, and found that it was costly in a significant number of
scenarious.)
Only if objects are small and operations on them short.
>a := b;

does an actual deep copy but there is no copy constructor.

Actually no copy constructor, or just none explicitly defined?
Something's got to be doing the copying - does it matter whether we
call that a copy constructor or not? How deep should the copy be?
Should something in the system "know" that for strings, you don't need
to copy the data, because strings are immutable - a reference copy
would be enough?
A copy remains reference copy until it needs to be changed.
So, you can read from it and the copy wont be made, but as soon
as you write to it, it will detach and make an extra copy...

(Of course, if you pass variables by reference, an extra copy
is not made....)

Regards!
Atmapuri
Sep 6 '06 #48
Atmapuri <di*@community.nospamwrote:
You're assuming the cost is in memory. Reference counting is still
inefficient in *time* if references to the object are frequently
used/discarded. (I believe someone modified Rotor to be reference
counted, and found that it was costly in a significant number of
scenarious.)

Only if objects are small and operations on them short.
No. How can the size of the object make any difference to the *time*
performance cost due to assignments etc (anything which changes the
reference count)?
a := b;

does an actual deep copy but there is no copy constructor.
Actually no copy constructor, or just none explicitly defined?
Something's got to be doing the copying - does it matter whether we
call that a copy constructor or not? How deep should the copy be?
Should something in the system "know" that for strings, you don't need
to copy the data, because strings are immutable - a reference copy
would be enough?

A copy remains reference copy until it needs to be changed.
So, you can read from it and the copy wont be made, but as soon
as you write to it, it will detach and make an extra copy...

(Of course, if you pass variables by reference, an extra copy
is not made....)
Interesting. I'd have to examine that scenario further to comment,
frankly.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Sep 6 '06 #49
Hi!
>Only if objects are small and operations on them short.

No. How can the size of the object make any difference to the *time*
performance cost due to assignments etc (anything which changes the
reference count)?
Because large objects contain a lot of data. And a lot of data
needs a lot of processing. If you have a function call that works
on a lot of data, the overhead of reference count is basically zero.

In case of garbage collector however, the overhead is growing
with the size of the object. In the example I posted, if you allocate
arrays of double and of Length, and also perform the
computations, you will noticed that garbage collector takes 75%
of time... and computation only 25%. I measured that with a
profiler..

Thats because if you allocate 100 000 objects of 8kB within
a tight loop the GC is working like crazy.... and reference
count is not affected by object size. Its overhead is constant
and for large objects basically zero.

Regards!
Atmapuri
Sep 6 '06 #50

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

72
by: Raymond Hettinger | last post by:
Peter Norvig's creative thinking triggered renewed interest in PEP 289. That led to a number of contributors helping to re-work the pep details into a form that has been well received on the...
1
by: Kenneth McDonald | last post by:
I'm working on the 0.8 release of my 'rex' module, and would appreciate feedback, suggestions, and criticism as I work towards finalizing the API and feature sets. rex is a module intended to make...
5
by: jens | last post by:
I was wondering if anyone could tell be whether it's possible to instruct preg_match not to save subexpressions matches under 0, 1...n keys when using named subexpressions; I.e instruct preg_named...
7
by: mark | last post by:
Access 2000: I creating a report that has a record source built by the user who selects the WHERE values. An example is: SELECT * FROM CHARGELOG WHERE STDATE Between #10/27/2003# And...
2
by: Sehboo | last post by:
Hi, I have several regular expressions that I need to run against documents. Is it possible to combine several expressions in one expression in Regex object. So that it is faster, or will I...
4
by: Együd Csaba | last post by:
Hi All, I'd like to "compress" the following two filter expressions into one - assuming that it makes sense regarding query execution performance. .... where (adate LIKE "2004.01.10 __:30" or...
56
by: Luke Matuszewski | last post by:
I am designing the library, which will hidden all its functions within singleton object ... So for clients they will use it like . eg. system.getElementWithId('ruler'); At library side, i...
2
by: aarklon | last post by:
Hi all, Recently i was reading a c book which contained a section called C pitfalls. it had a paragraph on the following lines:- ...
1
by: Allan Ebdrup | last post by:
I have a dynamic list of regular expressions, the expressions don't change very often but they can change. And I have a single string that I want to match the regular expressions against and find...
3
by: RobG | last post by:
There has been a discussion on the iPhone web development group where an opinion has been expressed that function expressions are bad for performance and can be avoided by using function...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.