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
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
Nasıl no-ri-hayır-rdoc gem için varsay...
Git mergetool istenmeyen oluÅŸturur .or...
Nasıl pahalı RTTI?...
Nasıl ünvan değişikliği istenmeyen UİB...
Bir İmageView etrafında istenmeyen dol...