C RTTI istenmeyen ne yapabiliriz? | Netgez.com
SORU
27 ÅžUBAT 2011, Pazar


C RTTI istenmeyen ne yapabiliriz?

LLVM belgelerine baktığımızda, they use "a custom form of RTTI" ve bu isa<>, cast<> dyn_cast<> şablon işlevleri var neden olduğunu söylediler.

Genellikle, bir kütüphane, bir dil, bazı temel işlevleri reimplements okuma kodu korkunç bir koku ve sadece çalıştırmak için davet ediyor. Ancak, bunu konuşuyoruz LLVM: Millet C compiler üzerinde çalışıyoruzveC çalışma zamanı. Eğer ne yaptıklarını bilmezler bile, Mac OS ile birlikte gelen gcc sürümü clang tercih ederim çünkü çok fazla yandım.

Yine de, onları daha az tecrübe olmanın, normal RTTI tuzaklar ne olduğunu merak ediyorum. -Tablo v var olan bir tür için çalıştığını biliyorum, ama bu sadece iki soru yükseltir:

  • Sadece bir iÅŸlem için sanal bir yöntem gerekir, neden sadece virtual gibi bir yöntem mark deÄŸil mi? Sanal yıkıcılar bu iÅŸi iyi yapıyor gibi görünüyor.
  • EÄŸer çözüm düzenli RTTI kullanmak deÄŸilse, bunu nasıl uygulandığı bir fikriniz var mı?

CEVAP
28 ÅžUBAT 2011, PAZARTESÄ°


LLVM kendi RTTI sistemi rulo çeşitli nedenleri vardır. Bu sistem, basit ve güçlü olduğunu, ve the LLVM Programmer's Manual bir bölümü olarak nitelendirdi. Başka bir poster işaret ettiği gibi, Coding Standards C RTTI ile iki önemli sorun gündeme getiriyor: 1) Alanı maliyeti ve 2) kullanarak kötü performansı.

RTTI alan maliyet oldukça yüksek: sınıfın adını ve onun temel sınıflar hakkında bilgi içeren bir işlem (en az bir sanal yöntem) alır RTTI bilgi, her sınıf. Bu Bilgi typeid operatörü olarak dynamic_cast uygulamak için kullanılır. Çünkü bu maliyet para için her sınıf ile bir işlem (ve hayır, PGO ve Bağlantı iyileştirmeleri yardım yok, çünkü taban puan RTTI bilgi) LLVM inşa ile -fno-rttı. Deneysel olarak, bu oldukça önemli olan bir yürütülebilir boyutu %5-10, sırasını kaydeder. LLVM typeid bir eşdeğer ihtiyacı yok, her sınıf için isimler (type_info diğer şeyler arasında) tutmak, sadece işe yaramaz.

Kötü performansı oldukça kolay eğer kodunu basit işlemler için oluşturulan bazı kıyaslama ya görünürsen görün. LLVM ısa<>operatör genellikle tek bir yük ve bir sabit ile karşılaştırma sınıfları bu classof onların yöntemi uygulamak nasıl dayalı kontrol olsa) derler. İşte basit bir örnek:

#include "llvm/Constants.h"
using namespace llvm;
bool isConstantInt(Value *V) { return isa<ConstantInt>(V); }

Bu derler:

$ clang t.cc -S -o - -O3 -I$HOME/llvm/include -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -mkernel -fomit-frame-pointer
...
__Z13isConstantIntPN4llvm5ValueE:
    cmpb    $9, 8(%rdi)
    sete    %al
    movzbl  %al, êx
    ret

bir yük olduğunu ve sürekli karşı karşılaştırın. Buna karşılık, dynamic_cast ile eşdeğer

#include "llvm/Constants.h"
using namespace llvm;
bool isConstantInt(Value *V) { return dynamic_cast<ConstantInt*>(V) != 0; }

derler ki:

clang t.cc -S -o - -O3 -I$HOME/llvm/include -D__STDC_LIMIT_MACROS -D__STDC_CONSTANT_MACROS -mkernel -fomit-frame-pointer
...
__Z13isConstantIntPN4llvm5ValueE:
    pushq   %rax
    xorb    %al, %al
    testq   %rdi, %rdi
    je  LBB0_2
    xorl    %esi, %esi
    movq    $-1, %rcx
    xorl    íx, íx
    callq   ___dynamic_cast
    testq   %rax, %rax
    setne   %al
LBB0_2:
    movzbl  %al, êx
    popq    %rdx
    ret

Bu çok fazla kod, ama katil çağrısına __dinamik_dökme, sonra onun için sürünmek ile RTTI veri yapıları ve bir çok general, dinamik olarak hesaplanan yürümek bu şeyler. Bu birkaç büyüklük, yük ve karşılaştırın yavaştır.

Tamam, tamam, yavaş, neden bu kadar önemli? Bu LLVM tür kontroller ÇOK önemlidir çünkü. Optimize birçok yerinde desen etrafında kodunda belirli bir yapıları eşleştirme ve kısaltmaları sahne inşa edilir. Örneğin, burada basit bir model zaten Op0/Op1 bir tamsayı çıkarma işlemi sol ve sağ tarafında olduğunu bilir) eşleştirme için kod:

  // (X*2) - X -> X
  if (match(Op0, m_Mul(m_Specific(Op1), m_ConstantInt<2>())))
    return Op1;

Maç operatörü ve-öyle* ısa bir dizi için her tür bir kontrol yapmak/dyn_cast aramalar, kaynatın şablon metaprograms. İnce taneli desen eşleştirme bu tür için dynamic_cast kullanarak vahşice ve showstoppingly yavaş olacaktır.

Son olarak, anlatımcılık biri olan başka bir nokta var. LLVM kullanır farklı şeyler ifade etmek için kullanılan different 'rtti' operators tip onay, dynamic_cast, zorla (iddia) dökme, taşıma boş vb. C 'ler dynamic_cast (doğal olarak) bunların hiçbirini sunmuyor işlevselliği.

Sonunda, bu duruma bakmak için iki yol vardır. Olumsuz tarafta, C RTTI hem de aşırı dar bir çok insan için (tam yansıma) tanımlanır ve çok yavaş LLVM yaptığı gibi bile basit şeyler için yararlı olabilir. Olumlu tarafta, C dili Kütüphanesi kod olarak bu gibi soyut kavramlarla tanımlamak ve dil özelliğini kullanarak tercih edebiliriz güçlüdür. C hakkında en sevdiğim şeylerden biri, güçlü ve zarif kitaplıklar olabilir. RTTI çok yüksek C benim en sevdiğim özellikleri arasında bile:) değil !

-Chris

Bunu PaylaÅŸ:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VÄ°DEO

Rastgele Yazarlar

  • Kim Barbin

    Kim Barbin

    3 Mayıs 2012
  • Shanice Caruthers

    Shanice Caru

    27 EKÄ°M 2011
  • Stevie

    Stevie

    2 Mayıs 2010