Wednesday, October 10, 2012

Memory leak

     Memory leak is something to be avoided while programming, In .NET, we have the garbage collector, I thought that the System.GC takes care of the left out objects, after going though this informative article : http://www.codeproject.com/Articles/19490/Memory-Leak-Detection-in-NET
how the GC works is ‘GC builds a list of live objects, and then walks through the heap in search of objects which are not present in this list of live objects. After finding out the objects which are not present in this list of live objects, it marks them all as garbage, and starts to compact the memory to remove holes which were created by unreferenced (dead) objects.’ So Any objects with a weak reference are cleared for Garbage collection. The steps GC goes through:

1.    Execution Engine Suspension – The EE is suspended until all managed threads have reached a point in their code execution deemed "safe".
2.    Mark – Objects that don't have roots are marked garbage.
3.    Plan – The GC creates a budget for each generation being collected, and then determines the amount of fragmentation that will exist in the managed heap as a result of a GC collection.
4.    Sweep – Deletes all objects marked for deletion.
5.    Compact – Moves all non-pinned objects that survived the GC to the lower end of the heap.
6.    Execution Engine Restart – Restart the execution of managed threads.

And Unmanaged objects cannot be reclaimed by GC, therefore a ‘finalize’ a necessary there.
Now to the point: If an object is declared using the new keyword… like let’s say
TextBox tb = new TextBox;
Then later in the code the textbox is initialized again like:
tb = (TextBox)Page.FindControl(“TextBox1”);
then does this mean there is a leak?
So I used the GC.GetTotalMemory method to check what happens
Not this may not be the right way to get the memory used. Many in these forum Posts argue that it’s not possible to get the memory used during runtime.
The below console application calculates the memory used before and after a DataTable Object is created, And also if the DataTable is newed again.

namespace memTest
{
    class Program
    {
        static void Main(string[] args)
        {
            long mem = 0;
            mem = GC.GetTotalMemory(true);
            Console.WriteLine(mem.ToString());
            DataTable dt = new DataTable();
            mem = GC.GetTotalMemory(true);
            Console.WriteLine("After Datatabled is newed"+mem.ToString());
            dt = new DataTable();
            mem = GC.GetTotalMemory(true);
            Console.WriteLine("After Datatabled is newed again" + mem.ToString());
            Console.Read();
        }
    }
}

This is the output I got:



 105752 Is at the start, After the DataTable is created It becomes 109960 and after the same DataTable is 'newed' again, the memory remains the same.
And therefore does this mean that the garbage collector recognizes and manages the memory re-allocation?

Your comments please







Thursday, May 3, 2012

Exporting a GridView To Excel is simple
Well... but it soms come with some complications
If the gridview has TextBoxes or Checkboxes, you would have to take only the value and put it to a literal control, then export.
And while exporting; If you are using the UpdatePanel, it means you cannot have the export button within the panel,
as this works against the response object to create the excel file, you would have to add a postback trigger to the button.


the .aspx
<asp:UpdatePanel runat=server ID=updPnl>
<ContentTemplate>
<table>
<tr><td><asp:ImageButton ID="LinkButtonExcel"  runat="server" ImageUrl="~images/ex.jpg"
        ToolTip="Click to export contents of grid to Excel."
        onclick="LinkButtonExcel_Click" CausesValidation="false"></asp:ImageButton>
</td></tr>
<tr><td>
<asp:GridView ID="GridView1" runat="server" AutoGenerateColumns="True" ></asp:GridView>
<td><tr>

</table>
 </ContentTemplate></UpdatePanel>

the codebehind

.cs
protected void LinkButtonExcel_Click(object sender, ImageClickEventArgs e)
        {
            try
            {
               
GridView1.AllowPaging = false;
                bindRpt(); // this method binds the gridview
                GenerateExcel(
GridView1);
            }
            catch
            {
                Page.ClientScript.RegisterStartupScript(this.GetType(), "", "alert('Could not Export to excel, please try again later );", true);
            }
        }


public void GenerateExcel(GridView grdSource)
        {

            StringBuilder sbDocBody = new StringBuilder();
            try
            {
                // Declare Styles
                sbDocBody.Append("<style>");
                sbDocBody.Append(".Header {  background-color:Navy; color:#ffffff; font-weight:bold;font-family:Verdana; font-size:12px;}");
                sbDocBody.Append("</style>");
                //
                StringBuilder sbContent = new StringBuilder();

                sbDocBody.Append("<br><table align=\"center\" cellpadding=0 cellspacing=0 border=1>");

                if (grdSource.Rows.Count > 0)
                {
                    for (int i = 0; i < grdSource.Columns.Count - 1; i++)
                    {
                        sbDocBody.Append("<td class=\"Header\" width=\"120\">" + grdSource.Columns[i].HeaderText + "</td>");
                    }
                    sbDocBody.Append("</tr>");
                    // Add Data Rows
                    for (int i = 0; i < grdSource.Rows.Count; i++)
                    {
                        sbDocBody.Append("<tr>");
                        for (int j = 0; j < grdSource.Columns.Count - 1; j++)
                        {
                            if (grdSource.Rows[i].Cells[j].Controls.Count == 0)
                            {
                                sbDocBody.Append("<td class=\"Content\">" + grdSource.Rows[i].Cells[j].Text + "</td>");
                            }
                            else
                            {
                                if (grdSource.Rows[i].Cells[j].Controls[1].ToString() == "System.Web.UI.WebControls.LinkButton")
                                {
                                    LinkButton lnkBtn = (LinkButton)grdSource.Rows[i].Cells[j].Controls[1];
                                    sbDocBody.Append("<td class=\"Content\">" + lnkBtn.Text + "</td>");
                                }
                                else if (grdSource.Rows[i].Cells[j].Controls[1].ToString() == "System.Web.UI.WebControls.Label")
                                {
                                    Label lblData = (Label)grdSource.Rows[i].Cells[j].Controls[1];
                                    sbDocBody.Append("<td class=\"Content\">" + lblData.Text + "</td>");
                                }
                                else
                                if (grdSource.Rows[i].Cells[j].Controls[1].ToString() == "System.Web.UI.WebControls.TextBox")
                                {
                                    TextBox tb = (TextBox)grdSource.Rows[i].Cells[j].Controls[1];
                                    sbDocBody.Append("<td class=\"Content\">" + tb.Text + "</td>");
                                }
                            }
                        }
                        sbDocBody.Append("</tr>");
                    }
                    sbDocBody.Append("</table>");
                 }
                //
                HttpContext.Current.Response.Clear();
                HttpContext.Current.Response.Buffer = true;
                //
                HttpContext.Current.Response.AppendHeader("Content-Type", "application/ms-excel");
                HttpContext.Current.Response.AppendHeader("Content-disposition", "attachment; filename=BiasReport-" + DateTime.Now.ToLongDateString() + ".xls");
                HttpContext.Current.Response.Write(sbDocBody.ToString());
                HttpContext.Current.Response.End();
            }
            catch (Exception ex)
            {
                // Ignore
            }
        }

 

Friday, February 17, 2012

Size of a DataTable in a Session

Storing an object in the session for easy access by other pages is the easiest way to move around objects in a web application but
What’s the size of a DataTable stored in a session
I used serialization as shown here http://stackoverflow.com/questions/1689045/can-i-get-the-size-of-a-session-object-in-bytes-in-c
After creating a DataTable with a few columns and 100 rows,
like...
        private DataTable getTable()
        {
            #region make tables         
            //        Add around 10 columns to the table
            #endregion
            for (int i = 0; i < 100; i++)
            {
                dt.Rows.Add(...//add 10 rows
                dt.AcceptChanges();
            }
            return dt;
        }
After putting it to a session I tried calculating the memory using...

protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                long totalSessionBytes;
                BinaryFormatter b = new BinaryFormatter();
                MemoryStream m = new MemoryStream();
                DataTable dt = getTable();
                Session.Add("tab", dt);
                b.Serialize(m, Session["tab"]);
                totalSessionBytes = m.Length;
                Response.Write("Total MB = " + (totalSessionBytes/1000).ToString());

            }
        }


Then It showed 137 MB! And even when Session is replaced with ViewState, it gave the same result. 137! Well… So I saved the binary object to a file Making the DataTable in a constructor of a class, and serializing it...

    [Serializable]
    public class serialtest
    {

        private DataTable dt = new DataTable();


        public serialtest()
        {
            dt = getTable();
        }
     
        private DataTable getTable()
        {
              //the method above
        }
    }


Then making the object and serializing it to a file
private void makefile(serialtest s)
        {
            Stream str = File.OpenWrite("C:\\ serial.txt");
            BinaryFormatter formatter = new BinaryFormatter();
            formatter.Serialize(str, s);
            str.Close();

        }


The size of the file, it said 240KB I did the same thing with a ViewState and the result was exactly the same So, there is no conclusion as to how you will be able to get the size of the object in a viewstate or a session

Friday, February 10, 2012

RENDER FAILED

This problem usually shows up when the view goes wrong in SharePoint 2007, this problem had shown itself on a list and when the view was modified, it worked
If you google <!-- #RENDER FAILED --> , it gives you a number of solutions but all of them describe the problem for a list in which the view needs to be changes and/or modified
I had this problem in every list and library on every site, and SharePoint was not allowing me to create anything.
Then After checking the content database, I found it had been made read-only , therefore, SharePoint cannot work without write permissions one the content DB (obviously)
after changing this everything was back to normal again.
There were no errors in any of the lists/libraries/workflows