Falcon: Giancarlo Niccolai
Falcon’un geliştiricisi Giancarlo Niccolai, Computerworld’e Falcon’un geliştirilmesi, C++’ın gücü ve etkisi ile Falcon sürüm 0.9’daki yeni çoklu iş parçacığı tasarımının betik dili manzarasını nasıl yenilikçi kılacağı hakkında bilgi vermek için biraz zaman ayırdı.
Falcon’un geliştirilmesine ne sebep oldu?
Günlük işimin bir kısmı, finansal ağlar üzerinden gerçek zamanlı veri akışı yapan sunucuların durumuyla ilgilenmekti. Denetim uygulamasında bir betikleme imkânı tam anlamıyla bir nimet olurdu; çünkü uyarı koşulları belirlenmesi zor, sürekli değişen ve sürekli gözetim gerektiren nitelikteydi.
Konuya yabancı değildim; daha önce xHarbour projesinde (xBase dillerinin modern bir taşınması) çalışmıştım ve bu alanda bazı araştırmalar da yapmıştım. İş yükü ağırdı; her bir mesaj üzerinde uygulanacak mantık basit olsa bile, geçen veri saniyede binlerce mesaj mertebesindeydi, her biri hızlı aksiyon gerektiriyor ve her biri hâlihazırda karmaşık C++ sınıf hiyerarşilerine seri hâlden çıkarılmış yaklaşık bir ila dört kilobayt ham veriden oluşuyordu.
Ham hesaplama gücü açısından mevcut motorlar yeterliydi, ancak açgözlüydüler. Görevlerini, tüm uygulamayı sürdürmek için yapılması gereken en önemli şey olarak görüyorlardı; bu nedenle bir betiği kurmak, bir geri çağırma başlatmak, harici veriyi sarmalamak ya da uygulamadan çok yüksek hızda gelen veriyi sağlamak için gereken süreyi pek umursamıyorlardı.
Ayrıca onları çok iş parçacıklı bir bağlamda kullanmak da oldukça zordu. Çok iş parçacığında çalışacak şekilde tasarlanmış (yani farklı iş parçacıkları tarafından eşzamanlı kullanılabilen – bizim de ilgilenmemiz gereken pek çok bağlantı ve veri akışı vardı) tek VM Python’du; ancak çok ilkel bir çoklu iş parçacığı anlayışıyla çalışıyor, her bellek ayırmada ve her betiğin çeşitli adımlarında küresel kilitleri zorunlu kılıyordu. Testlerim, bunun betikle doğrudan ilişkili olmayan uygulama bölümlerinde bile (yani Python VM’leri başlatılmadan önce betikler için veriyi hazırlayan kısımlarda) hızlı bir yavaşlamaya yol açtığını gösterdi.
Olası tüm betik motorları arasında Lua en uygun olanıydı; ancak eşzamanlı iş parçacıklarından kullanımı bazı sorunlar doğuruyordu (o dönemde bellek ayırıcısı iş parçacığı güvenli değildi ve geniş küresel kilitlerle yeniden uyarlanması gerekiyordu). Ayrıca geniş tamsayı verileriyle uğraşmak zorunda olduğumdan (finansal piyasalardaki fiyatlar sıklıkla ondalık bölenli int64 olarak dağıtılır), Lua’nın yalnızca tek bir sayı türü sunması – 58 bit hassasiyetli kayan nokta – beni endişelendiriyordu. Bunlar finans alanında ciddi yuvarlama/hassasiyet sorunlarına da yol açıyor ve bu nedenle genellikle kaçınılıyor.
Bu motorları görevin gereksinimlerini karşılayabilir hâle getirmek için yapılması gereken iş o kadar fazlaydı ki, alternatifler ya denetim uygulamasını ve daha sonra ikinci aşamada sunucuların kendilerini betikleme fikrinden vazgeçmek ya da yeni bir şey yazmaktı.
Vazgeçmekten nefret ederim; bu yüzden, yalnızca bir betik motoru olması ve ana uygulamayla birlikte büyük veri aktarımını yönlendirmesi amaçlanan HASTE (Haste Advanced Simple Text Evaluator) üzerinde çalışmaya başladım.
Dil belirli bir sorunu çözmeyi mi hedefliyordu?
HASTE’in erken geliştirilmesinin arkasındaki ana fikir, mevcut karmaşık çok iş parçacıklı uygulamalarla ‘entegre edilebilirlik’ ve gerçek zamanlı, acil ve büyük ölçekli veri akışıyla etkileşimdi.
Çalışır bir şey elde ettiğimde, ham veriyle başa çıkabilme yeteneğinin ve VM’nin ana uygulamayla iş birliği yapma biçiminin, ikili dosya ayrıştırma, görüntü işleme, oyun geliştirme (oyun betikleme değil), geniş/uluslararası dize işleme gibi diğer betik dillerinin parlamadığı alanlarda çok değerli olduğunu kısa sürede fark ettim.
Aynı zamanda, diğer betik dillerindeki yapıları sınırlayıcı buluyordum. Buyruksal ve prototip tabanlı programlama oldukça güçlü olduğu ve Ruby’nin ‘tam OOP’ yaklaşımı büyüleyici olduğu için bunlarla yaşayabilirdim; ancak HASTE çalışır ve iyi performans gösterir hâle gelmişken (HASTE VM, Lua’nınkinden daha basit ve biraz daha hızlıydı) motorun saf ihtiyaçlarının ötesinde düşünmeye başladım.
Bir profesyonel olarak, HASTE’i geliştirdiğim o spesifik görev günlük faaliyetlerimin sadece küçük bir parçasıydı. Larry Wall’un Perl’ü kendi ihtiyaçlarından (büyük miktarda yapılandırılmamış günlük verisini ayrıştırmak) yola çıkarak geliştirmesine benzer şekilde, görevlerimi sürdürebilmek için daha üst düzey bir mantığa ihtiyaç duymaya başladım – yapılandırılmış veriler üzerinde karmaşık analiz, örüntü bulma ve karar verme.
C, C++, Java, assembly, Lisp, Prolog, Clipper/xBase, Delphi, SQL ve elbette Python, Lua, Perl ve PHP dâhil pek çok dille çalıştım ve zaman içinde eldeki problemi çözmek için en iyi araçları kullanmayı öğrendim. Günlük ihtiyaçlarımı karşılayabilecek ve yeni fikirleri yönlendirebilecek kadar esnek bir araca ihtiyaç duyduğumu hissettim.
Saf fikirler makine için faydalıdır. Prolog gibi saf bir mantık dili, kuralları ham makine koduna açarak çözümleri mümkün olan en hızlı şekilde bulabilir. Erlang gibi saf işlevsel diller, derleme zamanında büyük hesaplamaları otomatik olarak paralelleştirebilir. Ruby gibi saf OOP dilleri ise her varlığı aynı şekilde ele alarak bunları uygulamak için gereken kodun karmaşıklığını azaltabilir.
Ancak saflık zihin için asla iyi bir fikir değildir. Zihin birleştirme ve analojiye doğru çalışır ve gerçek dünyadaki çözümler, genellikle geniş bir çözümleme teknikleri kümesi kullanılabildiğinde daha etkilidir. Bu, matematikte bile böyledir; diferansiyel bir denklemin indirgenmesi gibi görünüşte ‘mekanik’ problemleri çözmek için farklı çözümleme tekniklerini (ve çoğu zaman ciddi miktarda hayal gücü ve deneyimi) uygulamanız gerekir.
HASTE son derece basitti; diziler ve sözlüklerle saf prosedürel bir dildi, ancak ilginç bir özelliği vardı – fonksiyonlar da normal öğeler olarak kabul ediliyordu. Bu bana, ‘programlama paradigması’nın ‘hepsi ve hiçbiri’ olduğu, HASTE’in betik motorunun ötesinde genel amaçlı bir dil yönünde çalışma fikrini verdi.
Böylece Falcon, saf OOP’ye sahip olma fikriyle (böylece ham, sert C yapıları sözlük benzeri bir yapıyı doldurmaya gerek kalmadan eşlenebilsin), ama OOP olmadan; saf prosedürel bir yapıya sahip olma fikriyle (eski, sevilen fonksiyonlar ve çağrı-dönüş iş akışıyla yönlendirilen), ama prosedürel olmadan; ve işlevsel yapılara sahip olma fikriyle, ama işlevsel olmadan ortaya çıktı.
Ayrıca, mevcut fikirlerin yanına ve onların boyunca yeni fikirler ekleme düşüncesiyle geliştirildi. Problemleri yeni kavramsal araçlarla çözmek için genişleyen bir kavramlar kümesi; profesyonel geliştiricinin fikrini problemle eşleştirmek ve yaşayan bir çözüm meydana getirmek için ihtiyaç duyduğu zihinsel yükü azaltmak amacıyla. Artık bir dili çözümü elde etmek için nasıl düşünmesi gerektiğini öğrenmeye gerek kalmadan, programcının zihninin problemleri çözme biçimine doğru ilerleyen bir dile sahip olmak.
Farklı ve sürekli değişen alanlarda (bir gün davranış örüntüleri aramak için gigabaytlarca ikili veriyi ayrıştırmak, ertesi gün şirketimdeki kurslar için sınıf ‘dönüşümlülüklerini’ organize etmek gibi) daha üst düzey mantık problemlerine hızlı bir şekilde, kolay ve esnek çözümler şekillendirebileceğim bir araca ihtiyacım vardı.
Falcon’da gurur duyduğum tek bir şey varsa, o da en egzotik nedenlerle değil, bir yanda büyük uygulamaların entegrasyonu ve güçlendirilmesi sorununu, diğer yanda karmaşık mantık ve son derece değişken problemleri çözme gereksinimini ele almak için ortaya çıkmış olmasıdır. Başka bir deyişle, gerekli bir araç olarak ortaya çıktı.
Perl, Clipper, muhtemelen C++ ve C gibi, gerçek problemleri ele almak üzere ortaya çıkan az sayıda dil vardır; bunlar da aslında araştırma/eğitsel üniversite projelerinden evrimleşmiştir.
Falcon’u daha düşük seviyeli bir dil yerine neden C++ üzerine inşa etmeyi seçtiniz? İki dil arasındaki benzerlikler nelerdir?
OOP’yi seviyorum ve C’nin gücünü seviyorum. Falcon için C++’ı seçtiğimde, düşük seviyeli işler için C’yi, daha üst kavramları şekillendirmek için C++ sınıflarını kullanacağımdan emindim. Betiklemem gereken tüm uygulamalar C++ idi ya da C++ ile entegre olabiliyordu. Ayrıca oyun endüstrisinde çalışan bir arkadaşım bana sanal çağrıların aslında switch’lerden daha verimli olduğunu söylemişti ve bir betik dilinde bunlardan çok sayıda var. Bunu kendim de test ettim ve modern işlemcilerin sanal çağrıların varlığında gerçekten çok iyi performans gösterdiği ortaya çıktı; böylece genellikle karmaşık if’lerle çözülen pek çok yaygın problem, bunun yerine sanal çağrılarla çözülebiliyordu.
Başlangıçta STL’yi de kullandım; bu, genellikle dinamik tiplemeye dayalı herhangi bir kütüphaneden çok daha yüksek performans sunar (STL map’leri Python dize sözlüklerinden en az yüzde 10 daha hızlıdır), ancak bu durum diğer programlarla birlikte çalışabilirlik açısından önemli bir sorun getirdi. Falcon aynı zamanda bir betik motoru olarak tasarlanmıştı ve uygulamaların hangi STL sürümünü kullanmak istedikleri konusunda sıklıkla farklı görüşleri olur. STL’yi DLL’ler arasında taşımak oldukça zahmetlidir ve C++ modüllerinin ikili uyumluluğuna ölümcül bir darbedir (doğası gereği zaten C modüllerinin ikili uyumluluğundan daha az stabildir). Ayrıca STL, kodun oldukça büyümesine neden oldu ve istediğimden çok daha fazla. Bu yüzden, harici bağımlılıkları modüller arası arayüzden temizlediğimden emin olmak için geçici olarak daha yavaş olan dinamik tipli yapılara geri döndüm.
Son zamanlarda, yeni derleyicilerin istisna fırlatmanın hızlı yolunda son derece verimli olduğunu (aslında bir hata koşulunda tek bir if’ten bile daha hızlı) fark etmişken, VM’nin derinliklerinde hata üretildiğinde ortaya çıkan kontrol kaskatlarının olduğu yerlerde istisnaları devreye aldım.
Kısacası Falcon, hız ve kodun okunabilirliği ile sürdürülebilirliği açısından avantaj sağlayabildiği yerlerde C++ kullanırken, düşük seviyeli pek çok konuda C odaklı kalır. Bu, C uygulamalarıyla birlikte çalışabilirliği azalttığı izlenimini verebilir; ancak durum böyle değildir.
Açık kaynak bir proje olarak ilk çalışmalarımızdan biri, meşhur Xchat programı için FXchat betik eklentisinin hazırlanmasıydı; bilindiği üzere Xchat eklenti API’si saf (ve ham) C’dir. Buna rağmen arayüz, herhangi bir birlikte çalışabilirlik sorunu olmaksızın ve hatta belirgin bir verimsizlik olmadan çerçeveye zarif bir şekilde uyum sağlar; çünkü Falcon betik motoru kendi yüklenebilir modülü içinde sınırlandırılmıştır ve FXchat modülü bir köprü görevi görür. Kod hatta basit ve doğrudandır; kısa sürede bizimkinden çok daha karmaşık hâle gelen, C ile yazılmış diğer betik dili eklentileriyle karşılaştırmak kolaydır.
Aynı şey harici kütüphaneleri bağlayan modüller için de söylenebilir. Hem C++ ile yazılmış DCOP kütüphanesiyle hem de C ile yazılmış SDL kütüphane setiyle tam birlikte çalışabilirlik ve hiçbir performans ya da uyumluluk sorunu olmadan zarif bir şekilde bağlanıyoruz.
Falcon şu anda geliştiriciler tarafından nasıl benimseniyor?
Falcon sahnede hâlâ az biliniyor ve Python ile Perl gibi devlerin ortalıkta olduğu, REBOL ve Erlang gibi büyük kurumlar tarafından beslenen bir ortamda, yeni ürünlere karşı temkinlilik yüksek. Öte yandan, Falcon’la tanışan pek çok geliştiricinin ondan etkilendiğini ve artık onsuz olmak istemediklerini söylemek gerekir!
Kross projesinden Sebastian Sauer, Falcon’un Kross ve KDE içinde yer alması için yoğun çaba harcadı; BlastWave’deki Dennis Clarke ise BlastWave açık kaynak paket deposunun Web arayüzünü Falcon ile yeniden tasarlıyor ve tüm Falcon kod tabanının Sun platformlarına taşınmasına yardımcı oluyor – AuroraUX SunOS dağıtımı, onu resmi betik dili olarak (tercih edilen ağır sıklet geliştirme dili olarak Ada ile birlikte) benimsemeye karar verdi.
Her gün pek çok ‘tebrikler’ mesajı alıyoruz; ancak pratikte daha dün başlamış sayılırız (birkaç ay önce açık kaynak olduk ve dağıtılmaya başladık). Bu nedenle, pek çok ilgili geliştiricinin bir göz attığı ve projenin gelecekteki geliştirmeler için istikrarlı bir platform sağlayacak kadar tutarlı hâle gelip gelmediğini görmek üzere pencereden izlediği hissine sahibiz.
Bu bağlamda, bazı resmî kurumlardan ilginç teklifler almaya başlıyoruz. Şu an için bu yalnızca ilgi ve iş değişimi meselesi; ancak son zamanlarda gözlemlediğimiz hızla büyüme devam ederse, Falcon projesini desteklemek için yakında bir ekonomik yapı kurmamız gerekecek.
Falcon ekosistemi nasıl?
Başlangıçta ve birkaç yıl boyunca, sadece bendim. ‘Sadece’yi tırnak içinde söylüyorum; çünkü Falcon bir boş zaman projesi olarak değil, yüksek profilli bilişim alanında günlük işimle etkileşime girmeyi hedefleyen profesyonel bir proje olarak tasarlanmıştı. Yazılımımı değil, becerilerimi ve danışmanlık zamanımı satabilmiş olmam; açıklanamayan bazı iç projeleri, açık kaynak yoluyla paylaştığım genel parçalardan ayırmamı sağladı (SourceForge’da çeşitli projelerde kullandığım daha eski bazı kütüphanelerim de var).
2007’nin başlarından itibaren bazı katkıcılar kodu çekip zaman zaman yamalar sağladı; ancak depoya benim dışımdaki ilk katkılar 2008’dendir.
Projede aktif olarak çalışan, harici ya da çekirdekte, yan modüllerde veya ilgili projelerde kod sağlayan yaklaşık 10 ila 12 geliştirici, katkıcı ve paketleyiciden oluşan bir topluluğum var. Katkıları sayı ve ağırlık olarak hâlâ az, ancak Falcon kadar geniş ve karmaşık bir projeye dâhil olmak zaman gerektiriyor.
Ayrıca Falcon tabanlı ve Falcon ile ilişkili projeleri barındırmak için bir tür ‘mini-SourceForge’ hazırlıyoruz.
Geliştiriciler proje tarzımız hakkında biraz bilgi edinmek isterse, açık kaynaklı bir projenin olabileceği kadar açığız. Yeni fikirler, projede istikrarlı biçimde yer alan ya da sadece uğrayıp bir not bırakan insanların yardımı ve önerileri sayesinde motorumuza sürekli olarak entegre edilmiştir. Bugüne kadar mümkün olmamış olsa da, Falcon projesine kulak vermeye ve el uzatmaya istekli olan herkese bilgilerimi aktarmaya hazırım. Dolayısıyla, geliştiriciler bir fark oluşturmanın yolunu arıyorsa, bizimle kalın ve oyunuzu anlamlı kılalım!
Dilin kendine ait bir depo sistemi var mı?
Hayır. Bunu söyleyen kişi ben olsam da garip gelebilir, ancak tekerleği yeniden tasarlamayı gerçekten sevmiyorum. SVN kullanıyoruz, fakat ihtiyaç doğarsa GIT’e ya da daha Web odaklı bir şeye geçebiliriz. Şu anda commit geçmişini çok önemli görmüyorum (0.8 ve 0.9 head dalları istisna olmak üzere), bu yüzden yeni bir depoya geçmek herhangi bir sorun teşkil etmez.
Falcon hız üzerine bir vurguya sahip gibi görünüyor, bu programlama dilleri içinde önemli mi?
Hız programlama dilleri içinde önemli değildir – bazı programlama dilleriyle çözülebilecek bazı görevler için önemlidir. Söylediğim gibi, HASTE’i başka hiçbir betik dilinin karşılamadığı bir hız ihtiyacından dolayı yazdım, ancak Falcon başka nedenlerle HASTE’ten evrildi.
Hız her şey olsaydı, betik dilleri var olmazdı. Temel işlemlerde, sınıfımızdaki en iyiler aynı işleri yapan C’den yaklaşık 30 kat daha yavaş çalışabiliyor ve bu kesinlikle yavaştır. Çok yönlülük, uyarlanabilirlik, sürdürülebilirlik, uygunluk, entegre edilebilirlik, karmaşıklık ve daha pek çok etken hangi dilin benimseneceğine karar vermede büyük rol oynar.
Hız, her şeyin önkoşulu olması anlamında en önemli etkendir, ancak dile özgü değildir. Hız, tüm “girdi‑işleme‑çıktı” hattı tarafından belirlenir ve bir betik dilinin bu hat içindeki katkısı genellikle küçük bir parçadır. IPO hattınız gereksinimi karşılamıyorsa, başka hiçbir şeyin önemi yoktur; Falcon’un erken döneminde, uygulamalarımın işi zamanında yapabilecek kadar verimli bir IPO hattında kullanılmasına izin veren başka hiçbir betik motoru yoktu.
Tüm sisteminiz IPO zaman gereksinimlerini karşıladığında, hız denklemden çıkar ve hız dışındaki her şey önem kazanır. Bu ikili bir seçimdir: tüm IPO hattınız ya yeterince hızlıdır ya da değildir.
“hızlı” dediğimizde, geliştirmemizi Falcon çevresindeki tüm sistemin onu mümkün olduğunca hızlı kullanmasına yardımcı olmaya odakladığımızı kastediyoruz. VM hızı da önemlidir; yoğun biçimde VM tabanlı hesaplamalar yapmak istediğiniz bazı görevler vardır, ancak bizim bakış açımıza göre bu, çevredeki dünyaya (uygulamalar, modüller, iş parçacıkları) daha hızlı çalışabilmeleri için sunulan “hizmete” kıyasla ikincil bir rol oynar.
Bu nedenle VM’nin kendisi üzerinde tek bir optimizasyon yapmadan yedi yıl yaşayabildik ve şimdi, yansıtma modelimizi tamamladığımız ve çevredeki dünyaya elimizden gelen en iyi hizmeti sunduğumuz noktada, onu optimize etmeye başlıyoruz.
Falcon’un derleme zamanında düzenli ifade derlemesi, diğer dillerin kütüphane yordamlarıyla nasıl karşılaştırılır?
Aslında derleme zamanında düzenli ifadelerin şu ana kadar hazır olması planlanıyordu (Nisan 2009), ancak 0.9 sürümünde biraz uzadık ve bu durum derleme zamanı regex geliştirmesini biraz ileri bir tarihe kaydırdı. Yine de konu ilginç, çünkü betik motoru kullanıcıları için yararlı olabilecek bağlama düzeyinde üç mekanizmayı göstermeme olanak tanıyor.
Plan şu şekilde: Falcon modüler sistemi, C++’a service adı verilen bir mekanizma sunar. Bir service, modülün onu yükleyen betiklere yayınlayacağı şeyleri C++’a yayınlayan sanal bir sınıftır.
0.8.12’den bu yana, Falcon derleyicisi talep üzerine eksiksiz bir sanal makineyi çalıştıran bir meta‑derleyiciye sahiptir. Meta‑derleme fikrini kabul ettiğimizde, derleyici ortam ayarlarını da kullanarak Regex modülünü yükleyebilir ve service arayüzü üzerinden onun yöntemlerini kullanabilir; bu, doğrudan C fonksiyonlarını çağırmaya tamamen benzer, yalnızca bir sanal çağrı dolaylı katmanı vardır (ki bu, bir düzenli ifadeyi derleme bağlamında tamamen önemsizdir).
0.9’dan beri, öğelerin kendileri operatörleri item_co (item common operations) adlı bir fonksiyon vektörü üzerinden çözmekten sorumludur. Derleme zamanında düzenli ifadeler olarak üretilen dizgiler için yeni bir öğe türü tanıtabilir ve bunlara diğer dizgi öğe türünden kısmen türetilmiş bir item_co tablosu sağlayabiliriz ya da onları özel bir işaretleyiciye sahip bir dizgi olarak oluşturup (zaten dizgi alt türlerimiz var) eşitlik/ilişkisel operatörlerde dallanmalarla işlem yapabiliriz.
Modern sistemlerde, bir dallanma CPU/bellek süreleri açısından basit bir çağrıdan daha pahalıya mal olabilir; bu yüzden muhtemelen bir öğe türü eklemeyi tercih ederim (bu, betik düzeyinde de bu özel dizgileri algılayıp onları farklı biçimde ele almak için yararlı olurdu).
Regex modülünü derleme zamanında kullanmak istememiz, gömücü uygulamalar için bir başka ilginç noktadır. Düzenli ifadeleri ana motora dahil etseydik, onu biraz daha büyütmüş olurduk ve gömücülerin bu özelliği devre dışı bırakabilme olanağını ortadan kaldırırdık.
Falcon’u istememin nedenlerinden biri, yabancı ve daha az güvenilir betiklerin uzaktan derlenebilmesine ve önceden derlenmiş biçimde uzak bir sunucuya gönderilerek uzaktan yürütülmesine izin vermekti. Yürütmeyi yapan sunucu, güvenlik gerekçeleriyle bazı özellikleri devre dışı bırakmak isteyebilir (örneğin dosya G/Ç kullanımını yasaklayabilir) ve bunu yalnızca bazı ayrıcalıksız VM’lerde yaparken, yönetim betikleri tam yetkiyle çalışır. Diğer betik motorlarıyla bu, derin yeniden yazımlar olmadan imkânsızdı.
Falcon modüler sistemi, modüllerin talepte bulunan VM’lere enjekte edilmeden önce uygulama tarafından incelenmesine ve değiştirilmesine olanak tanır. Böylece, farklı ayrıcalık seviyelerine sahip betik alanları olan bir sunucu ya da uygulama, betiğin kullanmasına izin vermek istediği modülleri önceden yükleyip yeniden yapılandırabilir, diğer modüllerin yüklenmesini engellerken ayrıcalıklı betiklerin engelsiz çalışmasına izin verebilir.
Regex’ler ağırdır ve tüm gömülü uygulamalar betiklerinin bunları kullanmasını istemeyebilir. Örneğin, bir MMORPG uygulaması AI botlarının düzenli ifadelere ihtiyacı olmadığına karar verebilir ve Regex modülünü sağlamaktan kaçınabilir. Bu noktada, derleyici kaynakta bir r"..." dizgisi bulursa basitçe bir hata yükseltir ve VM, bir modül içinde önceden derlenmiş bir Regex ile uğraşmak zorunda kalırsa hata üretir.
Aynı zamanda, Regex modülü eksiksiz bir komut satırı Falcon kurulumunda zorunlu olduğundan, komut satırı betikleri Regex’leri yalnızca Regex modülünün dinamik yüklenmesinin ek maliyetiyle kullanabilir; bu, eksiksiz bir Falcon uygulamasında önemsizdir ve Web sunucusu modüllerinde olduğu gibi tekrar eden kullanım kalıplarında önbelleğe alınır.
Düzenli ifadelerinizi sürmek için kendi Regex kütüphanenizi geliştirmeyi planlıyor musunuz?
Hayır, PCRE’den memnunuz; görüşümüze göre mevcut en iyi kütüphane o ve görece büyük olsa bile, ihtiyaç halinde yüklenen ayrı bir modülde bulunması en doğru yol gibi görünüyor. Gelişimini mümkün olduğunca yakından takip ediyoruz; PCRE’nin mevcut olduğu bazı sistemlerde (birçok Linux dağıtımı) yerel bağlama sağlıyor ve mevcut olmadığı yerlerde modül kodu içinde doğrudan dağıtıyoruz.
Falcon’un gömülebilir yönü ne kadar esnek?
Bunun hakkında yukarıdaki Regex örneğinde genişçe konuştum; ancak önceden yüklenmiş modüllerin yeniden yapılandırılabilirliği ve uygulama VM’leri arasında paylaşımının ötesinde, daha fazlası var.
VM’nin kendisi, hedef uygulama tarafından geçersiz kılınabilen birçok sanal metoda sahiptir ve betik başına bir VM modeline izin verecek kadar hafiftir. Ağır betikler hedef uygulamada kendi VM’lerine sahip olabilir ve her biri kendi iş parçacığında mutlu biçimde çalıştırılabilir; yine de, yeni çalıştırılmış betiklerin bağlantısı kesilip yenileri bağlanarak VM’ler geri dönüştürülebilir, mevcut modüller korunur ve böylece onlara ihtiyaç duyan betiklere zaten hizmet eder durumda olurlar.
VM’nin kendisi, periyodik geri çağrılar ve uyku istekleri aracılığıyla gömülü uygulama ile etkileşime girebilir. Örneğin, VM’nin çalışmaya hazır bir coroutine takas edemediği her uyku isteğinin çağıran uygulamaya iletilmesi için bir bayrak ayarlanabilir; uygulama da boş zamanı en uygun gördüğü şekilde kullanmaya karar verebilir. Bu, örneğin FXChat bağlamasında sleep() fonksiyonunun Xchat’in devam etmesine izin verdiği etkileyici yarı paralel etkileri mümkün kılar.
Bu ikincil bir yön gibi görünebilir, ancak diğer motorlar bu konuda aslında çok kapalıdır; bir betiği başlattığınızda ya da bir geri çağrı verdiğinizde, uygulamanın yapabileceği tek şey onun yakında bitmesini ummaktır. Falcon ile hedef VM’yi basit isteklerle kesintiye uğratabilir, bunların mümkün olan en kısa sürede yerine getirilmesini sağlayabilir ve nihayetinde askıya alındığı ve incelendiği noktadan devam ettirebilirsiniz.
0.9’dan beri, kişiselleştirilmiş bir nesne modeli bile tanıttık. Falcon örneklerinin tam teşekküllü Falcon nesneleri olması gerekmez; uygulama, Falcon VM içinden geçen öğelere veriden kendi eşlemesini sağlayabilir. Bunu, her yeni örnekte bir sözlük oluşturma ve her özelliği ana programdan ya da bağlanmış kütüphaneden veri alan bir fonksiyona eşleme ihtiyacıyla karşılaştırın.
Geçersiz kılabileceğiniz diğer sınıflar arasında, Falcon modüllerini başka türde kaynaklardan ya da gömülü uygulamaların iç depolamasından sağlayabilen modül yükleyici ve 0.9’dan beri URI sağlayıcıları bulunur. Modüller ve gömülü uygulamalar kendi URI sağlayıcılarını kaydedebilir; böylece app:// alanında bir modül açmak, dahili olarak sağlanan bir kaynaktan modül alma isteğine dönüşür ya da bir betikten app:// üzerinden bir akış açmak, uygulamanın diğer bölümleriyle akışlar aracılığıyla ikili veri iletişimini mümkün kılar.
Açıkçası, motorumuzu etraftaki en esnek çözüm yapmak için elimizden geleni yaptık. Lua’nın çok esnek olduğu söylenir, çünkü onu istediğiniz gibi yeniden programlayabilirsiniz. Ancak bu, aslında herhangi bir açık kaynaklı proje için de geçerlidir.
0.9 sürümündeki yeni çok iş parçacıklı tasarım, betik dili panoramasında nasıl bir yenilik getirecek?
Betik dillerinde çok iş parçacıklılığın hassas bir konu olmasının iki iyi nedeni vardır (birçoğunun yüzleşmek bile istemediği).
Birincisi, çok iş parçacıklılık işleri bozabilir. İyi çok iş parçacıklılıkta (modern mimarilerin paralel hesaplama gücünden aşırı ek yük olmadan gerçekten yararlanmaya izin veren çok iş parçacıklılıkta), bir iş parçacığındaki hatadan kurtulmanın yolu yoktur. Başarısız olan bir iş parçacığı, başarısız bir uygulamadır ve bu, betik dili sanal makinelerinin arkasındaki kontrollü yürütme kavramına oturtulması biraz zor bir durumdur.
İkinci neden ise, Lua geliştiricilerinin de belirttiği gibi, a = 0 ifadesinin deterministik olmadığı bir dilin çok iş parçacıklılıkta verimli biçimde kullanılamayacağıdır.
Bazı betik dilleri, a = 0 ifadesini deterministik ve iş parçacıkları arasında görünür kılmak için her atama talimatını kilitler; bu, birçok açıdan performansı öldürür. Yalnızca betiğin kendi performansını tüketmekle kalmaz, uygulama içinde eşzamanlı programlama durumunda, gereksiz bağlam değişimlerine zorlayarak ana uygulamanın performansını da ciddi biçimde düşürebilir.
Biz saf bir ajan tabanlı iş parçacıklılık modelini benimsedik.
Her iş parçacığı ayrı bir sanal makine çalıştırır ve iş parçacıkları arası iletişim yalnızca özel veri yapıları üzerinden gerçekleşebilir. Bu şekilde, her sanal makine küresel senkronizasyondan tamamen bağımsız biçimde çalışabilir. MemBuf öğe türü aracılığıyla ham bellek alanlarını paylaşmak ya da ayrı işlemlerle oluşturulmuş tam nesneleri iş parçacıkları arası bir öğe kuyruğu üzerinden göndermek mümkündür.
Mesele şu ki, bize göre betik dillerinde çok iş parçacıklılık, düşük seviyeli dillerdeki çok iş parçacıklılık olarak görülmemelidir; orada her işlem, alttaki paralel CPU’lardaki etkinliklere eşlenebilir. Mutex/event tabanlı paralel programlama fikri, betik dilleri gibi son derece yüksek seviyeli dillerde reddedilmelidir; çünkü en basit talimatta bile çok fazla temel işlem yer alır. Üstelik, düşük seviyeli dillerle yazılmış karmaşık uygulamalarda bile bu ilkel yapıların daha yüksek seviyeli iletişim mekanizmaları oluşturmak için kural gereği kullanıldığı düşünüldüğünde, bizim görüşümüz, betik dillerindeki çok iş parçacıklılığın tam olarak bu mekanizmaları sağlaması ve betikleri verimli biçimde yapamayacakları şeylere, yani düşük seviyeli senkronizasyon ilkellerine zorlamaya çalışmamasıdır.
Bir sunucu yazarken, bu ilkeller üzerinden karmaşık senkronizasyon kuralları ve yapıları kurmakta, onları doğrudan kullanmaktan kaçınmak için çabaladığımı görüyorum ve aynı çabayı betik kullanıcılarına yüklememiz gerektiğini düşünmüyorum. İlkel senkronizasyonun yararlı olduğu alan, betik dillerinin doğrudan rol oynaması gereken bir alan değildir – zaten betik dilinden kullanılacak bir C modülü yazmak isteyeceğiniz yerdir.
0.9’da, birden fazla sanal makinede bulunan nesneleri hesaba katan bir iş parçacıkları arası çöp toplayıcı tanıttık. Bu, MemBuf örneklerinin paylaşımı yoluyla zaten kullanılıyor, ancak bu desteği diğer nesne türlerine de genişletmeyi planlıyoruz. Örneğin, şu anda bir yerel nesnenin kopyasını bir öğe kuyruğu aracılığıyla başka bir iş parçacığına göndermek mümkündür (alttaki veri, muhtemelen bir modülden ya da gömülü bir uygulamadan geliyor olsa bile, aslında paylaşılabilir; kopyalanması gereken yalnızca her VM’nin nesnenin temsiline sahip olmasıdır). Bu, iş parçacıkları arasında tam nesnelerin birlikte oluşturulmasını biraz zorlaştırır ve ajan tabanlı iş parçacıklılık açısından çalışsa bile, yeni iş parçacıkları arası GC sistemini kullanarak derin öğeleri iş parçacıkları arasında gönderebilmeyi planlıyoruz. 0.9’dan beri, derin veriyi haricen (yani gömülü uygulamada ya da bir modülde) oluşturmak ve bunu farklı bir iş parçacığındaki bir VM’ye göndermek zaten mümkündür.
Bunu iki farklı VM arasında yerel olarak yapmada kalan tek sorun, hedef VM nesne üzerinde çalışırken kaynak VM’nin nesne ve içindeki herhangi bir veri üzerinde çalışmasına izin verilmemesini sağlamaktır. Bu bir sınırlama gibi görünse bile, bu tam olarak çok iş parçacıklılığa yönelik nesne izleyici yaklaşımının dayattığı şeydir ve daha yüksek seviyeli paralel soyutlama anlayışımızla tamamen tutarlıdır.
0.9 sürümü ayrıca, mesaj yönelimli programlamanın iş parçacıkları arası işlemlere genişletildiği iş parçacıkları arası yayın mekanizmasını da tanıtır. Bunu hâlâ tamamen netleştirmemiz gerekiyor, ancak bu, bu sürüm aralığını “0.9” olarak numaralandırmamızın nedenidir.
Son olarak, VM artık yerel çok iş parçacıklı yapılar içerdiğinden, farklı iş parçacıkları için farklı VM’lere sahip olma gerekliliğini de ortadan kaldırabiliriz; her iş parçacığı kendi yerel bağlamı üzerinde çalışırken, VM üzerindeki ortak işlemler (örneğin yeni modüllerin yüklenmesi) kolayca korunabilir. Yine de, bu gömülü uygulamalar için yararlı bir model olduğundan, farklı iş parçacıklarında yaşayan birden fazla VM olasılığını dikkate almamız gerekiyor.
Bir yazılım geliştiricisi Falcon geliştirmeye nasıl dahil olabilir?
Kolayca. Falcon’a verebileceğiniz desteği temelde beş ana alana ayırabiliriz. Bunları ağırlıklı aciliyet/karmaşıklık oranına göre sıralıyorum.
-
Modüller. Dilin mevcut özelliklerini genişletmemiz gerekiyor ve modüller, hem yazılması ve derlenmesi görece basit oldukları hem de yazarı VM ve öğe API’si ile oldukça doğrudan temas ettirdikleri için başlanacak iyi bir noktadır. Şu anda kapsamlı bir modül geliştirici kılavuzumuz yok, ancak örnekler çok sayıdadır ve iyi yorumlanmıştır; hem VM’nin hem de öğelerin API’leri ayrıntılı biçimde belgelenmiştir. Sitedeki “extensions” alanımızdan indirilebilen bir iskelet modül mevcuttur ve yeni projeler için kolay bir başlangıç sağlar. En çok talep edilen modüller ve bağlamalar listelenmiştir.
-
Uygulamalar. Falcon ile yazılmış kapsamlı bir CMS gibi çarpıcı bir uygulamayı memnuniyetle karşılarız, ancak daha basit uygulamalar da kabul edilir.
-
Uzantılar ve gömülü kullanım. Bir betik motoru olarak, uygulamalarını Falcon ile yönlendirmek isteyenleri memnuniyetle karşılıyoruz. Örneğin, KDE uygulamalarında Kross ile olan bağlama. XChat için sevimli bir betik motoru bağlamamız var ve bunu diğer betiklenebilir uygulamalar (diğer IM sistemleri, editörler, müzik çalarlar vb.) için de istiyoruz. Ayrıca mevcut HTTP sunucusu modül bağlama motorunu genişletmemiz ve daha fazla sunucuya uygulamamız gerekiyor. Şu anda yalnızca Apache’yi destekliyoruz.
-
Falcon çekirdeği. Çekirdek sistemi, çekirdek modülü ve Feathers’ı sürdürmek ve genişletmek hâlâ oldukça zorlu: 0.9 geliştirme dalı yeni başladı ve bellek yönetimi ve derleyici iyileştirmeleri açısından mevcut en ileri tekniklerden yararlanmamız ya da yenilerini bulmamız gerekiyor. Bu turda en az iki yeni paradigmayı tanıtacağız: mantıksal programlama ve tür sözleşmesi programlaması; ayrıca tablo tabanlı programlama üzerinde yapılacak çok iş var. Alan hâlâ açık; bu nedenle gerçekten bu alandaki en üst düzey teknolojiyle bizzat uğraşmak istiyorsanız, denemek için doğru yer ve doğru zaman burasıdır.
-
IDE. Falcon uygulamalarının geliştirilmesi ve hata ayıklanması için bir IDE’ye ihtiyacımız var. Son derece ilginç bir araç, uygulamaların kendi betiklerini yönetmek için dahili olarak başlatabilecekleri gömülebilir bir IDE olurdu (oyun mod uygulamalarını düşünün, ama aynı zamanda özelleşmiş veri madenciliği araçlarını da). Falcon oldukça açık bir motora sahiptir ve bunu doğrudan ortama entegre etmek kolay olacaktır. IDE’yi beşinci sıraya koydum; çünkü dil bu arada diğer dört noktayı geliştirmezse bir IDE işe yaramaz. Ancak diğer dört nokta tatmin edici biçimde ilerlediğinde hazır bir IDE’ye sahip olmak gerçekten bir nimet olurdu.
Katılmak kolaydır – üzerinde çalışmak istediğiniz kodu SVN’imizden almanız (ya da kendi uzantınızı yazmak istiyorsanız Falcon + geliştirme dosyalarının tam kurulumunu yapıp iskelet modülü kurmanız) ve bir şeyler yapmanız yeterli. Sonra haber grubumuz, e‑posta ya da IRC üzerinden bize ses verin; aramıza katılmış olursunuz. Geliştiriciler, katkıları sürekli ve faydalı olursa katkıcı olarak katılabilir ve Komite’ye girebilirler.
Dili sürdürürken zor kararlarla karşılaştınız mı?
Hem evet hem hayır. Evet; çünkü geri dönüşü olmayan birçok nokta vardı ve bu nedenle bir şeyi diğerine tercih etmem gereken yerlerde kararlar zordu. Örneğin, durum bilgili makineler kurmak için kullanılan, eski Falcon dilinin sevimli bir özelliği olan durum bilgili fonksiyonlara desteği bırakmaya karar verdiğimde.
Durum bilgili makineler birçok bağlamda oldukça kullanışlıydı ve onları doğrudan destekleyen dil yapılarının olması ilginçti. Ancak her fonksiyona giriş ve çıkışın, bunun durum bilgili bir fonksiyon olup olmadığını kontrol etme gereği nedeniyle çok maliyetli olduğunu gözlemledik ve bu da bu yapıların terk edilmesine yol açtı. Dolayısıyla, bu tür kararlar “sertlik (metalurji)” anlamında zorlu olsa da, aldığım kararların hiçbiri alınması güç kararlar değildi.
Her karar derin bir teknik maliyet–fayda analizinden sonra alındı; “sertlik (metalurji)” arttıkça analiz de derinleşti. Bu nedenle, karar vermek için sağlam bir temele sahipken ve üzerinde çalışılacak somut kanıtlar ve veriler varken, her karar aslında kolaydı; çünkü ya tek uygulanabilir seçenekti ya da teknik açıdan en iyisiydi.
Geriye dönüp baktığınızda, dilin geliştirilmesinde değiştireceğiniz bir şey var mı?
Açık kaynak olmaya daha erken geçmek için daha fazla çaba gösterirdim. Başladığımda pazar zaten oldukça doluydu, bu yüzden çözümümün kendi uygulama alanlarında teknik olarak daha iyi olduğunu kanıtlayana kadar araştırmamın sonuçlarını kamuoyuna sunma konusunda biraz çekingen davrandım. Ancak bu, modüller gibi yan alanların gelişimini yavaşlattı. Geliştiriciler yalnızca bir probleme daha iyi bir yaklaşım nedeniyle değil, yeni bir araçla eğlenceli bir şeyler yapma fikriyle de çekilebilirlerdi. Açık kaynağın bu hazcı yönünü küçümsedim ve şimdi iç işlerin hepsiyle tek başıma ilgilenmek zorunda kalınca biraz nefesim daraldı. Bu yüzden bilgimi aktarmaya ve projeyi sürdürmek isteyen herkese yardım etmeye bu kadar hevesliyim.
Falcon’ın geleceğini nerede görüyorsunuz?
İyi bir betik dili olmakta. Ne kadar totolojik görünse de, aslında durum bu değil. Diğer birçok dil, hatta en önde gelenler bile, kapsamlarını aşırı büyüttü ve artık türsüz, ultra üst seviye, mantık odaklı betik dilleri için tam olarak amaçlanmamış alanlara girmeye çalışıyor.
Yeni sınırlar bulup onları aşmak gerektiği doğruysa, doğada önceden belirlenmişlik olduğu da doğrudur. Bir şeftali çekirdeğinden şeftali yetişir; bir gezegen pek çok şey olabilir ama asla bir yıldız olmaz.
Tasarımı abartarak evrimleşmiyorlar; yalnızca potansiyellerini seyreltiyorlar. Amacımız, hem esnek bir iç değişken mantık motoruna ihtiyaç duyan uygulamaların hizmetine sunulabilecek hem de doğrudan geliştiricilerin komutası altında kullanılabilecek, sürekli büyüyen bir üst seviye kontrol mantığı ve tasarım soyutlaması potansiyeli sağlamaktır; bunu da performans açısından makul bir maliyetle (diğer betik dillerine kıyasla değil, işleri sabit kodlu biçimde yapmaya kıyasla) gerçekleştirmektir.