efficient access to same data within multiple classes

V

Vanessa

Hi guys,

First, I'm a newbie :)

I've been trying to create an application using C#. The application has 2
classes.
Class A and class B. Class A will read a file and store the data in a byte
array.
Then based on user action, class A will create class B and pass the byte
array as constructor parameter.

class A:
{
...
byte[] data;
...
createB(data);
...
}

class B:
{
public B(byte[] data)
{
...
DoProcess(data);
...
}
}

The problem is every time the class B is created, it seems to create a new
instance of byte array, which then takes memory resource.
For example, if the byte array is 10MB in size and I have 5 class B created,
it takes, at least, 50MB of memory ( as I can see in the task manager ).
Hence, the application becomes memory hungry.
How can I make the byte array as 'static' reference so class B won't need to
create a new instance of it every time it is created?

Thanks.

Note: the real application is a tabcontrol based winform application. The
byte array will be needed for each tab page to do some processing.
Class A is the main form, and Class B is class that extends TabPage.
 
V

Vanessa

Peter Duniho said:
[...]
The problem is every time the class B is created, it seems to create a
new
instance of byte array, which then takes memory resource.
For example, if the byte array is 10MB in size and I have 5 class B
created,
it takes, at least, 50MB of memory ( as I can see in the task manager ).
Hence, the application becomes memory hungry.
How can I make the byte array as 'static' reference so class B won't
need to
create a new instance of it every time it is created?

You'll have to post a concise-but-complete code sample that reliably
demonstrates your problem. There's nothing about the code you did post
that would suggest the byte[] is being copied. Any array is a reference
type, which means when you pass the value of a variable referring to an
instance, you're just passing a reference to the instance, not a copy of
it.

It's possible your DoProcess() method somehow copies the data, which might
explain what you're seeing. But since you didn't post that code, it's not
possible to say one way or the other.

By the way, your code should _not_ be doing any real processing in the
constructor for a class (such as in the "class B" constructor you
posted). The constructor should do minimal work to ensure the class is
properly initialized, and any actual work the class does should happen in
response to some other method call to the class.

Pete

Thx Pete,

While posting I did several changes to the source code and apparently I
noticed that in the Class B there was a stupid array copying :

this.data = data; //I still wonder if this is the actual culprit

By commenting the code above and passing the array right from class A by
calling a method in the class B and a few workarounds I've managed to make it
loves the memory more :)
The whole application is a byte reading and converting; it reads a binary
database file and doing some byte converting and decoding against some binary
event files.
The results are represented in tab pages using datagridview, of course,
threaded and delegated.

Thanks for your help.
 
V

Vanessa

Peter Duniho said:
While posting I did several changes to the source code and apparently I
noticed that in the Class B there was a stupid array copying :

this.data = data; //I still wonder if this is the actual culprit

Assuming the type of "this.data" and "data" are both arrays (and given
your descriptions so far, it seems like a safe assumption), then that
statement does not copy the array.

Note that even if you were copying the array (and so far there's no
indication you are), the only way doing so would cause your memory usage
to continually increase would be if you had code somewhere explicitly
retaining references to the copies.
By commenting the code above and passing the array right from class A by
calling a method in the class B and a few workarounds I've managed to
make it
loves the memory more :)

Your description implies that you only create a single byte[], and then
with each user interaction, use that array when dealing with class B.
However, if your description was incomplete and you are in fact reading a
whole new byte[] each time, or at least more than once, then if you are
for some reason keeping references to each class B instance, then that
would prevent the array instances from being released.

That's a lot of "ifs", but without actual code to look at, it's the best I
can do in trying to explain what you were seeing.

Again, without a concise-but-complete code sample that reliably reproduces
the problem, it's not possible to say exactly what was going on. You may
have made the symptoms go away, but if you want to actually understand
what was going on, you should pursue the question with a
concise-but-complete code sample that reliably demonstrates the problem,
posted here.

Pete

Well, sorry just read the notification.

Ok, here is a brief description and codes to describe what the application
should do.

[Class A]

private byte[] buffer; //the byte buffer to store the whole database file
content

//method to read the database file, run right when the application starts
private void ReadDB(string dbpath)
{
FileStream dbfs = new FileStream(dbpath,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
BinaryReader dbbr = new BinaryReader(dbfs);
this.buffer = new byte[dbfs.Length];

try
{
dbbr.Read(this.buffer, 0, this.buffer.Length);
}
catch (Exception ex)
{
Logger.Log(Logger.SEVERE, ex.StackTrace);
}
finally
{
dbbr.Close();
}
}

//This code fragment executed when user wants to read an event file
//As you can see the Class B which extends .NET TabPage class, is created.
//
//Then a public method on Class B is executed to read the event file
DataPage page = new DataPage();
page.SetDataFile(OpenEvtFileDlg.SafeFileName);
page.Name = OpenEvtFileDlg.SafeFileName;
this.tabControl.Controls.Add(page);
this.tabControl.SelectedTab = page;
page.StartReading(this.buffer);

[Class B]
//The StartReading method
public void StartReading(byte[] buffer)
{
Thread t = new Thread(new ParameterizedThreadStart(ReadMsg));
t.Start(usr);
}

As we can see the byte array is fed into a thread that executes the ReadMsg
method which then translates the event file previously set within Class A by
calling ClassB.SetDataFile(string s)
This is the last modification that works fine for me :)
 
V

Vanessa

Vanessa said:
Peter Duniho said:
While posting I did several changes to the source code and apparently I
noticed that in the Class B there was a stupid array copying :

this.data = data; //I still wonder if this is the actual culprit

Assuming the type of "this.data" and "data" are both arrays (and given
your descriptions so far, it seems like a safe assumption), then that
statement does not copy the array.

Note that even if you were copying the array (and so far there's no
indication you are), the only way doing so would cause your memory usage
to continually increase would be if you had code somewhere explicitly
retaining references to the copies.
By commenting the code above and passing the array right from class A by
calling a method in the class B and a few workarounds I've managed to
make it
loves the memory more :)

Your description implies that you only create a single byte[], and then
with each user interaction, use that array when dealing with class B.
However, if your description was incomplete and you are in fact reading a
whole new byte[] each time, or at least more than once, then if you are
for some reason keeping references to each class B instance, then that
would prevent the array instances from being released.

That's a lot of "ifs", but without actual code to look at, it's the best I
can do in trying to explain what you were seeing.

Again, without a concise-but-complete code sample that reliably reproduces
the problem, it's not possible to say exactly what was going on. You may
have made the symptoms go away, but if you want to actually understand
what was going on, you should pursue the question with a
concise-but-complete code sample that reliably demonstrates the problem,
posted here.

Pete

Well, sorry just read the notification.

Ok, here is a brief description and codes to describe what the application
should do.

[Class A]

private byte[] buffer; //the byte buffer to store the whole database file
content

//method to read the database file, run right when the application starts
private void ReadDB(string dbpath)
{
FileStream dbfs = new FileStream(dbpath,
FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
BinaryReader dbbr = new BinaryReader(dbfs);
this.buffer = new byte[dbfs.Length];

try
{
dbbr.Read(this.buffer, 0, this.buffer.Length);
}
catch (Exception ex)
{
Logger.Log(Logger.SEVERE, ex.StackTrace);
}
finally
{
dbbr.Close();
}
}

//This code fragment executed when user wants to read an event file
//As you can see the Class B which extends .NET TabPage class, is created.
//
//Then a public method on Class B is executed to read the event file
DataPage page = new DataPage();
page.SetDataFile(OpenEvtFileDlg.SafeFileName);
page.Name = OpenEvtFileDlg.SafeFileName;
this.tabControl.Controls.Add(page);
this.tabControl.SelectedTab = page;
page.StartReading(this.buffer);

[Class B]
//The StartReading method
public void StartReading(byte[] buffer)
{
Thread t = new Thread(new ParameterizedThreadStart(ReadMsg));
t.Start(usr);
}

As we can see the byte array is fed into a thread that executes the ReadMsg
method which then translates the event file previously set within Class A by
calling ClassB.SetDataFile(string s)
This is the last modification that works fine for me :)

Correction the t.Start(usr) should be t.Start(buffer)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top