Forum: D Programlama Dili RSS
Büyük üyeleri başa taşıyarak yapının büyüklüğünü azaltmak (.offsetof ve align)
acehreli (Moderatör) #1
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Konu adı: Büyük üyeleri başa taşıyarak yapının büyüklüğünü azaltmak (.offsetof ve align)
Bellek Yönetimi bölümüne ek yapıyorum. (Kitabın kağıt baskısının son hazırlıkları.)

.offsetof niteliğini (property) ve align niteliğini (attribute) anlatırken aşağıdaki gibi bir işlev yazdım. Yapının bellekteki yerleşiminin nerelerinde ne kadar doldurma baytı bulunduğunu gösteriyor.

Doldurma baytlarını aza indirmenin bir yolu, üyeleri büyükten küçüğe doğru sıralı olarak tanımlamaktır. Aynı üyelere sahip oldukları halde B yapısının üyeleri A'dan daha küçüktür:
void nesneYerleşiminiYazdır(T)()
    if (is (T == struct) || is (T == union))
{
    import std.stdio;
    import std.string;
 
    writefln("=== '%s' nesnelerinin yerleşimi (.sizeof: %s, .alignof: %s) ===",
             T.stringof, T.sizeof, T.alignof);
 
    /* Tek satır bilgi yazar. */
    void satırYazdır(size_t uzaklık, string bilgi)
    {
        writefln("%4s: %s", uzaklık, bilgi);
    }
 
    /* Doldurma varsa miktarını yazdırır. */
    void doldurmaBilgisiYazdır(size_t beklenenUzaklık,
                               size_t gözlemlenenUzaklık)
    {
        if (beklenenUzaklık < gözlemlenenUzaklık) {
            /* Gözlemlenen uzaklık beklenenden fazlaysa
             * doldurma baytı var demektir. */
 
            const doldurmaMiktarı = gözlemlenenUzaklık - beklenenUzaklık;
            const bilgi = format("... %s bayt DOLDURMA", doldurmaMiktarı);
 
            satırYazdır(beklenenUzaklık, bilgi);
        }
    }
 
    /* Bir sonraki üyenin doldurma olmayan durumda nerede
     * olacağı bilgisini tutar. */
    size_t doldurmasızUzaklık = 0;
 
    /* Not: __traits(allMembers) bir türün üyelerinin
     * isimlerinden oluşan bir 'string' topluluğudur. */
    foreach (üyeİsmi; __traits(allMembers, T))
    {
        mixin (format("alias üye = %s.%s;", T.stringof, üyeİsmi));
 
        const uzaklık = üye.offsetof;
        doldurmaBilgisiYazdır(doldurmasızUzaklık, uzaklık);
 
        const türİsmi = typeof(üye).stringof;
        satırYazdır(uzaklık, format("%s %s", türİsmi, üyeİsmi));
 
        doldurmasızUzaklık = uzaklık + üye.sizeof;
    }
 
    doldurmaBilgisiYazdır(doldurmasızUzaklık, T.sizeof);
}
 
struct A
{
    byte b;
    int i;    // Ortada tanımlanmış
    ubyte u;
}
 
struct B
{
    int i;    // Başta tanımlanmış
    byte b;
    ubyte u;
}
 
import std.stdio;
 
void main()
{
    nesneYerleşiminiYazdır!A();
    writeln();
    nesneYerleşiminiYazdır!B();
}
Çıktısı:

=== 'A' nesnelerinin yerleşimi (.sizeof: 12, .alignof: 4) ===
   0: byte b
   1: ... 3 bayt DOLDURMA
   4: int i
   8: ubyte u
   9: ... 3 bayt DOLDURMA

=== 'B' nesnelerinin yerleşimi (.sizeof: 8, .alignof: 4) ===
   0: int i
   4: byte b
   5: ubyte u
   6: ... 2 bayt DOLDURMA


align niteliği ise değişkenlerin, kullanıcı türlerinin, ve üyelerin hizalama birimlerini belirler. Örneğin, yukarıdaki A'nın eşdeğeri olan aşağıdaki yapıda hiç doldurma baytı bulunmaz:
align (1)    // Bu yapının nesnelerinin hizalama değeri (alignment)
struct C
{
    byte b;
    align (1) int i;    // i'nin hizalama değeri
    ubyte u;
}
 
void main()
{
    nesneYerleşiminiYazdır!C();
}
Hiç doldurma baytı olmayınca nesnelerin büyüklüğü üyelerin toplam büyüklüklerine denk oluyor:
=== 'C' nesnelerinin yerleşimi (.sizeof: 6, .alignof: 4) ===
   0: byte b
   1: int i
   5: ubyte u


Ancak, heyecana kapılıp her yere align(1) eklemeden önce :) C yapısının performansını denemeyi ihmal etmeyin! Hizalama biriminin bir amacı performanstır. C'nin int üyesi yukarıdaki gibi dördün katı olmayan bir adrese rastlatılırsa benim denemelerime göre %10'dan fazla hız kaybına bile neden olabilir çünkü int değerlere dördün katı olan adreslerde iseler hızlı erişilirler.

Ali
Avatar
Salih Dinçer #2
Üye Ock 2012 tarihinden beri · 1912 mesaj · Konum: İstanbul
Grup üyelikleri: Üyeler
Profili göster · Bu konuya bağlantı
Bu hizalama kavramını (alignment) merak ediyordum. Bazen align'ı bir yerlerde görüyor ve anlam veremiyordum. Teşekkürler…

Bu arada kitabın hard kopyası basıldı mı, özelden yazar mısın? Sayfalarını sadece koklamak bile çok hoşuma giderdi :)
Bilgi paylaştıkça bir bakmışız; kar topu olmuş ve çığ gibi üzerimize geliyor...:)
acehreli (Moderatör) #3
Kullanıcı başlığı: Ali Çehreli
Üye Haz 2009 tarihinden beri · 4527 mesaj
Grup üyelikleri: Genel Moderatörler, Üyeler
Profili göster · Bu konuya bağlantı
Kağıt kitabı DConf 2015'ten önce kendim bastıracağım. Tabii ki burada da duyuracağım. :)

Ali
Doğrulama Kodu: VeriCode Lütfen resimde gördüğünüz doğrulama kodunu girin:
İfadeler: :-) ;-) :-D :-p :blush: :cool: :rolleyes: :huh: :-/ <_< :-( :'( :#: :scared: 8-( :nuts: :-O
Özel Karakterler:
Bağlı değilsiniz. · Şifremi unuttum · ÜYELİK
This board is powered by the Unclassified NewsBoard software, 20100516-dev, © 2003-10 by Yves Goergen
Şu an: 2017-11-21, 15:22:48 (UTC -08:00)