Taille d'une classe [Résolu]

Signaler
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006
-
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006
-
Bonjour,



Je crée plusieur instance d'une petite classe qui ne contient qu'un
evenement et quelque petite variable Rectangle, float ,.. enfin rien de
bien monstrueux niveau memoire...



Le problème vient quand je regarde la taille du processus qui augment de 30 à 40Mo à chaque création d'un de ces objets



J'ai donc essayer un GC.Collect après chaque nouvelle instance ce qui a
permis de diviser par 3 ou 4 ce nombre ce qui fait que chaque instance
consomme encore 10 Mo.



Est-ce que quelqu'un sais comment quelque petite variable peuvent consommer autant de memoire ou comment eviter ce problème ?



Ah oui, j'ai utiliser la reflection pour trouver les type de mes classe
et les allouer via CreateInstance.. je ne sais pas si ça influence le
résultat. D'après mes test ça n'influence que très peu



Merci

7 réponses

Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006

Ahhh ça va j'ai trouver...



Pour info :



En fait la fonction GetHbitmapt ne se contente pas de retourner le pointeur... il crée un nouvel objet....Donc voilà le code



...


Bitmap backbmp = new Bitmap(pt[0].X, pt[0].Y);


IntPtr hBmp = backbmp.GetHbitmap(BackColor);


imgBack = Image.FromHbitmap(hBmp);


DeleteObject(hBmp);


backbmp.Dispose();


...


Et plus besoin de GC.Collect et tout ça...
Messages postés
3466
Date d'inscription
lundi 16 octobre 2000
Statut
Modérateur
Dernière intervention
30 octobre 2008
46
<!--StartFragment --> 30 a 40 Mo par instance ? Waouh. Effectivement.
Elle contient quoi cette classe ? Parce que la c'est vraiment impressionant !
Enfin, si un GC.collect te permet de recuperer 30 Mo sur un seul object, c'est qu'il doit quand meme y avoir beaucoup de chose dedans, non ?

Poste nous des bouts de code pour qu'on puisse voir ce qui cloche

A la limite, essaie de voir avec le CLR Profiler, les choses qui pourraient clocher.

Mx
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006

En fait le GC.Collect vire tout ce que j'aloue comme mémoire pour la création de l'objet



voilà le code de ma classe



using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Collections;

namespace PrintTemplate
{
/// <summary>
/// Summary description for PrintTemplateItemLine.
/// </summary>
public class PrintTemplateItemLine
: PrintTemplateItem
{
#region Membre statique
public static readonly Icon IconNewItem=new Icon(typeof(PrintTemplateItemText), @"Icon.NewLine.ico");
public static readonly Icon IconItem=new Icon(typeof(PrintTemplateItemText), @"Icon.ItemLine.ico");
public static readonly string ItemName="Ligne";
#endregion

#region Constantes
const float Marge = 0.5f;
#endregion

#region Propriétés
private ArrayList v_Points;
public PointF[] Points
{
get
{
return (PointF[]) v_Points.ToArray(typeof(PointF));
}
}

private Color v_Color;
public Color Color
{
get
{
return v_Color;
}
set
{
v_Color=value;
}
}

private float v_DrawWidth;
public float DrawWidth
{
get
{
return v_DrawWidth;
}
set
{
v_DrawWidth=value;
}
}

private DashStyle v_DashStyle;
public DashStyle DashStyle
{
get
{
return v_DashStyle;
}
set
{
v_DashStyle=value;
}
}
#endregion

public PrintTemplateItemLine()
{
v_Points = new ArrayList();
v_Points.Add(new PointF(2,2));
v_Points.Add(new PointF(12,2));
DashStyle = DashStyle.Solid;
DrawWidth = 0.25f;
Color = Color.Black;
}

public override void Draw(System.Drawing.Graphics g, PrintTemplate.CallBack cb, bool Selected)
{
Pen pen = new Pen(Color, DrawWidth);
pen.DashStyle = DashStyle;
g.DrawLines(pen, Points);
if (Selected)
{
PointF[] dR = new PointF[] {
new PointF(4, 4),
new PointF(1, 1)
};
g.TransformPoints(CoordinateSpace.Page, CoordinateSpace.Device, dR);
RectangleF[] Rects = new RectangleF[Points.Length];
int i=0;
foreach(PointF pt in Points)
Rects[i++] = new RectangleF(new PointF(pt.X - dR[0].X/2, pt.Y - dR[0].Y/2), new SizeF(dR[0].X, dR[0].Y));

g.FillRectangles(new SolidBrush(Color.White), Rects);
g.DrawRectangles(new Pen(Color.Black, dR[1].X), Rects);
}
}

public override bool HitTest(PointF Point)
{float X Point.X, Y Point.Y;
PointF[] pts=Points;
for (int i=1; i -(Marge + DrawWidth) && dS < len + (Marge + DrawWidth) && Math.Abs((X - x0)*dY - (Y - y0)*dX) < (Marge + DrawWidth))
return true;
}
return false;
}

public override string ToString()
{
return "Ligne";
}
}
}


qui herite de



using System;
using System.Drawing;
using System.Windows.Forms;
using System.Runtime.Serialization;

namespace PrintTemplate
{
/// <summary>
///
/// </summary>
[Serializable]
public abstract class PrintTemplateItem
: IDeserializationCallback
{
#region Evénements
[NonSerialized]
private System.ComponentModel.EventHandlerList Events=new System.ComponentModel.EventHandlerList();

[NonSerialized]
private static readonly object EVENT_PRINTTEMPLATEITEMCHANGE=new object();
public delegate void PrintTemplateItemChangeEventHandler(object sender, EventArgs e);

public event PrintTemplateItemChangeEventHandler PrintTemplateItemChange
{
add
{
Events.AddHandler(PrintTemplateItem.EVENT_PRINTTEMPLATEITEMCHANGE, value);
}
remove
{
Events.AddHandler(PrintTemplateItem.EVENT_PRINTTEMPLATEITEMCHANGE, value);
}
}
#endregion

#region Variable
[NonSerialized]
private bool Changed=false;
#endregion

#region IPrintTemplateItem Members

abstract public void Draw(Graphics g, PrintTemplate.CallBack cb, bool Selected);

virtual public bool HitTest(PointF Point)
{
return false;
}

virtual public System.Windows.Forms.Control GetUI()
{
return null;
}

virtual public void OnMouseDown(float X, float Y, MouseButtons Btn)
{
}

virtual public void OnMouseMove(float X, float Y, MouseButtons Btn)
{
}

virtual public void OnMouseUp(float X, float Y, MouseButtons Btn)
{
}

virtual public bool HasChange()
{
return this.Changed;
}

virtual public void ChangeSaved()
{
Changed=false;
}
#endregion

#region Protected Methods
protected void ItemChanging()
{
Changed=true;
object[] arg= {this, new EventArgs()};
if (Events[EVENT_PRINTTEMPLATEITEMCHANGE]!=null)
Events[EVENT_PRINTTEMPLATEITEMCHANGE].DynamicInvoke(arg);
}
#endregion

#region IDeserializationCallback Members

public void OnDeserialization(object sender)
{
Events=new System.ComponentModel.EventHandlerList();
Changed=false;
// TODO: Add PrintTemplateItem.OnDeserialization implementation
}

#endregion
}
}

L'allocation se fait dans un collection

Type t=(Type)e.Button.Tag;
PrintTemplateItem NewItem=(PrintTemplateItem)Activator.CreateInstance(t,null);
PTV.PT.AddItem(NewItem);

Le type du template line est dans le tag du bouton


Sinon le programme CLRProfiler est vraiment terrible... mais je ne
trouve pas d'ou vien le prob... j'ai chercher une heure mais je
,'arrive pas à tracer ce qui se passe quand je crée l'instance...

je vais encore chercher ce soir...
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006

Apparement ce n'est pas un problème au niveau de la classe mais plutôt
du moment ou je selectionne l'element dans le programme. On dirait
qu'il y a comme une fuite memoire



voila le code executer



public bool SelectItem(PrintTemplateItem Item)


{


if (Item!=null && !PT.ContainsItem(Item))


return SelectItem(null);


if (PT.SelectedItem!=Item)


{


if (base.Events[PrintTemplateView.EVENT_SELECTEDITEMCHANGING]!=null)


{


object[] arg=


{


this,


new SelectedItemChangingEventArgs(Item)};


base.Events[PrintTemplateView.EVENT_SELECTEDITEMCHANGING].DynamicInvoke(arg); // Lance l'evenement SelectedItemChanging


}



PT.SelectedItem=Item;


Redraw();


GC.Collect();


return true;


}


else return false;


}

et l'evenement renvoi ici


private void PTV_SelectedItemChanging(object sender, PrintTemplateView.SelectedItemChangingEventArgs e)


{


tbtnDelItem.Enabled=(e.Item!=null);



Control CtrlPTItem;


if (this.panControl.Controls.Count>0)


{


CtrlPTItem=this.panControl.Controls[0];


this.panControl.Controls.Clear();


CtrlPTItem.GotFocus-=new EventHandler(ItemGUI_GotFocus);


CtrlPTItem.Leave-=new EventHandler(ItemGUI_Leave);


}





if (e.Item != null)


CtrlPTItem=e.Item.GetUI();


else


{


Label Ctrllbl=(Label)(CtrlPTItem=new Label());


Ctrllbl.Text="Veuillez sélectionner un objet";


Ctrllbl.AutoSize=true;


}





if (CtrlPTItem==null)


{


Label Ctrllbl=(Label)(CtrlPTItem=new Label());


Ctrllbl.Text="Aucune interface disponible";


Ctrllbl.AutoSize=true;


}



this.panControl.Controls.Add(CtrlPTItem);


CtrlPTItem.GotFocus+=new EventHandler(ItemGUI_GotFocus);


CtrlPTItem.Leave+=new EventHandler(ItemGUI_Leave);


ReplaceCtrlPTItem(CtrlPTItem);



treeDocument.SelectedNode=GetObjectTreeNode(e.Item, treeDocument.Nodes);


}
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006

Voilà j'ai trouver d'où ça vennait mais je ne sais pas comment je
pourrais faire pour resoudre le problème. c'est au moment ou je crée
une image pour dessiner l'objet.



j'ai remarquer qu'en executant ce code :



Bitmap backbmp = new Bitmap(pt[0].X, pt[0].Y, g);


imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));


imgBack.Dispose();


imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));


imgBack.Dispose();


imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));


imgBack.Dispose();


imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));


imgBack.Dispose();


imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));


backbmp.Dispose();


GC.Collect();




(pt[0].X et pt[0].Y valent 782 et 1160 dans mon programme)



On aperçoit une grosse perte de memoire (à peu près 3 Mo à chaque instance malgré le dispose et le GC.Collect !!!!)



Si quelqu'un a une idée ... je suis preneur
Messages postés
2368
Date d'inscription
mardi 17 avril 2001
Statut
Modérateur
Dernière intervention
26 décembre 2007
19
rajoute après çà:
backbmp = null; quand tu ne t'en sers plus

et pourquoi tu fais cette suite d'instructions , elle n'a aucun intérêt...

::|The S@ib|::
MVP C#.NET
Messages postés
337
Date d'inscription
jeudi 19 décembre 2002
Statut
Membre
Dernière intervention
15 avril 2006

Non toujours la même chose

j'ai taper des imgback.dispose imgback = null et GC.Collect partout mais rien à faire



J'ai juste fait ce code pour tester...



La code complet est



if (imgBack != null) \\ ***
{
imgBack.Dispose();
imgBack = null;
};

g.ResetTransform();
InitTransform(g);
Point[] pt = {new Point(205, 305)};
g.TransformPoints(CoordinateSpace.Device, CoordinateSpace.World, pt);
Bitmap backbmp = new Bitmap(pt[0].X, pt[0].Y);
imgBack = Image.FromHbitmap(backbmp.GetHbitmap(BackColor));
backbmp.Dispose();
backbmp = null;
GC.Collect();
GC.WaitForPendingFinalizers(); \\ ***
Graphics gbmp = Graphics.FromImage(imgBack);
gbmp.ResetTransform();
gbmp.PageUnit=GraphicsUnit.Millimeter;
gbmp.ScaleTransform(Zoom,Zoom);
gbmp.TranslateTransform(2, 2);
gbmp.Clear(this.BackColor);
gbmp.FillRectangle(new SolidBrush(Color.Gray),1,1,200,300);
gbmp.FillRectangle(new SolidBrush(Color.White),0,0,200,300);
gbmp.DrawRectangle(new Pen(Color.Black,25/g.DpiX*Zoom),0,0,200,300);
PT.Redraw(gbmp, cb, false, false);
gbmp.Dispose();

Il y a une perte de 3 Mo entre les 2 ***

j'en -3 au premier dispose puis +3 au new bitmap +6 au image.From bitmap et -3 à backbmp.Dispose();

c'est le +6 qui est bizarre...pourquoi 6Mo en alouant et 3 qd on libere la memoire

PS : Merci quand même pour vos reponses