C# String.IndexOf, String.Contains, Regex.IsMatch(), Regex.IsMatch(Compiled) performans karşılaştırma

Ne tür bir uygulama geliştiriyor olursak olalım (Web, Mobile, Cloud, Game, Desktop, etc) string tipi üzerinde karşılaştırma mutlaka yaparız.

Bu makalede, string değişkenler üzerinde yapabileceğimiz karşılaştırma methodlarını performans odaklı olarak inceleyeceğiz.

Ben aşağıdaki 4 yöntemi karşılaştırmaya karar verdim, eğer sizin aklınıza başka karşılaştırma yöntemleri gelirse, aşağıdaki Yorumlar alanına veya Issues altına bir yorum bırakabilirsiniz ;)

  • String.IndexOf()
  • String.Contains()
  • Regex.IsMatch()
  • Regex.IsMatch(Compiled)

Öncelikle test ortamımızı oluşturalım, bunun için TestScenarios ve Program isimli birer class oluşturuyoruz.

Program.cs dosyasında yeralan Program class‘ında sadece TestScenarios class‘ından yeni bir instance oluşturup, InvokeTest() methodunu çağırıyoruz;

TestScenarios class‘ı içerisinde, üzerinde testleri geçekleştireceğimiz, string bir değişkene ihtiyacımız var;

Ben, kendi bilgisayarımda, karşılaştırma operasyonunu 10 Milyon (10_000_000) defa yapıp, toplam harcanan süreyi ölçtüm;

Karşılaştırma operasyonunu gerçekleştirip, sonucu ekrana yazdırabilmek için TestAndPrint() isimli bir method geliştirdim;

Bu method içerisinde, öncelikle, Stopwatch tipinde bir değişken oluşturuyorum.

GarbageCollector tarafından testin etkilenmemesi için, GC sınıfının Collect() methodunu Generation 2 için çalıştırıyorum.

Sonra da, WaitForFullGCComplete() methodu ile, eğer yürüyen bir Collect() operasyonu varsa, tamamlanmasını bekliyorum.

Stopwatch değişkenini Restart() edip, sıfırlıyor, Action tipinde aldığım Test() parametresini çağırıyor, geçen toplam süreyi milisaniye cinsinden ekrana yazıyorum.

Şimdi, tek tek, String.IndexOf(), String.Contains(), Regex.IsMatch() ve Regex.IsMatch(Compiled) test senaryolarını yazalım;

String.IndexOf() testi için;

String.Contains() testi için;

Regex.IsMatch() testi için;

Regex.IsMatch(Compiled) testi için;

Şimdi, TestScenarios class içerisine InvokeTest() methodu yazıyoruz;

Her testi 2 kere çalıştırıyoruz, biri karşılaştırma sonucu başarılı olacak şekilde, biri başarılı olmayacak şekilde.

Gelelim, en önemli kısma, karşılaştırma sonuçları :)

Sonuçlara baktığım zaman aşağıdaki noktalar dikkatimi çekti;

  • Tüm testlerde arama sonucu bulunmadığı zaman, arama sonucu bulunduğu zamana göre daha iyi performans göstermiş
  • Regex karşılaştırmaları en yavaş olanlar
  • String.Contains() karşılaştırması, String.IndexOf() karşılaştırmasından daha iyi performans göstermiş

Microsoft‘un Github‘da yayınladığı ReferenceSource repository’sinde String classının Contains() methodu aşağıdaki şekilde yazılmış;

Aslında Contains() methodu, içeride IndexOf() methodunu çağırıyor.

Peki, neden bizim testlerimizde Contains() ve IndexOf() farklı sonuçlar üretti?

Çünkü, Contains() methodu içinden IndexOf() methodu, StringComparison.Ordinal parametresi ile çağırılıyor.

Eğer kendi uygulamalarımızda IndexOf() methodunu çağıracaksak, StringComparison.Ordinal parametresini kullanmamız performans artışı sağlayacaktır.

Daha kolayı, Contains() methodunu kullanmak :)

İlgili diğer makaleler

blog comments powered by Disqus

Engin Polat hakkında

Senior Software Engineer, @Microsoft

Ada ve Ege'nin babası ;)

Kategoriler

İstatistik

Makale Adedi: 484

Creative Commons Lisansı