BenchmarkDotNet | Kurulumu ve Temelleri 1. Kısım

Yazdığınız bir kod parçası ne kadar verimli? Az önce yaptığınız değişiklik uygulamanızı iyileştirecek mi? Bunu nereden biliyorsunuz? Bu değişiklik ne kadar önemliydi? Bunlar kıyaslama yani benchmarking yapmadan cevaplanamayacak sorular. Bu video serisinde, kodun ne kadar verimli olduğunu belirlemek için Benchmarkdotnet‘in kodu değerlendirmek için nasıl kullanılacağına ve ardından kodun değiştirilmiş bir versiyonuna kıyasla ne kadar verimli olduğuna bakacağız.

BenchmarkDotNet, yöntemleri karşılaştırma ölçütlerine dönüştürmenize, performanslarını izlemenize ve tekrarlanabilir ölçüm deneylerini paylaşmanıza yardımcı olur. Birim testleri yazmaktan daha zor değil! BenchmarkDotNet sizi popüler kıyaslama hatalarından korur ve kıyaslama tasarımınızda veya elde ettiğiniz ölçümlerde bir sorun olduğunda sizi uyarır. Sonuçlar, denemenizle ilgili tüm önemli gerçekleri vurgulayan kullanıcı dostu bir biçimde sunulur. Proje, .NET Runtime dahil olmak üzere 6800’den fazla proje tarafından benimsenmiş ve .NET Foundation tarafından desteklenmektedir.

Tipik bir durumda ne yapmanız gerektiğini düşünelim. İlk olarak, bir pilot deney yapmalı ve en iyi yöntem çağırma sayısını belirlemelisiniz. Ardından, birkaç ısınma yinelemesi gerçekleştirmeli ve karşılaştırma ölçütünüzün sabit bir duruma ulaştığından emin olmalısınız.

Elle yazılmış birçok kıyaslama, yanlış iş kararlarına yol açan yanlış sayılar üretir. BenchmarkDotNet, sizi kıyaslama tuzaklarının çoğundan korur ve yüksek ölçüm hassasiyeti elde etmenizi sağlıyor.

Mükemmel yöntem çağırma sayısı, ısınma ve gerçek yineleme sayısı hakkında endişelenmemelisiniz: BenchmarkDotNet en iyi kıyaslama parametrelerini seçmeye çalışır ve ölçüm öngörüsü ile tüm kıyaslama çalıştırmalarının toplam süresi arasında iyi bir denge elde etmeye çalışır.

Videoda neler öğrendik?

➡️ Benchmark attribute kullanımı

➡️ MemoryDiagnoser attribute kullanımı

➡️ BenchmarkRunner.Run kullanımı

✅ Gen 0, Gen 1 ve Gen 2 nedir ve nasıl çalışır?

Küçük .NET nesneleri, küçük heap’lere tahsis edilir. Bunlardan üç tane vardır: Gen 0, Gen 1 ve Gen 2. Gen 0’a yeni nesneler yerleştirilir.

Gen 0 dolduğunda, .NET Garbage Collector çalışır, artık ihtiyaç duyulmayan nesneleri elden çıkarır ve diğer her şeyi Gen 1’e taşır. Gen 1 dolarsa, GC yeniden çalışır, aynı zamanda Gen 1’deki nesneleri Gen 2’ye taşır.

Gen 2 dolduğunda tam bir GC çalışması gerçekleşir. Bu, gereksiz Gen 2 nesnelerini temizler, Gen 1 nesnelerini Gen 2’ye taşır, ardından Gen 0 nesnelerini Gen 1’e taşır ve son olarak referans verilmeyen her şeyi temizler.

Kaynaklar:

✔️ https://benchmarkdotnet.org/

✔️ https://www.red-gate.com/products/dotnet-development/ants-memory-profiler/learning-memory-management/memory-management-fundamentals

Hepsine hükmeden tek bir döngü – While

C# compiler’ın tüm döngüleri lowering mekanizması ile while döngüsüne dönüştürdüğünü biliyor muydunuz? Ben de bilmiyordum.

Lowering mekanizması C# compiler’ın sıklıkla kullandığı bir yapı. Bunu özellikle “Compiler magic” veya Syntactic sugar dediğimiz durumlarda kullanılıyor. Ek olarak daha kompleks mekanizmaları, MSIL ve makine koduna daha rahat çevrilebilmesi için basit mekanizmalara çeviriyor.

Eric Lippert şöyle diyor;

“Bununla birlikte, derleyicinin aynı dilde yüksek seviyeli dil özelliklerinden düşük seviyeli dil özelliklerine “düşürülmesini” sağlamaktır.”

C# compiler’ı aşağıdaki tüm döngüleri arka tarafta while döngüsünün muadili olacak şekilde çeviriyor;

✅ for döngüsü

✅ foreach döngüsü

✅ while döngüsü

✅ do while döngüsü

Belki de bu döngüler sadece biz developer’lar için vardır.

Örneğin;

for(var i = 0; i less 5; i++)
{
}

şeklinde bir kod yazdığımızda C# compiler bu kodu;

int num = 0;
while (num less 5)
{
    num++;
}

olarak lower ediyor.

Ek olarak lowering mekanizması sadece çevrimlerden ziyade, normalde developer’ın yazması gereken kodları kendisi yazarak developer’ın çok daha az kod yazarak işini halletmesine yardımcı oluyor.

Lowering çok önemli bir konu bu arada. Derinlemesine bilmeseniz ile sharplab.io gibi mekanizmaları düzenli olarak kullanmanız size çok faydalı olacaktır.

Kaynaklar:

1️⃣ https://mattwarren.org/2017/05/25/Lowering-in-the-C-Compiler/

2️⃣https://github.com/dotnet/roslyn/tree/main/src/Compilers/CSharp/Portable/Lowering

C# 10 Yenilikleri – Tek overload’u olan delegate türü

C# 10 ile birlikte, derleyici, yalnızca tek bir overload’a sahip olan delegate’lerin türünü çıkarabiliyor.

Örneğin;

// int
var i = Console.Read();

// Func int
Func int f = Console.Read;

Bu birden fazla overload’u olan Console.WriteLine’da çalışmaz mesela;

var str = Console.WriteLine; // Hata

Yani artık C# 10 ile şu şekilde delegate’ler yazabiliyoruz;

var str = (int i) => i.ToString();
str(42);

Egosuz programlama

1971 yılında Gerald Weinberg‘in çıkardığı The Psychology of Computer Programming kitabında bahsettiği bir yazılım geliştirme metodolojisi bu.

Yazılım mühendisliği diğer mühendisliklere göre yeni bir alan aslında. Yeniliklere de oldukça açık. Genelde takım halinde icra edilen bir mühendislik olan yazılımı takım kimyasını koruyup, egoları bir kenara bırakıp nasıl yapılacağı ile ilgili yol gösterir bu kurallar.

1. Understand and accept that you will make mistakes.

Orhan Gencebay’ın dediği gibi, “hatasız kul olmaz“. Yazılımdaki hatalar çok az sektörde ölümcül durumlara sebep olur. Önemli olan bu hatalardan ders çıkarmak, öğrenmek, bu hatalara gülebilmektir. Bu hataları canlı ortamda tecrübe etmeden bulmak en önemli amaçtır.

2. You are not your code.

Geliştiricilerin kodları incelemesinde amaç hataları bulmaktır, ve hatalar daima olacaktır. Bu hataları kişisel olarak algılamayıp birinci maddeyi hatırlamalısın. Herkes hata yapabilir fakat önemli olan bu hataları çözmektir.

3. No matter how much “karate” you know, someone else will always know more.

El elden üstündür. Yazılım dünyasında benim en sevdiğim konulardan biri bu. Tecrübeye bakmaksızın her hangi bir kişiden yeni bir bakış açısı, yeni bir yöntem veya daha kolay bir çözüm öğrenebilirsiniz. Öğrenmek için hep çaba sarf edin, sormaktan çekinmeyin.

4. Don’t rewrite code without consultation.

Önemli bir şeyi değiştirmeden önce danışmak faydalı olur. Code review zaten yanlış bir değiştirmenin önüne geçecektir ama danışmaktan zarar gelmez. Hatalı kodu düzeltmek ile kodu yeniden yazma arasındaki farkı iyi anlamamız gerekir.

5. Treat people who know less than you with respect, deference and patience.

Yazılım ile alakası olamayan kişiler veya daha az tecrübeli, daha az bilgili yazılımcılar ile çalışırken saygılı, sabırlı ve geri bildirime açık ol. Yazılımcılar her zaman itiraz eden, üstten bakan kişiler olmamalıdır.

6. The only constant in the world is change.

Efesli Herakleitos‘un dediği gibi, “Değişmeyen tek şey değişimin kendisidir”. Yazılım için çok önemli bir söz. Durmadan değişen, gelişen teknolojiler ile baş başayız. Yenilikleri olumlu şekilde karşılamalı ve yeni meydan okumalar olarak görmelisin.

7. The only true authority stems from knowledge, not from position.

Bilgi yetkinliği, yetkinlik ise saygıyı doğurur. Saygı görmek istiyorsanız daha bilgili olun. Kendinizi her zaman geliştirin ve yetkin bir insan olun.

8. Fight for what you believe, but gracefully accept defeat.

Fikirlerini doğru şekilde savunmalısın ama fikrinden daha iyi fikirler daha doğru çözümler olduğunda vazgeçmeyi bilmelisin. Takım kararlarına saygı göster. Bazı durumlarda sana daha az mantıklı gelen tercih uygulanabilir. Bu karar sonucunda çıkan sonuçlara da saygılı olmalısın. Sonuç olarak senin fikrin doğru çıkmış olsa bile “ben demiştim ama” gibi kalıpları fazla kullanmaktan kaçınmalı, sadece gerekli yerde kullanmalısın. Olaylar yaşanır geçer, önemli olan daha önce de bahsettiğimiz gibi bunlardan en faydalı sonuçları çıkarmaktır.

9. Don’t be “the guy in the room.”

Karanlık bir köşede sessizce çalışan yabani kişi olmayın. Çalışma ortamınızdaki herkesle ilişki kurun. Sadece yazılım takımı değil herkesle. Yazılımcıların işi hep bilgisayarlarla olduğu için iş ortamında doğal olarak daha az sosyal etkileşimde bulunurlar. Bunu değiştirin.

10. Critique code instead of people – be kind to the coder, not to the code.

Kişileri değil kodu eleştir, kodlara değil kodu yazan kişiye nazik ol. kod içerisinde bir hata gördüğünde veya değişiklik olmasını istediğinde “bunu niye böyle yaptın” diye bir yaklaşım yerine “bunu böyle yapsak daha iyi olmaz mı?” yaklaşımı her zaman daha avantajlıdır. İstediğin değişikliğin sebebinde açıklayıcı ol, teknik olarak neden gerekli olduğu doğru bir şekilde anlat. Aynı hataları senin de yapacağının farkında ol ve ona göre davran.

Kaynak:

https://en.wikipedia.org/wiki/Egoless_programming

https://blog.codinghorror.com/the-ten-commandments-of-egoless-programming/

https://wiki.c2.com/?EgolessProgramming

Leetcode Çözümleri | Three Consecutive Odds

Leetcode içerisinde bulunan “Three Consecutive Odds” sorusunun açıklaması ve çözümü. Bu soruda size verilen bir tam sayı dizisinde, 3 tane yan yana tek sayı olup olmadığını bulmanız isteniyor.

➡️ Leetcode 1550. Three Consecutive Odds: https://leetcode.com/problems/three-consecutive-odds/

➡️ Problem açıklaması:

Given an integer array arr, return true if there are three consecutive odd numbers in the array. Otherwise, return false.

Example 1:

Input: arr = [2,6,4,1]

Output: false

Explanation: There are no three consecutive odds.

Example 2:

Input: arr = [1,2,34,3,4,5,7,23,12]

Output: true

Explanation: [5,7,23] are three consecutive odds.

Constraints:

1 <= arr.length <= 1000

1 <= arr[i] <= 1000

Visual Studio 2022 ile gizli karakterleri görün!

Visual Studio 2022 17.0.3 release’i ile gelen özelliklerden biri de “bidirectional” yani çift yönlü karakterleri artık editörde görebiliyoruz.

Kodun yanlış sunulmasına izin veren potansiyel olarak kötü amaçlı bir istismarı önlemek için, Visual Studio artık iki yönlü metin kontrol karakterlerinin editör içerisindeki karakterlerin sırasını değiştirmesine izin vermeyecek.

Bu özelliği Tools –> Options –> Text Editor –> General page altındaki “Show bidirectional text control characters” kısmında açıp kapatabilirsiniz. Default’ta açık geliyor.

Bidirectional karakter olarak adlandırılan karakterlerin tüm listesi şu şekilde; U+061c, U+200e-U+200f, U+202a-U+202e, U+2066-U+2069

Kaynak:

https://docs.microsoft.com/en-us/visualstudio/releases/2022/release-notes#bidirectional-text-control-character-rendering

https://en.wikipedia.org/wiki/Left-to-right_mark

https://www.fileformat.info/info/unicode/char/200e/index.htm

C# 10 Yenilikleri – CallerArgumentExpression attribute kullanımı

C# 10 ile gelen yeniliklerden biri de CallerArgumentExpression attribute kullanımı.

CallerArgumentExpression attribute kullanımı size parametre olarak verdiğiniz expression’ın string halini size geri döndürüyor. Diğer compiler servis attribute’ler gibi bu da optional.

using System.Runtime.CompilerServices;

void Write(object obj, [CallerArgumentExpression("obj")] string? msg = null)
{
    Console.WriteLine($"Expression şu: {msg}");
}

Write(new object());
Write("Merhaba");
Write(42 + 42 + 42);
Write(() lambda { });

int i = 42;
Write(i);

// Expression şu: new object()
// Expression şu: "Merhaba"
// Expression şu: 42 + 42 + 42
// Expression şu: () lambda  { }
// Expression şu: i

Kaynak: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-10.0/caller-argument-expression

LeetCode Çözümleri | Add Digits

Leetcode içerisinde bulunan “Add Digits” sorusunun açıklaması ve çözümü. Bu soruda sizi verilen bir tam sayının rakamları toplamı tek hane olana kadar toplayıp geriye döndürmeniz isteniyor.

➡️ LeetCode 258. Add Digits: https://leetcode.com/problems/add-digits/

➡️ Problem açıklaması:

Given an integer num, repeatedly add all its digits until the result has only one digit, and return it.

Example 1:

Input: num = 38

Output: 2

Explanation: The process is

38 —- 3 + 8 —- 11

11 —- 1 + 1 —- 2

Since 2 has only one digit, return it.

Example 2:

Input: num = 0

Output: 0

Constraints:

0 <= num <= 2^31 – 1

⚠️Follow up: Could you do it without any loop/recursion in O(1) runtime?

.NET 6 Yenilikleri – Nuget paket validasyonu

.NET 6 ile gelen yeniliklerden biri de EnablePackageValidation kullanımı.

Bu tag nuget paketlerinizin validasyonunun sağlıyor. Peki ne bu validasyonlar?

  • Sürümler arasında birbirini bozan değişiklik olup olmadığını doğrular.
  • Paketin, farklı runtime implementasyonlarına özgü uygulamalar için aynı public API yapısına sahip olup olmadığını doğrular.
  • Geliştiricilerin uygulanabilirlik açıklarını yakalamasına yardımcı olur.

Projenizin .csproj dosyası içerisinde PropertyGroup altında kullanabilirsiniz bu tag’ı.

<PropertyGroup>
  <EnablePackageValidation>true</EnablePackageValidation>
</PropertyGroup>

Kaynak:

https://docs.microsoft.com/en-us/dotnet/fundamentals/package-validation/overview