Web Q&A

Releasing Memory in JScript, Bulkload Problems, and More

Edited by Nancy Michell

Q I have some questions regarding garbage collection in JScript®. I think I have a memory leak in Microsoft® Internet Explorer 6.0, but on the other hand it might be a circular reference problem. In my code, I assume "new Object()" is owned by JScript but "document.createElement" is owned by the Internet Explorer DOM and therefore the garbage collector from JScript cannot release the DOM element. Is this correct? What is the best way to avoid this?

Q I have some questions regarding garbage collection in JScript®. I think I have a memory leak in Microsoft® Internet Explorer 6.0, but on the other hand it might be a circular reference problem. In my code, I assume "new Object()" is owned by JScript but "document.createElement" is owned by the Internet Explorer DOM and therefore the garbage collector from JScript cannot release the DOM element. Is this correct? What is the best way to avoid this?

When you load the code in Internet Explorer 6.0 and click Refresh, you can observe increasing memory in Task Manager:

<html>
<body>
  <script type="text/JScript">
    for (i=0; i<1000; i++) {    // this loop enforces the effect
      var model = new Object();
      var element = document.createElement("<br>");
      model.myElement = element;
      element.myModel = model;
      model = null;
      element = null;
      } 
  </script>
</body>
</html>

A This isn't a memory leak. You're creating new text on the page a thousand times! That's going to make the page bigger. It's only a memory leak if you create a bunch of objects that cannot be reached and also cannot be freed. Here you're creating a bunch of elements that Internet Explorer needs to hold onto to render the page correctly. Internet Explorer doesn't know that later you're not going to run a script that manipulates all those objects you just created.

A This isn't a memory leak. You're creating new text on the page a thousand times! That's going to make the page bigger. It's only a memory leak if you create a bunch of objects that cannot be reached and also cannot be freed. Here you're creating a bunch of elements that Internet Explorer needs to hold onto to render the page correctly. Internet Explorer doesn't know that later you're not going to run a script that manipulates all those objects you just created.

When the page goes away—when you navigate away in the browser—the memory will be released. It will not leak. The circular reference is broken when the page is destroyed.

Q I'm trying to import some XML into a database by passing the XML to a stored procedure which is being called by the ADO.NET SQL provider. When the XML file is too large, it fails with a SqlException (which says that a severe error occurred). I've tracked it down to a failure in sp_xml_preparedocument.

Q I'm trying to import some XML into a database by passing the XML to a stored procedure which is being called by the ADO.NET SQL provider. When the XML file is too large, it fails with a SqlException (which says that a severe error occurred). I've tracked it down to a failure in sp_xml_preparedocument.

It works fine with an XML file that has 43403 characters, but if I add one more character (by changing the final Vendor field from "Micros" to "Microso"), I get the failure. The parameter being passed to the stored procedure is of type ntext. I can't use bulkload. Is this a known issue? Is the size limit coming from ADO.NET, SQL, or sp_xml_preparedocument? And finally, is there a workaround?

A Actually, one way you could use bulkload is to load the data into staging tables and then do your insert and update from there. As far as sp_xml_preparedocument failing, such problems have happened before. Most of them were due to one of the following: a single wrong character (or character in wrong encoding) that trips up the parser, using an nvarchar that truncates the XML, or using text instead of ntext (which leads to improper characters).

A Actually, one way you could use bulkload is to load the data into staging tables and then do your insert and update from there. As far as sp_xml_preparedocument failing, such problems have happened before. Most of them were due to one of the following: a single wrong character (or character in wrong encoding) that trips up the parser, using an nvarchar that truncates the XML, or using text instead of ntext (which leads to improper characters).

However, on the off chance that none of these are the actual cause of your problem, the next step you should take is to try the latest SQL Server™ service pack (https://www.microsoft.com/sql) in order to see if that rectifies this problem.

Q I'm designing a search interface and I want to use translations for the word "Go". Many Web sites use "Go" in a variety of languages to signify the submit function. But should I use the word or some type of icon? Should I just use an arrow icon?

Q I'm designing a search interface and I want to use translations for the word "Go". Many Web sites use "Go" in a variety of languages to signify the submit function. But should I use the word or some type of icon? Should I just use an arrow icon?

A Arrow symbols like those shown in Figure 1 are directional, so their interpretation depends on where they are placed. Text is not directional, so it doesn't matter where you decide to place it; the meaning doesn't change.

A Arrow symbols like those shown in Figure 1 are directional, so their interpretation depends on where they are placed. Text is not directional, so it doesn't matter where you decide to place it; the meaning doesn't change.

Figure 1 Arrow Icons

Figure 1** Arrow Icons **

While studies may show self-reported user preference for one button over another, this is much less important than understanding the interface on first encounter. This is especially true for a tool or Web Service that may be used only occasionally.

No matter what label you choose for the submit button, however, remember it's most important to support the Enter key as an option for search query submission. Users rarely comment on the Enter key functionality unless it's not there; then you'll hear about it! Outside of that, for usability purposes, the iconography for submission means much less than the proximity of the submit button to the search text box (preferably to the right of it).

Q I have a question about persisting a data tree structure to a SQL database and having that tree be searchable and fast. XML could represent the structure and I could use SQL for the storage, but I want to be able to search the data tree quickly. Unfortunately, there will be a variable number of branches and leaves much like a directory structure on a file system, so I can't use a fixed table relationship. What is the best way to build this database structure?

Q I have a question about persisting a data tree structure to a SQL database and having that tree be searchable and fast. XML could represent the structure and I could use SQL for the storage, but I want to be able to search the data tree quickly. Unfortunately, there will be a variable number of branches and leaves much like a directory structure on a file system, so I can't use a fixed table relationship. What is the best way to build this database structure?

A SQLXML seems to perform much better on shallow hierarchies than deep ones. As the nesting of the XML increases, so does memory usage and processing time. Take a look at this article on processing hierarchies in SQL: Expanding Hierarchies.

A SQLXML seems to perform much better on shallow hierarchies than deep ones. As the nesting of the XML increases, so does memory usage and processing time. Take a look at this article on processing hierarchies in SQL: Expanding Hierarchies.

The deeper the XML nests, the more expensive it is to parse or construct (from flat data). Try parsing XML over a range of 1,000-10,000 levels deep using the world's fastest XML parser. Try running a simple XSLT script over that same data. Deep hierarchies are almost always more expensive than shallow hierarchies.

When retrieving XML through XPath, SQLXML uses the SQL Server FOR XML EXPLICIT mode, which essentially requires ordered outer unions. According to various industry studies, when constructing XML from flat relational data, the ordered outer union approach generally outperforms every other approach except for hybrid shredding (in which the data granularity is determined adaptively or otherwise adjusted to avoid unnecessary joins). SQLXML doesn't control or modify the user's data layout, so adaptive storage strategies are not an option.

When modifying XML through updategrams, SQLXML shreds the data (takes it from a hierarchial format into a flat format) and generates atomic DML statements, just like in your example. When inserting XML through bulkload, SQLXML again shreds the data, but uses a SQL bulkload operation. Both are very efficient.

On retrieval, the worst case is that you get roughly one select per element type (not per element), union all'd together and then ordered by primary key columns for nesting. Frequently, there are two main performance problems with this approach. First, SQL Server does not optimize cast primary key columns well (you should use lots of sql:datatype/xsd:type qualifiers in the annotated schema so that SQLXML can eliminate unnecessary casts from the query it generates). Second, ordered outer unions scale badly beyond, say, hundreds of element types.

The example you cite is not an apples-to-apples comparison because it does not generate XML. It's easy to generate flat data that represents a hierarchy. The expensive part is turning that flat representation into a true hierarchical representation (XML). The deeper the hierarchy, the more expensive the transformation. If you run a performance analysis tool over SQLXML, you'll see that most of the processing time is taken up by datatype conversions in OLEDB and conversion from the flat rowset into XML hierarchy, not in the execution of the SQL query itself. You can also try running a union query without the FOR XML EXPLICIT at the end and verify that the SQL query is not the bottleneck.

If you choose to use XML to persist the data tree structure, then you should consider using SQLXML3.0 to shred this document into a SQL Server database. One possible solution is to create an annotated XSD schema that describes the instance XML document. The max-depth annotation allows you to describe recursive tree structure. The SQLXML bulkload feature allows you to shred this document to the SQL Server database. The SQLXML help file has some examples. Take a look at the max-depth section where it describes how to treat XML documents with variable levels of hierarchy (as long as they are recursive and you can specify the maximum number of levels).

Q I have noticed that many Web sites which require a login in order to access some of their content or services don't place the login box directly on the home page. Most sites include a link to sign in somewhere at the top of the home page or don't even place a link on the home page at all, but instead direct the user to a login page when he navigates to a section of the site that requires login.

Q I have noticed that many Web sites which require a login in order to access some of their content or services don't place the login box directly on the home page. Most sites include a link to sign in somewhere at the top of the home page or don't even place a link on the home page at all, but instead direct the user to a login page when he navigates to a section of the site that requires login.

Should a Web site show a login section directly on the home page where the user can enter a user name and password? Or is a small sign-in link enough? Or is it better to go with the third option where the user is prompted to log in only when they need to?

A Rather than placing the user name and password request fields on just the home page or on a separate page dedicated for logging in, it might be appropriate in some cases to provide the user name and password fields on all pages. This does take some screen real estate, but it reminds unregistered users that there is more available if they log in. Taking users to a dedicated login screen is disorienting, even when you return them to the page they came from.

A Rather than placing the user name and password request fields on just the home page or on a separate page dedicated for logging in, it might be appropriate in some cases to provide the user name and password fields on all pages. This does take some screen real estate, but it reminds unregistered users that there is more available if they log in. Taking users to a dedicated login screen is disorienting, even when you return them to the page they came from.

Q Suppose you have a function, and sometimes that function is also inside a try... catch..., but other times it isn't. And suppose when it is in a try catch, I was to throw the same error again, but when it isn't I don't want to because I'll get an error saying "an exception has been thrown but not caught."

Q Suppose you have a function, and sometimes that function is also inside a try... catch..., but other times it isn't. And suppose when it is in a try catch, I was to throw the same error again, but when it isn't I don't want to because I'll get an error saying "an exception has been thrown but not caught."

So I want to rethrow the error only if there is a nested catch to catch it. Is there a way to tell if there is a catch to catch a throw before you throw? Here's the JScript code:

try
{  // Do something that causes an error
}
catch(e)
{
    if (<there is another catch(e)>)
    {
        throw(e);
    }
        else
    {   // do something
        }
}

A Sorry, there's no way to detect whether a caller will catch an exception you throw. However, your question reveals a potential design flaw in your application. The whole point of throwing exceptions is to say "something unexpected happened, and I don't know how to handle it." If you can get away without rethrowing the exception, then apparently you can handle this unexpected event. If you can handle it and continue, then don't ever rethrow the exception. If you can't handle it, defer to your caller to handle it. You should never have to make a decision based on what the caller can handle—make the decision based on what you can handle.

A Sorry, there's no way to detect whether a caller will catch an exception you throw. However, your question reveals a potential design flaw in your application. The whole point of throwing exceptions is to say "something unexpected happened, and I don't know how to handle it." If you can get away without rethrowing the exception, then apparently you can handle this unexpected event. If you can handle it and continue, then don't ever rethrow the exception. If you can't handle it, defer to your caller to handle it. You should never have to make a decision based on what the caller can handle—make the decision based on what you can handle.

If no caller can handle the exception, the right thing to do is to halt the program. A program that can't handle an exception is badly broken and needs to be stopped before it does damage. If your caller can't handle an exception then either rewrite the caller or don't throw an exception.

Also, don't ever use exceptions as control flow for main-line cases. Exception handling was designed and implemented specifically to manage fatal errors, so that's all it should be used for.

Q In ASP.NET (specifically with Visual Basic®), how do you post form data to a Web page? When an ASP.NET Web page is rendered, the form's action field is automatically changed to post to itself. I need to show a login page, and when "Login" is clicked, post the form data to a different Web site (that Web site is set up to use Request.Form to capture my data). I know I can capture the data myself and pass it in a query string, but that's not an option. I must post it to the other site.

Q In ASP.NET (specifically with Visual Basic®), how do you post form data to a Web page? When an ASP.NET Web page is rendered, the form's action field is automatically changed to post to itself. I need to show a login page, and when "Login" is clicked, post the form data to a different Web site (that Web site is set up to use Request.Form to capture my data). I know I can capture the data myself and pass it in a query string, but that's not an option. I must post it to the other site.

A If you're just using HTMLControls on your form, all you need to do to post to another page is remove the runat="server" from the FORM tag and set the action attribute to the URL you want to post to. If you don't add the runat="server", the FORM element will be sent to the client unaltered. This does not prevent you from setting values of the HTMLControls on your form in the Web form's Page_Load event.

A If you're just using HTMLControls on your form, all you need to do to post to another page is remove the runat="server" from the FORM tag and set the action attribute to the URL you want to post to. If you don't add the runat="server", the FORM element will be sent to the client unaltered. This does not prevent you from setting values of the HTMLControls on your form in the Web form's Page_Load event.

If you are using WebControls, the runat="server" on the form is required. However, you can still post to another page. Details for this case can be found at: Passing Server Control Values Between Pages.

Got a question? Send questions and comments to WebQA@microsoft.com.

Thanks to the following Microsoft developers for their technical expertise: Avner Aharoni, Amy Alberts, Greg Alger, Tom Alphin, Bear, Michael Brundage, Eric Lippert, Rainer Maurer, Everett McKay, Tosh Meston, Manal Mohanna, Michael Rys, Marc Shepard, Kim Tapia St Amant, Mark Stevenson (MCS), Maarten van Dantzich.