17 Ocak 2012 Salı

Outlook Enterprise Vault Sekmesi

Enterprise Vault sekmesi Outlook'ta artık gözükmüyorsa

1.            Outlook Kapatılır.

2.            C:\Program Files (x86)\Enterprise Vault\EVClient\
                veya
                C:\Program Files\Enterprise Vault\EVClient\
                Klasöründeki ResetEVClient.exe çalıştırılır. Komut Penceresi kendi kendine kapanana kadar beklenir.

3.            Outlook tekrar açılır.

16 Ocak 2012 Pazartesi

XslCompiledTransform caching ile performansın arttırılması

Merhaba,
Daha önceki yazılarda xml processing’in maliyetinden bahsetmiştik. En çok zaman kaybedilen yerlerden biri de Xsl çevrimleridir.
XslCompiledTransform sınıfının Load metodunu her çevrimde kullanmayıp önbellekten kullanarak ciddi kazançlar elde edilebilir.
Load metodu arka tarafta yeni bir assembly oluşturup derleme işlemi gerçekleştirdiği için zaman kaybına neden olmaktadır.

Örneğin 361 sn süren işlemin ekran görüntüsünü aşağıda görebilirsiniz:


361 sn’nin 248 sn’si xsl çevriminde geçmiş:


Bu sürenin de %79’u yani 197 sn’si CPU’da geçmiş.
Bu süreyi oluşturan xsl transformation işlemi aslında kısa süren bir işlem fakat yüzlerce kez tekrarlandığı için bu kadar çok zaman alıyor.

Aşağıdaki ekran görüntüsünde tek bir XSL transformation işlemi 217 ms zaman almış:

Bu işlem 1200 kez tekrarlanmış:


Yapılan iyileştirme sadece bir kaç satır kod değişikliği ile load metodunun 1200 kere değil sadece bir kez çalıştırılması:

        public static string TransformToXMLString(string xslPath, string inputXML)
        {
            XslCompiledTransform xslTransform = null;
            if (CacheMain.Cache[xslPath] != null)
            {
                xslTransform = (XslCompiledTransform)CacheMain.Cache[xslPath];
            }
            else
            {
                xslTransform = new XslCompiledTransform();
                xslTransform.Load(xslPath);
                TimeSpan timeOut = new TimeSpan(0, 0, 30, 0, 0);
                CacheMain.Cache.Add(xslPath,
xslTransform, null, Cache.NoAbsoluteExpiration, timeOut, CacheItemPriority.NotRemovable, null);
            }
           
            return TransformToXMLString(xslTransform, inputXML);
        }


http://blogs.msdn.com/b/spike/archive/2009/07/10/improving-xslcompiledtransform-performance.aspx adresinde load metodunun her defasında çalıştırılması durumunda aynı içeriğe sahip 3 xml dosyasının çevrim işleminin süreleri şu şekilde belirtilmiş:

..\..\Person_1.xml done, elapsed time (ms): 224
..\..\Person_2.xml done, elapsed time (ms): 117
..\..\Person_3.xml done, elapsed time (ms): 119

Load işleminin sadece bir kez yapılması durumunda aynı xml dosyalarının çevrim sürelerini aşağıda görebilirsiniz:

..\..\Person_1.xml done, elapsed time (ms): 211
..\..\Person_2.xml done, elapsed time (ms): 1
..\..\Person_3.xml done, elapsed time (ms): 1

119 ms’den 1 ms’ye düşmüş.

Tarık


5 Ocak 2012 Perşembe

Kaybolmayan cache istiyoruz

Merhaba,

Uygulamanın kullandığı ram seviyesi application pool’un kullanabileceği değerin %90’ına ulaşınca sistem kendisini rahatlatmak için önbelleği temizlemeye başlıyor.
Bunu engellemek istiyorsanız web.config dosyasına aşağıdaki satırları eklemeniz yeterli.
İlk değer haricindekiler default değerleri göstermektedir.
<![if !supportLists]>1.  <![endif]><caching>  
<![if !supportLists]>2.  <![endif]>  <cache disableMemoryCollection = "true"  
<![if !supportLists]>3.  <![endif]>    disableExpiration = "false"  
<![if !supportLists]>4.  <![endif]>    privateBytesLimit = "0"  
<![if !supportLists]>5.  <![endif]>    percentagePhysicalMemoryUsedLimit = "90"  
<![if !supportLists]>6.  <![endif]>    privateBytesPollTime = "00:02:00"/>  
<![if !supportLists]>7.  <![endif]></caching> 
Tarık


GarbageCollector tercihi hayati önem taşıyor

Merhaba,

Çok kullanıcılı web uygulamalarında garbage collector seçimi hayati önem taşımaktadır.
Özellike uygulama çok fazla ram kullanıyorsa.
Default değerlerle workstation concurrent modda çalışan garbage collector aynı anda çok fazla kullanıcıdan gelen isteklerin oluşturduğu bellek çöplüğünü temizlemeye yetişemiyor.
Ayrıca uygulamanın ram kullanımı %90’ı bulduğunda (default değer %90) sistem kendisini rahatlatmak için önbelleği temizliyor.
Gelen ilk istekle birlikte önbellekte bulunamayan resource bilgileri veritabanından tekrar çekiliyor.
Sistem kendisini rahatlatmaya çalışırken ekstra iş çıkıyor.
Kısır döngüye giriyor, GC siliyor daha doğrusu silmeye çalışıyor, sayfalar tekrar oluşturuyor.
Kısa bir süre sonra beklenen son geliyor ve uygulama crash oluyor.
Bu arada mağdur olan kullanıcılardan şikayetler gelmeye başlıyor.
Sonrası malum.

Tarık


Resource kullanımı ve viewstate compressor ilişkisi

Merhaba,

Postback’lerde gidip gelen viewstate bilgisi fazla yer kaplamasın diye sıkıştırırız.
Böylece bant genişliği düşük olan bölgelerdeki kullanıcılar da uygulamayı daha rahat kullanabilir.
Bu noktada dikkat edilmesi gereken çok önemli bir husus var.
Viewstate bilgisini kaydederken kullanılan StringWriter sınıfında culture bilgisi olarak invariant culture kullanılırsa viewstate bilgisinin yüklenmesi sırasında gerçekleştirilen decompress’teki deserialize işleminde veri tipleri convert edilir.
Bu da ciddi zaman kayıplarına neden oluyor.
Özellikle ram kullanımının çok arttığı zamanlarda sistem kendini toparlamak için zorlanırken en çok zaman alan işlemler top 10 listesinde zirveye çıkabilir.
Bant genişliğinden kazanalım derken zorladığımız cpu’umuzu daha da zorlayarak sistemi zora sokmamak için aman dikkat diyoruz.

Tarık

4 Ocak 2012 Çarşamba

.NET Runtime version 2.0.50727.4927 - Fatal Execution Engine Error

Merhaba,

Son zamanlarda .net dll’lerinden (third party de olabilir) birini değiştirdikten sonra
web server’de ram ve cpu kullanımı normal seviyelerdeyken iis crash sorunu yaşamaya başlamış olabilirsiniz.

Loglarda şu ikisini görürseniz hotfix ile sorunu giderebilirsiniz:
.NET Runtime version 2.0.50727.4927 - Fatal Execution Engine Error (xxxxxxxx) (80131506)
Exception code: 0xc0000005

IIS üzerinde belirli bir kullanıcı kimliği ile çalışan kod, erişim izni olmayan bir yere erişmeye çalışırsa bu hata gelmekte ve uygulama crash olmaktadır.

Çözüm olarak şu iki linki incelemenizi ve hotfix’i uygulamanızı öneririm:



Tarık

Performance counters kullanımını kapatmak

Merhaba,

Uygulama performansını arttırmak için server’de kullanılmayan tüm servislerin kapatılması önerilir.
Performance counters, canlı bir sistemin gidişatını takip edebilmek için çok önemlidir fakat onun da sisteme getirdiği bir yük var.
Aşağıda cache’den veri okuma sırasında performance counters kullanımının yarattığı 147 ms’lik gecikmenin resmini görebilirsiniz:


DynaTrace gibi bir yazılımla sistemin durumunu anlık olarak sürekli izliyorsanız performance counters’lara gerek kalmadığı için kapatılması az da olsa sistem performansını arttıracaktır.

Tarık

Xml Processing'in maliyeti

Merhaba,

Daha önceki yazılarımda xml serializer kullanımından kaynaklanan yavaşlığın ve sistem kaynaklarına olan etkisinden bahsetmiştim.
Bu durumun resmini aşağıda görebilirsiniz:


Sürenin %79’u CPU’da geçiyor. Ve bu sürenin çoğu da schema oluşturmada geçiyor.
Önceki yazıda 5.5 sn süren xml serileştirme işleminin gerçekte sadece 162 ms’sinin data’yı serileştirmede geçtiğini görmüştük.
5.5 sn’nin %79’u yaklaşık 4.34 sn yapıyor.
Kısacası 162 ms’lik bir serileştirme işlemi için CPU’yu 4.34 sn meşgul ediyoruz.

Tarık


XmlSerializer

XmlSerializer kullanımı konusunu biraz daha açalım.
Bir datatable’i XmlSerializer ile serileştirirsek oluşacak çıktı şu şekilde olmaktadır:

<?xml version="1.0" encoding="utf-16"?>
<DataTable>
  <xs:schema id="NewDataSet" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="NewDataSet" msdata:IsDataSet="true" msdata:MainDataTable="dtt" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="dtt">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Id" TYPE="xs:int" minOccurs="0" />
                <xs:element name="Ad" TYPE="xs:string" minOccurs="0" />
                <xs:element name="Soyad" TYPE="xs:string" minOccurs="0" />
                <xs:element name="Adres" TYPE="xs:string" minOccurs="0" />
                <xs:element name="Yas" TYPE="xs:int" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <DocumentElement>
      <dtt diffgr:id="dtt1" msdata:rowOrder="0">
        <Id>0</Id>
        <Ad>Ad0</Ad>
        <Soyad>Soyad0</Soyad>
        <Adres>Adres0</Adres>
        <Yas>0</Yas>
      </dtt>
      <dtt diffgr:id="dtt2" msdata:rowOrder="1">
        <Id>1</Id>
        <Ad>Ad1</Ad>
        <Soyad>Soyad1</Soyad>
        <Adres>Adres1</Adres>
        <Yas>1</Yas>
      </dtt>
      <dtt diffgr:id="dtt3" msdata:rowOrder="2">
        <Id>2</Id>
        <Ad>Ad2</Ad>
        <Soyad>Soyad2</Soyad>
        <Adres>Adres2</Adres>
        <Yas>2</Yas>
      </dtt>
    </DocumentElement>
  </diffgr:diffgram>
</DataTable>

Dikkat ederseniz metadata, gerçek data kadar yer kaplıyor.

DataTable’de bazı dataların değiştirilip AcceptChanges denmemesi durumunda ise serileştirmeye DiffGram da ekleniyor ve çıktı şu şekilde oluyor:

<?xml version="1.0" encoding="utf-16"?><DataSet>
  <xs:schema id="ds" xmlns="" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xs:element name="ds" msdata:IsDataSet="true" msdata:UseCurrentLocale="true">
      <xs:complexType>
        <xs:choice minOccurs="0" maxOccurs="unbounded">
          <xs:element name="dtt">
            <xs:complexType>
              <xs:sequence>
                <xs:element name="Id" type="xs:int" minOccurs="0" />
                <xs:element name="Ad" type="xs:string" minOccurs="0" />
                <xs:element name="Soyad" type="xs:string" minOccurs="0" />
                <xs:element name="Adres" type="xs:string" minOccurs="0" />
                <xs:element name="Yas" type="xs:int" minOccurs="0" />
              </xs:sequence>
            </xs:complexType>
          </xs:element>
        </xs:choice>
      </xs:complexType>
    </xs:element>
  </xs:schema>
  <diffgr:diffgram xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" xmlns:diffgr="urn:schemas-microsoft-com:xml-diffgram-v1">
    <ds>
      <dtt diffgr:id="dtt1" msdata:rowOrder="0" diffgr:hasChanges="modified">
        <Id>45</Id>
        <Ad>Ad0</Ad>
        <Soyad>Soyad0</Soyad>
        <Adres>Adres0</Adres>
        <Yas>0</Yas>
      </dtt>
      <dtt diffgr:id="dtt2" msdata:rowOrder="1" diffgr:hasChanges="modified">
        <Id>1</Id>
        <Ad>Addddddd</Ad>
        <Soyad>Soyad1</Soyad>
        <Adres>Adres1</Adres>
        <Yas>1</Yas>
      </dtt>
      <dtt diffgr:id="dtt3" msdata:rowOrder="2" diffgr:hasChanges="modified">
        <Id>2</Id>
        <Ad>Ad2</Ad>
        <Soyad>Soyad2</Soyad>
        <Adres>Adres2</Adres>
        <Yas>100</Yas>
      </dtt>
    </ds>
    <diffgr:before>
      <dtt diffgr:id="dtt1" msdata:rowOrder="0">
        <Id>0</Id>
        <Ad>Ad0</Ad>
        <Soyad>Soyad0</Soyad>
        <Adres>Adres0</Adres>
        <Yas>0</Yas>
      </dtt>
      <dtt diffgr:id="dtt2" msdata:rowOrder="1">
        <Id>1</Id>
        <Ad>Ad1</Ad>
        <Soyad>Soyad1</Soyad>
        <Adres>Adres1</Adres>
        <Yas>1</Yas>
      </dtt>
      <dtt diffgr:id="dtt3" msdata:rowOrder="2">
        <Id>2</Id>
        <Ad>Ad2</Ad>
        <Soyad>Soyad2</Soyad>
        <Adres>Adres2</Adres>
        <Yas>2</Yas>
      </dtt>
    </diffgr:before>
  </diffgr:diffgram>
</DataSet>

Aynı datatable’i WriteXml metodu ile serileştirirsek çıktımız oldukça sade hale gelmekte:

<DocumentElement>
  <dtt>
    <Id>0</Id>
    <Ad>Ad0</Ad>
    <Soyad>Soyad0</Soyad>
    <Adres>Adres0</Adres>
    <Yas>0</Yas>
  </dtt>
  <dtt>
    <Id>1</Id>
    <Ad>Ad1</Ad>
    <Soyad>Soyad1</Soyad>
    <Adres>Adres1</Adres>
    <Yas>1</Yas>
  </dtt>
  <dtt>
    <Id>2</Id>
    <Ad>Ad2</Ad>
    <Soyad>Soyad2</Soyad>
    <Adres>Adres2</Adres>
    <Yas>2</Yas>
  </dtt>
</DocumentElement>

Tarık