Ahmad Masykur

Share your knowledge although one function!

About the author

Ahmad Masykur is a Software Architecture Engineer at PT. Freeport Indonesia Jakarta Indonesia.
In this blog, I share things of interest to me. Most topics are likely to be related to software development, but don't hold me to it.

Certificates



Awards


Powered by

Widget Prayer Time not found.

There is an error in XML document (4, 16278).X

Page List

Validators


Ahmad Masykur

ASP.NET 4 Performance Tips

Performance atau dalam Bahasa Indonesia disebut sebagai kinerja merupakan sebuah hal yang penting dalam sebuah aplikasi. Dalam sebuah aplikasi web terdapat beberapa faktor yang menyebabkan kinerja bagus atau buruk. Secara umum kinerja aplikasi dinyatakan bagus jika waktu tanggap (response time) dapat tercapai secepat mungkin. Untuk aplikasi web publik seperti www.facebook.com, www.kaskus.us, www.detik.com dan situs lainnya, dengan kinerja yang baik dapat membuat pengunjung betah mengunjunginya. Untuk aplikasi bisnis, kinerja yang bagus akan meningkatkan kinerja karyawan yang menjadi usernya.

Berikut akan saya utarakan beberapa tips untuk meningkatkan kinerja aplikasi ASP.NET 4. Beberapa tips juga dapat digunakan juga untuk versi ASP.NET sebelumnya.

Aplikasi ASP.NET sebelum dioptimasi.

Pertama akan saya buat aplikasi sederhana menggunakan ASP.NET tanpa optimasi apapun. Dalam contoh ini saya buat sebuah halaman yang menampilkan data tabular yang datanya saya ambil dari XML. Halaman ini menggunakan Ajax dengan UpdatePanel. Buat sebuah aplikasi web project baru dan pilih ASP.NET Web Application.

image

Puat satu class Product untuk entity data product.

namespace WebApplication1
{
    public class Product
    {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Supplier { get; set; }
        public string Category { get; set; }
        public string QuantityPerUnit { get; set; }
        public decimal UnitPrice { get; set; }
        public decimal UnitsInStock { get; set; }
        public decimal UnitsOnOrder { get; set; }
        public decimal ReorderLevel { get; set; }
    }
}

Buat file XML yang berisi data berikut dan tempatkan dalam folder App_Data. Beri nama file Products.xml

<?xml version="1.0" encoding="utf-8" ?>
<Products>
  <Product ID="1" Name="Chai" Supplier="Exotic Liquids" Category="Beverages" QuantityPerUnit="10 boxes x 20 bags" UnitPrice="18.0000" UnitsInStock="39" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="2" Name="Chang" Supplier="Exotic Liquids" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="19.0000" UnitsInStock="17" UnitsOnOrder="40" ReorderLevel="25" />
  <Product ID="3" Name="Aniseed Syrup" Supplier="Exotic Liquids" Category="Condiments" QuantityPerUnit="12 - 550 ml bottles" UnitPrice="10.0000" UnitsInStock="13" UnitsOnOrder="70" ReorderLevel="25" />
  <Product ID="4" Name="Chef Anton's Cajun Seasoning" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="48 - 6 oz jars" UnitPrice="22.0000" UnitsInStock="53" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="5" Name="Chef Anton's Gumbo Mix" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="36 boxes" UnitPrice="21.3500" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="6" Name="Grandma's Boysenberry Spread" Supplier="Grandma Kelly's Homestead" Category="Condiments" QuantityPerUnit="12 - 8 oz jars" UnitPrice="25.0000" UnitsInStock="120" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="7" Name="Uncle Bob's Organic Dried Pears" Supplier="Grandma Kelly's Homestead" Category="Produce" QuantityPerUnit="12 - 1 lb pkgs." UnitPrice="30.0000" UnitsInStock="15" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="8" Name="Northwoods Cranberry Sauce" Supplier="Grandma Kelly's Homestead" Category="Condiments" QuantityPerUnit="12 - 12 oz jars" UnitPrice="40.0000" UnitsInStock="6" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="9" Name="Mishi Kobe Niku" Supplier="Tokyo Traders" Category="Meat/Poultry" QuantityPerUnit="18 - 500 g pkgs." UnitPrice="97.0000" UnitsInStock="29" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="10" Name="Ikura" Supplier="Tokyo Traders" Category="Seafood" QuantityPerUnit="12 - 200 ml jars" UnitPrice="31.0000" UnitsInStock="31" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="11" Name="Queso Cabrales" Supplier="Cooperativa de Quesos 'Las Cabras'" Category="Dairy Products" QuantityPerUnit="1 kg pkg." UnitPrice="21.0000" UnitsInStock="22" UnitsOnOrder="30" ReorderLevel="30" />
  <Product ID="12" Name="Queso Manchego La Pastora" Supplier="Cooperativa de Quesos 'Las Cabras'" Category="Dairy Products" QuantityPerUnit="10 - 500 g pkgs." UnitPrice="38.0000" UnitsInStock="86" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="13" Name="Konbu" Supplier="Mayumi's" Category="Seafood" QuantityPerUnit="2 kg box" UnitPrice="6.0000" UnitsInStock="24" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="14" Name="Tofu" Supplier="Mayumi's" Category="Produce" QuantityPerUnit="40 - 100 g pkgs." UnitPrice="23.2500" UnitsInStock="35" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="15" Name="Genen Shouyu" Supplier="Mayumi's" Category="Condiments" QuantityPerUnit="24 - 250 ml bottles" UnitPrice="15.5000" UnitsInStock="39" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="16" Name="Pavlova" Supplier="Pavlova, Ltd." Category="Confections" QuantityPerUnit="32 - 500 g boxes" UnitPrice="17.4500" UnitsInStock="29" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="17" Name="Alice Mutton" Supplier="Pavlova, Ltd." Category="Meat/Poultry" QuantityPerUnit="20 - 1 kg tins" UnitPrice="39.0000" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="18" Name="Carnarvon Tigers" Supplier="Pavlova, Ltd." Category="Seafood" QuantityPerUnit="16 kg pkg." UnitPrice="62.5000" UnitsInStock="42" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="19" Name="Teatime Chocolate Biscuits" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="10 boxes x 12 pieces" UnitPrice="9.2000" UnitsInStock="25" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="20" Name="Sir Rodney's Marmalade" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="30 gift boxes" UnitPrice="81.0000" UnitsInStock="40" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="21" Name="Sir Rodney's Scones" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="24 pkgs. x 4 pieces" UnitPrice="10.0000" UnitsInStock="3" UnitsOnOrder="40" ReorderLevel="5" />
  <Product ID="22" Name="Gustaf's Knäckebröd" Supplier="PB Knäckebröd AB" Category="Grains/Cereals" QuantityPerUnit="24 - 500 g pkgs." UnitPrice="21.0000" UnitsInStock="104" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="23" Name="Tunnbröd" Supplier="PB Knäckebröd AB" Category="Grains/Cereals" QuantityPerUnit="12 - 250 g pkgs." UnitPrice="9.0000" UnitsInStock="61" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="24" Name="Guaraná Fantástica" Supplier="Refrescos Americanas LTDA" Category="Beverages" QuantityPerUnit="12 - 355 ml cans" UnitPrice="4.5000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="25" Name="NuNuCa Nuß-Nougat-Creme" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="20 - 450 g glasses" UnitPrice="14.0000" UnitsInStock="76" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="26" Name="Gumbär Gummibärchen" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="100 - 250 g bags" UnitPrice="31.2300" UnitsInStock="15" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="27" Name="Schoggi Schokolade" Supplier="Heli Süßwaren GmbH &amp; Co. KG" Category="Confections" QuantityPerUnit="100 - 100 g pieces" UnitPrice="43.9000" UnitsInStock="49" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="28" Name="Rössle Sauerkraut" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Produce" QuantityPerUnit="25 - 825 g cans" UnitPrice="45.6000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="29" Name="Thüringer Rostbratwurst" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Meat/Poultry" QuantityPerUnit="50 bags x 30 sausgs." UnitPrice="123.7900" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="30" Name="Nord-Ost Matjeshering" Supplier="Nord-Ost-Fisch Handelsgesellschaft mbH" Category="Seafood" QuantityPerUnit="10 - 200 g glasses" UnitPrice="25.8900" UnitsInStock="10" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="31" Name="Gorgonzola Telino" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="12 - 100 g pkgs" UnitPrice="12.5000" UnitsInStock="0" UnitsOnOrder="70" ReorderLevel="20" />
  <Product ID="32" Name="Mascarpone Fabioli" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="24 - 200 g pkgs." UnitPrice="32.0000" UnitsInStock="9" UnitsOnOrder="40" ReorderLevel="25" />
  <Product ID="33" Name="Geitost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="500 g" UnitPrice="2.5000" UnitsInStock="112" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="34" Name="Sasquatch Ale" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="14.0000" UnitsInStock="111" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="35" Name="Steeleye Stout" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="18.0000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="36" Name="Inlagd Sill" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="24 - 250 g  jars" UnitPrice="19.0000" UnitsInStock="112" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="37" Name="Gravad lax" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="12 - 500 g pkgs." UnitPrice="26.0000" UnitsInStock="11" UnitsOnOrder="50" ReorderLevel="25" />
  <Product ID="38" Name="Côte de Blaye" Supplier="Aux joyeux ecclésiastiques" Category="Beverages" QuantityPerUnit="12 - 75 cl bottles" UnitPrice="263.5000" UnitsInStock="17" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="39" Name="Chartreuse verte" Supplier="Aux joyeux ecclésiastiques" Category="Beverages" QuantityPerUnit="750 cc per bottle" UnitPrice="18.0000" UnitsInStock="69" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="40" Name="Boston Crab Meat" Supplier="New England Seafood Cannery" Category="Seafood" QuantityPerUnit="24 - 4 oz tins" UnitPrice="18.4000" UnitsInStock="123" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="41" Name="Jack's New England Clam Chowder" Supplier="New England Seafood Cannery" Category="Seafood" QuantityPerUnit="12 - 12 oz cans" UnitPrice="9.6500" UnitsInStock="85" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="42" Name="Singaporean Hokkien Fried Mee" Supplier="Leka Trading" Category="Grains/Cereals" QuantityPerUnit="32 - 1 kg pkgs." UnitPrice="14.0000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="43" Name="Ipoh Coffee" Supplier="Leka Trading" Category="Beverages" QuantityPerUnit="16 - 500 g tins" UnitPrice="46.0000" UnitsInStock="17" UnitsOnOrder="10" ReorderLevel="25" />
  <Product ID="44" Name="Gula Malacca" Supplier="Leka Trading" Category="Condiments" QuantityPerUnit="20 - 2 kg bags" UnitPrice="19.4500" UnitsInStock="27" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="45" Name="Rogede sild" Supplier="Lyngbysild" Category="Seafood" QuantityPerUnit="1k pkg." UnitPrice="9.5000" UnitsInStock="5" UnitsOnOrder="70" ReorderLevel="15" />
  <Product ID="46" Name="Spegesild" Supplier="Lyngbysild" Category="Seafood" QuantityPerUnit="4 - 450 g glasses" UnitPrice="12.0000" UnitsInStock="95" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="47" Name="Zaanse koeken" Supplier="Zaanse Snoepfabriek" Category="Confections" QuantityPerUnit="10 - 4 oz boxes" UnitPrice="9.5000" UnitsInStock="36" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="48" Name="Chocolade" Supplier="Zaanse Snoepfabriek" Category="Confections" QuantityPerUnit="10 pkgs." UnitPrice="12.7500" UnitsInStock="15" UnitsOnOrder="70" ReorderLevel="25" />
  <Product ID="49" Name="Maxilaku" Supplier="Karkki Oy" Category="Confections" QuantityPerUnit="24 - 50 g pkgs." UnitPrice="20.0000" UnitsInStock="10" UnitsOnOrder="60" ReorderLevel="15" />
  <Product ID="50" Name="Valkoinen suklaa" Supplier="Karkki Oy" Category="Confections" QuantityPerUnit="12 - 100 g bars" UnitPrice="16.2500" UnitsInStock="65" UnitsOnOrder="0" ReorderLevel="30" />
  <Product ID="51" Name="Manjimup Dried Apples" Supplier="G'day, Mate" Category="Produce" QuantityPerUnit="50 - 300 g pkgs." UnitPrice="53.0000" UnitsInStock="20" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="52" Name="Filo Mix" Supplier="G'day, Mate" Category="Grains/Cereals" QuantityPerUnit="16 - 2 kg boxes" UnitPrice="7.0000" UnitsInStock="38" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="53" Name="Perth Pasties" Supplier="G'day, Mate" Category="Meat/Poultry" QuantityPerUnit="48 pieces" UnitPrice="32.8000" UnitsInStock="0" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="54" Name="Tourtière" Supplier="Ma Maison" Category="Meat/Poultry" QuantityPerUnit="16 pies" UnitPrice="7.4500" UnitsInStock="21" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="55" Name="Pâté chinois" Supplier="Ma Maison" Category="Meat/Poultry" QuantityPerUnit="24 boxes x 2 pies" UnitPrice="24.0000" UnitsInStock="115" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="56" Name="Gnocchi di nonna Alice" Supplier="Pasta Buttini s.r.l." Category="Grains/Cereals" QuantityPerUnit="24 - 250 g pkgs." UnitPrice="38.0000" UnitsInStock="21" UnitsOnOrder="10" ReorderLevel="30" />
  <Product ID="57" Name="Ravioli Angelo" Supplier="Pasta Buttini s.r.l." Category="Grains/Cereals" QuantityPerUnit="24 - 250 g pkgs." UnitPrice="19.5000" UnitsInStock="36" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="58" Name="Escargots de Bourgogne" Supplier="Escargots Nouveaux" Category="Seafood" QuantityPerUnit="24 pieces" UnitPrice="13.2500" UnitsInStock="62" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="59" Name="Raclette Courdavault" Supplier="Gai pâturage" Category="Dairy Products" QuantityPerUnit="5 kg pkg." UnitPrice="55.0000" UnitsInStock="79" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="60" Name="Camembert Pierrot" Supplier="Gai pâturage" Category="Dairy Products" QuantityPerUnit="15 - 300 g rounds" UnitPrice="34.0000" UnitsInStock="19" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="61" Name="Sirop d'érable" Supplier="Forêts d'érables" Category="Condiments" QuantityPerUnit="24 - 500 ml bottles" UnitPrice="28.5000" UnitsInStock="113" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="62" Name="Tarte au sucre" Supplier="Forêts d'érables" Category="Confections" QuantityPerUnit="48 pies" UnitPrice="49.3000" UnitsInStock="17" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="63" Name="Vegie-spread" Supplier="Pavlova, Ltd." Category="Condiments" QuantityPerUnit="15 - 625 g jars" UnitPrice="43.9000" UnitsInStock="24" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="64" Name="Wimmers gute Semmelknödel" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Grains/Cereals" QuantityPerUnit="20 bags x 4 pieces" UnitPrice="33.2500" UnitsInStock="22" UnitsOnOrder="80" ReorderLevel="30" />
  <Product ID="65" Name="Louisiana Fiery Hot Pepper Sauce" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="32 - 8 oz bottles" UnitPrice="21.0500" UnitsInStock="76" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="66" Name="Louisiana Hot Spiced Okra" Supplier="New Orleans Cajun Delights" Category="Condiments" QuantityPerUnit="24 - 8 oz jars" UnitPrice="17.0000" UnitsInStock="4" UnitsOnOrder="100" ReorderLevel="20" />
  <Product ID="67" Name="Laughing Lumberjack Lager" Supplier="Bigfoot Breweries" Category="Beverages" QuantityPerUnit="24 - 12 oz bottles" UnitPrice="14.0000" UnitsInStock="52" UnitsOnOrder="0" ReorderLevel="10" />
  <Product ID="68" Name="Scottish Longbreads" Supplier="Specialty Biscuits, Ltd." Category="Confections" QuantityPerUnit="10 boxes x 8 pieces" UnitPrice="12.5000" UnitsInStock="6" UnitsOnOrder="10" ReorderLevel="15" />
  <Product ID="69" Name="Gudbrandsdalsost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="10 kg pkg." UnitPrice="36.0000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="15" />
  <Product ID="70" Name="Outback Lager" Supplier="Pavlova, Ltd." Category="Beverages" QuantityPerUnit="24 - 355 ml bottles" UnitPrice="15.0000" UnitsInStock="15" UnitsOnOrder="10" ReorderLevel="30" />
  <Product ID="71" Name="Flotemysost" Supplier="Norske Meierier" Category="Dairy Products" QuantityPerUnit="10 - 500 g pkgs." UnitPrice="21.5000" UnitsInStock="26" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="72" Name="Mozzarella di Giovanni" Supplier="Formaggi Fortini s.r.l." Category="Dairy Products" QuantityPerUnit="24 - 200 g pkgs." UnitPrice="34.8000" UnitsInStock="14" UnitsOnOrder="0" ReorderLevel="0" />
  <Product ID="73" Name="Röd Kaviar" Supplier="Svensk Sjöföda AB" Category="Seafood" QuantityPerUnit="24 - 150 g jars" UnitPrice="15.0000" UnitsInStock="101" UnitsOnOrder="0" ReorderLevel="5" />
  <Product ID="74" Name="Longlife Tofu" Supplier="Tokyo Traders" Category="Produce" QuantityPerUnit="5 kg pkg." UnitPrice="10.0000" UnitsInStock="4" UnitsOnOrder="20" ReorderLevel="5" />
  <Product ID="75" Name="Rhönbräu Klosterbier" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Beverages" QuantityPerUnit="24 - 0.5 l bottles" UnitPrice="7.7500" UnitsInStock="125" UnitsOnOrder="0" ReorderLevel="25" />
  <Product ID="76" Name="Lakkalikööri" Supplier="Karkki Oy" Category="Beverages" QuantityPerUnit="500 ml" UnitPrice="18.0000" UnitsInStock="57" UnitsOnOrder="0" ReorderLevel="20" />
  <Product ID="77" Name="Original Frankfurter grüne Soße" Supplier="Plutzer Lebensmittelgroßmärkte AG" Category="Condiments" QuantityPerUnit="12 boxes" UnitPrice="13.0000" UnitsInStock="32" UnitsOnOrder="0" ReorderLevel="15" />  
</Products>

Buat beberapa file JavaScript berikut

1. Divider.js

// Divider.js
function divider(value1, value2) {
    if (typeof (value1) == "number" && typeof (value2) == "number") {
        var result = value1 / value2;
        return result;
    } else {
        return null;
    }
}

2. Multiplier.js

// Multiplier.js
function multiplier(value1, value2) {
    if (typeof (value1) == "number" && typeof (value2) == "number") {
        var result = value1 * value2;
        return result;
    } else {
        return null;
    }
}

3. Default.js

// Default.js
$(document).ready(function () {
    $('#Multiplier').click(function () {
        var value1 = parseFloat($('#Value1').val());
        var value2 = parseFloat($('#Value2').val());
        $('#Result').val(multiplier(value1, value2));
    });
    $('#Divider').click(function () {
        var value1 = parseFloat($('#Value1').val());
        var value2 = parseFloat($('#Value2').val());
        $('#Result').val(divider(value1, value2));
    });
});

Ketiga file javascript file tersebut beserta jQuery akan digunakan dalam halaman default.aspx. Ganti halaman Default.aspx yang sudah dibuat oleh Visual Studio project template dengan code berikut.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<asp:Content ID="HeaderContent" runat="server" ContentPlaceHolderID="HeadContent">
</asp:Content>
<asp:Content ID="BodyContent" runat="server" ContentPlaceHolderID="MainContent">
    <script type="text/javascript" src="Scripts/jquery-1.3.2.min.js"></script>
    <script type="text/javascript" src="Scripts/multiplier.js"></script>
    <script type="text/javascript" src="Scripts/divider.js"></script>
    <script type="text/javascript" src="Scripts/Default.js"></script>
    <h2>
        Welcome to ASP.NET!
    </h2>
    <asp:ScriptManager runat="server" EnablePartialRendering="true">
    </asp:ScriptManager>
    <asp:Label runat="server" AssociatedControlID="PageListBox">Page:</asp:Label>
    <asp:DropDownList runat="server" ID="PageListBox" AutoPostBack="true" OnSelectedIndexChanged="PageIndexChanged" ></asp:DropDownList>
    <input type="text" name="Value1" id="Value1" value="1" />
    <input type="button" name="Muntiplier" id="Multiplier" value="x" />
    <input type="button" name="Divider" id="Divider" value="/" />
    <input type="text" name="Value2" id="Value2" value="1" />=
    <input type="text" name="Result" id="Result" value="" />
    <asp:UpdatePanel runat="server">
        <Triggers>
            <asp:AsyncPostBackTrigger ControlID="PageListBox" />
        </Triggers>
        <ContentTemplate>
            <asp:GridView ID="ProductView" runat="server" AutoGenerateColumns="false" EnableSortingAndPagingCallbacks="False" AllowSorting="True">
                <Columns>
                    <asp:BoundField HeaderText="Name" DataField="Name" />
                    <asp:BoundField HeaderText="Supplier" DataField="Supplier" />
                    <asp:BoundField HeaderText="Category" DataField="Category" />
                    <asp:BoundField HeaderText="Quantity Per Unit" DataField="QuantityPerUnit" />
                    <asp:BoundField HeaderText="Unit Price" DataField="UnitPrice" />
                    <asp:BoundField HeaderText="Units In Stock" DataField="UnitsInStock" />
                    <asp:BoundField HeaderText="Units On Order" DataField="UnitsOnOrder" />
                    <asp:BoundField HeaderText="Reorder Level" DataField="ReorderLevel" />
                </Columns>
            </asp:GridView>
        </ContentTemplate>
    </asp:UpdatePanel>
</asp:Content>

Buat code behind untuk default.aspx.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        private IEnumerable<Product> GetProducts()
        {
            var data = XDocument.Load(Server.MapPath("~/App_data/Products.xml"), LoadOptions.None);
            var q = from c in data.Descendants("Product")
                    select new Product
                    {
                        ID = int.Parse(c.Attribute("ID").Value),
                        Name = c.Attribute("Name").Value,
                        Supplier = c.Attribute("Supplier").Value,
                        Category = c.Attribute("Category").Value,
                        QuantityPerUnit = c.Attribute("QuantityPerUnit").Value,
                        UnitPrice = decimal.Parse(c.Attribute("UnitPrice").Value),
                        UnitsInStock = decimal.Parse(c.Attribute("UnitsInStock").Value),
                        UnitsOnOrder = decimal.Parse(c.Attribute("UnitsOnOrder").Value),
                        ReorderLevel = decimal.Parse(c.Attribute("ReorderLevel").Value)
                    };
            return q;
        }
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!Page.IsPostBack)
            {
                var products = GetProducts();
                PageListBox.Items.Clear();
                for (int i = 0; i < (int)(Math.Ceiling((double)products.Count() / 10)); i++)
                {
                    PageListBox.Items.Add(new ListItem((i + 1).ToString()));
                }
                ProductView.DataSource = products.Take(10);
                ProductView.DataBind();
            }
        }
        protected void PageIndexChanged(object sender, EventArgs e)
        {
            var products = GetProducts();
            int selectedPage = int.Parse(((DropDownList)sender).SelectedValue);
            ProductView.DataSource = products.Skip((selectedPage - 1) * 10).Take(10);
            ProductView.DataBind();
        }
    }
}

Analisis

Setelah semua kode disiapkan, buka halaman dengan browser. Saya gunakan Firefox dengan add-ons Firebug dan YSlow untuk menganalisis kinerja dari halaman yang dibuat.

image

Kita bisa lihat bahwa untuk membuka halaman untuk pertama kalinya membutuhkan waktu 6,53 detik. Kemudian saya akan cek untuk akses halaman untuk yang kedua kalinya dan seterusnya. Tekan menu Home untuk mengakses halaman itu kembali, hasilnya sebagai berikut.

image

Permintaan yang kedua jauh lebih cepat dari sebelumnya, yaitu hanya 4,16 detik. Mari kita analisis penyebab lambatnya permintaan yang pertama. Dilihat dari jumlahnya, akses yang pertama terdapat sebelas permintaan untuk membuka satu halaman; sedangkan akses yang kedua hanya ada enam permintaan. Hal ini disebabkan karena akses yang pertama akan mengambil semua file dari server. Sedangkan akses yang kedua beberapa file yang dibungkus oleh ScriptResource.axd dan WebResource.axd telah dicache di browser sehingga tidak diambil lagi.

Mari kita analisis lebih dalam dengan YSlow pada tab Components

image

Kita bisa lihat bahwa terdapat delapan (8) buah permintaan file javascript (JS) terlihat cukup lama. Browser akan mengunduh file JavaScript satu per satu karena adanya ketergantungan file JavaScript degan file JavaScript lainnya. Walaupun browser dapat mengunduh file tersebut secara bersamaan, namun server web hanya dapat melayani maksimal dua (2) permintaan dari user yang sama dalam waktu bersamaan. Ini membuat tanggapan (response) dari server menjadi lama. Pada permintaan yang kedua, sebagian dari file tersebut tidak diminta lagi pada akses yang kedua karena sudah ada di client (browser) sehingga lebih cepat.

Dengan data tersebut di atas, apa yang bisa kita lakukan? Kita bisa mencache semua file JavaScript dengan memasukkannya sebagai embeded resource sebagaimana JavaScript milik ASP.NET Ajax dan WebForms. Dengan cara tersebut dapat mempercepat permintaan yang kedua kalinya dan seterusnya, namun tetap lambat untuk permintaan yang pertama. Lalu apa yang bisa kita lakukan untuk mempercepat permintaan yang pertama? Dalam ASP.NET 4 terdapat fitur yang menarik yaitu penggabungan semua JavaScript menjadi satu file. Sebenarnya fitur ini telah ada dalam ASP.NET 3.5 SP1 namun di ASP.NET 4 terdapat pengembangan yang memungkinkan JavaScript milik WebForms diikutsertakan dalam paket kombinasi tersebut.

Tips 1: Gabungkan File-File JavaScript Menjadi Satu.

Dengan menggabungkan semua file JavaScript menjadi satu, tidak ada lagi permintaan bolak-balik dari client ke server. Kita praktekkan langsung dalam kode ASP.NET. Masukkan semua referensi JavaScript ke CompositeScript dalam ScriptManager.

<asp:ScriptManager runat="server" EnablePartialRendering="true">
    <CompositeScript>
        <Scripts>
            <asp:ScriptReference Assembly="System.Web" Name="WebForms.js" />
            <asp:ScriptReference Assembly="System.Web" Name="Menu.js" />
            <asp:ScriptReference Assembly="System.Web" Name="MenuStandards.js" />
            <asp:ScriptReference Name="MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Path="Scripts/jquery-1.3.2.min.js" />
            <asp:ScriptReference Path="Scripts/multiplier.js" />
            <asp:ScriptReference Path="Scripts/divider.js" />
            <asp:ScriptReference Path="Scripts/Default.js" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

Sekarang kita bisa lihat bahwa hanya ada empat permintaan ke server untuk menampilkan halaman yang sama. Dikarenakan jumlah permintaan lebih sedikit, waktu yang dibutuhkan untuk menampilkan halaman juga lebih singkat yaitu 3,96 detik. Bahkan lebih cepat dari permintaan kedua sebelumnya.

image

Sekarang kita cek untuk permintaan kedua.

image

Seluruh permintaan selesai hanya dalam waktu 2,27 detik. Suatu peningkatan kinerja yang luar biasa.

Dari CompositeScript tersebut, kita kombinasikan semua JavaScript yang ada dalam embeded resource maupun yang berupa file. Untuk yang berupa file kita dengan mudah dapat mengidentifikasinya, lalu bagaimana cara mengetahui embeded JavaScript apa saja yang kita gunakan? Pertama kita harus tahu assembly apa yang kita gunakan. Karena kita menggunakan WebForm dan ScriptManager otomatis kita menggunakan assembly System.Web dan System.Web.Extensions. Assembly System.Web menggunakan WebForms.js sebagai JavaScript utama sedangkan ScriptManager meng-embed MicrosoftAjax.js. Kedua javascript tersebut harus ada sebelum kita menggunakan control yang lain.

Untuk mengetahui JavaScript yang digunakan oleh control, kita klik pada Response tab pada Firebug untuk mendapatkan isi dari javascript. Berbekal informasi isi dari javascript, kita dapat mencari embeded resource dengan menggunakan Reflector. Buka reflector dan lihat pada assembly System.Web. Cari file javascript yang berkaitan dengan control yang kita gunakan kemudian klik ganda untuk melihat isinya. Jika isinya cocok, maka file tersebut yang kita masukkan dalam CompositeScript.

image

image

Adakah yang bisa dioptimalkan lagi? Untuk permintaan terhadap default.aspx masih membutuhkan waktu lebih dari 1 detik. Ketika kita bukan halaman default.aspx dengan lihat sumber (view source), kita dapatkan banyak kode yang jumlahnya cukup besar. Mari kita optimalkan isi dari default.aspx

image

Tips 2: Gunakan ViewState Seperlunya

Karena sifat dari web adalah stateless, ViewState digunakan untuk menjaga status dari halaman untuk digunakan di server. Setiap control yang dirender ke halaman selalu memiliki ViewState padahal tidak semuanya digunakan. Kita harus jeli mana yang kita gunakan dan mana yang tidak. Jika pada waktu postback, kita tidak memerlukan nilai dari control tersebut, kita tidak perlu menyimpan ViewState. Karena pada contoh ini kita hampir tidak memerlukan ViewState, kita bisa matikan semua ViewState kecuali DropDownList yang memang diperlukan untuk menentukan halaman berapa yang dibuka. Hasil dari optimasi adalah sebagai berikut.

image

Dari local komputer, perubahan tidak begitu berarti karena tidak ada latency terhadap jaringan. Yang jadi catatan di sini adalah ukuran file default.aspx yang didownload. Semula default.aspx berukuran 9,2 kini hanya berukuran 6,7; hemat 30% dari bandwidth. Lalu apa lagi yang bisa dioptimasi?

Tips 3: Manfaatkan Microsoft CDN untuk Situs Publik

Jika situs anda untuk konsumsi publis, CDN memberikan manfaat untuk mempercepat akses dengan memanfaatkan server CDN Microsoft yang tersebar di seluruh dunia. Pengunjung akan mendapatkan server CDN terdekat dengan tempat dia akses. Jika diakses dari Indonesia, kita akan mendapatkan server CDN yang ada di Singapore, jika diakses dari US maka akan download JavaScript dari US sehingga aplikasi kita akan lebih cepat diakses oleh pengunjung manapun.

Untuk memanfaatkan Microsoft CDN, set EnableCDN menjadi true pada ScriptManager

image

Selain mengeset property EnableCDN menjadi true, kita juga perlu mengeluarkan MicrosoftAjax.js dan MicrosoftAjaxWebForms.js dari CompositeScript. Jika tidak, kedua JavaScript tesebut akan tetap diambil dari local resource dan masuk dalam CompositeScript. Dengan setting EnableCDN kedua file tersebut akan diambil dari server Microsoft CDN. Selain kedua library tersebut, kita juga bisa memanfaatkan library lain yang sudah tersedia di CDN (Baik Microsoft CDN, Google CDN maupun server lain) seperti jQuery. Caranya dengan megeset lokasi CDN di Application_Start dalam Global.asax.

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    // map a simple name to a path
    ScriptManager.ScriptResourceMapping.AddDefinition("jQuery", new ScriptResourceDefinition
    {
        Path = "~/scripts/jquery-1.3.2.min.js",
        DebugPath = "~/scripts/jquery-1.3.2.js",
        CdnPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.min.js",
        CdnDebugPath = "http://ajax.microsoft.com/ajax/jQuery/jquery-1.3.2.js"
    });
}

Kode di atas mendefinisikan jQuery untuk lokasi di lokal dan CDN baik untuk versi debug maupun release.

Definisi tersebut yang kemudian digunakan di ScriptManager.

<asp:ScriptManager runat="server" EnablePartialRendering="true" 
    EnableViewState="False" LoadScriptsBeforeUI="False" EnableCdn="True">
    <Scripts>
        <asp:ScriptReference Name="jQuery" />
    </Scripts>
    <CompositeScript>
        <Scripts>
<%--
            <asp:ScriptReference Assembly="System.Web" Name="WebForms.js" />
            <asp:ScriptReference Assembly="System.Web" Name="Menu.js" />
            <asp:ScriptReference Assembly="System.Web" Name="MenuStandards.js" />
            <asp:ScriptReference Name="MicrosoftAjax.js" />
            <asp:ScriptReference Name="MicrosoftAjaxWebForms.js" />
            <asp:ScriptReference Path="Scripts/jquery-1.3.2.min.js" />
--%>                
            <asp:ScriptReference Path="Scripts/multiplier.js" />
            <asp:ScriptReference Path="Scripts/divider.js" />
            <asp:ScriptReference Path="Scripts/Default.js" />
        </Scripts>
    </CompositeScript>
</asp:ScriptManager>

Dari kode di atas, kita remark semua library yang akan kita ambil dari CDN. Semua library yang ada dalam assembly Microsoft ASP.NET sudah tersedia di Microsoft CDN. Library lainnya harus dimasukkan dalam Scripts di luar CompositeScript. Hasil akses dari kode yang sudah diubah sebagai berikut.

image

Terlihat bahwa waktu yang dibutuhkan lebih lama dari kode kita sebelumnya yang menggabungkan semua script menjadi satu. Hal ini wajar karena demo ini menggunakan komputer lokal sehingga akses jaringan jauh lebih cepat dibandingkan akses ke Internet. Kecepatan akan terasa sewaktu aplikasi sudah dihost di Internet.

Tips 4: Tempatkan Referensi Script di Bawah User Interface

image

Pada property ScriptManager, set nilai LoadScriptsBeforeUI menjadi False. Hal ini akan membuat referensi Script dirender sebelum tag penutup </body>. Hal ini membuat browser akan mendownload semua UI terlebih dahulu sebelum JavaScript sehingga halaman tampak lebih cepat tampil.

Tips 5: Gunakan Browser Cache

Penggunaan cache penting untuk mengurangi beban jaringan. Dengan menggunakan cache, browser tidaka akan mengambil halaman dari server lagi melainkan dari cache selama cache belum kadaluarsa. Cache hanya berlaku untuk HTTP GET sehingga ketika kita postback tetap akan mendapatkan data yang valid. Untuk memanfaatkan cache, cukup tambahkan directive OutputCache pada tiap page yang akan di-cache seperti contoh berikut.

<%@ Page Title="Home Page" Language="C#" MasterPageFile="~/Site.master" AutoEventWireup="true"
    CodeBehind="Default.aspx.cs" Inherits="WebApplication1._Default" %>
<%@ OutputCache Duration="86400" Location="Client" VaryByParam="None" %>    

Dalam contoh di atas, cache diset masa kadaluarsa selama satu hari. Halaman akan dicache selama sehari sehingga akan mengurangi beban server. Sebenarnya fungsi cache ini sudah ada sejak ASP.NET 2.0 dan masih valid sampai ASP.NET 4.0.

Demikian beberapa tips yang bisa meningkatkan kinerja aplikasi web kita. Semoga bermanfaat.


Categories: ASP.NET AJAX | ASP.NET | Tips
Permalink | Comments (2) | Post RSSRSS comment feed

Comments

Cahya Indonesia | Reply

Friday, January 21, 2011 4:04 PM

Cahya

Artikel yang sangat menarik...
Mau tanya nih, kalau kita banyak menggunakan Notes/Remark di Web Aplikasi kita untuk catatan kita apakah akan dimasukkan juga pada saat web di Publish atau dihapus secara otomatis? Jika tidak dihapus berarti akan menambah berat file yang di publish.

Ahmad Masykur United States | Reply

Friday, January 21, 2011 4:52 PM

Ahmad Masykur

Note/Remark tidak akan ikut dipublish selama Anda menggunakan web application yang dicompile menjadi file .dll. Yang dipublish hanya binary code saja.

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading