Comentarii

Copiați linkul Citat răspuns

s-ludwig comentat 1 iunie 2014

În timpul dezvoltării, un sistem de urmărire a sistemului de fișiere ar putea fi utilizat pentru a monitoriza modificările fișierelor din șabloanele de dietă care alcătuiesc aplicația. Fiecare șablon de dietă, în loc să fie compilat static în aplicație, va fi apoi compilat ca o bibliotecă partajată separată/DLL și încărcat și descărcat dinamic, după cum este necesar.

Textul a fost actualizat cu succes, dar s-au întâlnit aceste erori:

etcimon comentat 1 iunie 2014

Ar putea fi posibil să aveți o bibliotecă separată pentru compilarea șabloanelor de dietă într-un format .d și generarea informațiilor de dub, astfel încât un proiect vibe.d să poată face referire la ele ca o dependență.?

s-ludwig comentat 1 iunie 2014

Acest lucru ar fi cu siguranță posibil (pur și simplu writeToFile („somefile.d”, dietStringParser! (.));), Dar nu ar rezolva această problemă specială, deoarece aplicația ar trebui totuși reluată și repornită în acest caz.

s-ludwig comentat 1 iunie 2014

Dacă nu vrei să folosești DUB doar ca instrument pentru construirea bibliotecii dinamice. În acest caz, suportul discutat pentru pachetele cu un singur fișier ar fi util.

etcimon comentat 1 iunie 2014

Văd unde ajungi. Abordarea mea a fost aceea de a face repornirea serverului mai puțin dăunătoare, dar reîncărcarea șabloanelor de dietă ca obiect partajat în timpul rulării ar putea face bine. În proiectarea mea actuală a unui manager de configurare, mă întreb dacă serverul ar putea fi repornit fără a închide procesele (pentru a reconstrui rute și ascultători).

MartinNowak comentat 4 iunie 2014

Voi încerca să lucrez la asta, deoarece este o vitrină bună pentru bibliotecile partajate.
Ce înseamnă în timpul dezvoltării și ce proces ar monitoriza sistemul de fișiere, dub?
Cealaltă problemă este că randarea folosește șabloane, deci este puțin dificil să transmiteți argumentele printr-un indicator de funcție.

s-ludwig comentat 5 iunie 2014

Cu siguranță ar fi minunat, de fapt am auzit acest argument de nenumărate ori, că D a fost rău din cauza acestei creșteri a timpului de răspuns și că oamenii ar prefera să rămână cu limbajul lor interpretat dinamic.

„În timpul dezvoltării”, aș spune, ar trebui să însemne doar un fel de switch opt-in, probabil folosind -version =. Utilizarea -debug = ar avea avantajul că ar putea fi specificată direct pe linia de comandă DUB, dar asta nu ar fi bineînțeles foarte curat semantic.

Pentru monitorizarea sistemului de fișiere, watchDirectory * ar putea fi utilizat direct din cadrul procesului vibe.d. Construirea șabloanelor individuale se poate face folosind DUB prin generarea unui pachet fals cu proiectul vibe.d ca dependență pentru a obține toate setările de construire.

În ceea ce privește problema șablonului, chiar dacă modifică ușor semantica, cred că utilizarea unui parametru Variant [] pentru a transmite argumentele, similar cu ceea ce se făcea pentru renderCompat, ar trebui să fie de obicei bine.

* În prezent, acest lucru este implementat doar pentru driverul win32, dar aș putea investi ceva timp pentru ca acesta să ruleze și în driverul libevent.

zhaopuming comentat 29 iunie 2014

Deci, acest mecanism este foarte asemănător cu mecanismul de replică al lui Martin:-) Sperăm că într-o zi vom putea avea dub repl la fel ca lein repl în Clojure.

Și pentru un caz mai general, putem face acest mecanism să funcționeze pentru alte părți ale aplicației, astfel încât, atunci când fiecare parte este modificată, va fi compilată la cald și reîncărcată.

Despre couse, înainte de aceasta trebuie să definim o parte sau o unitate funcțională. Ca referință, vert.x are un concept de „vârf” care încapsulează o unitate funcțională și fiecare comunică între ele printr-un Eventbus, utilizând mesaje. Acest lucru se comportă foarte mult ca modelul de actor al lui Erlang/Scala. Avem deja toate instrumentele pentru suportul modelului de actor în vibrație, așa că, odată ce îl transformăm într-un model mai oficial, putem face această recompilare/reîncărcare la cald pe acești actori/unități. Atunci dieta temlată ar fi doar un caz special al unui actor (care se numește direct).

s-ludwig comentat 29 iunie 2014

Ceea ce mi-e teamă este că generalizarea acestui lucru la modulele D obișnuite face prea ușor pentru oameni să pășească pe propriile picioare, de exemplu, schimbând aspectul datelor de anumite tipuri. Java are mult mai multe posibilități de a detecta astfel de situații datorită reflectării detaliate a timpului de rulare, dar o aplicație D fie ar fi doar blocată, fie ar produce o ieșire greșită.

zhaopuming comentat 30 iunie 2014

Vrei să spui aspectul datelor pentru mesaje? poate avem nevoie de o altă unitate în loc de module D, care este o unitate de cod sursă. Modulul vert.x este ca un plugin și fiecare modul are propriul proiect, modulele comunicând numai prin mesaje (JSON). Cadrul de joc are o abordare similară. Acestea sunt sisteme de plugin-uri de execuție pentru reîncărcare la cald.

s-ludwig comentat 30 iunie 2014

Problema la care mă gândeam este când permiteți unei componente să își refolosească vechea memorie după ce a fost reîncărcată, ceea ce ar fi cea mai eficientă abordare, dar ar fi predispus la erori de corupție a datelor silențioase atunci când, de exemplu, un aspect struct s-a schimbat reîncărcați. Dacă, pe de altă parte, componenta ar trebui să înceapă de fiecare dată cu o stare curată, problema respectivă ar dispărea și transmiterea mesajelor ar trebui să fie mai bine *. Cu toate acestea, acest lucru ar însemna că componentele nu pot depinde de starea reciprocă, ceea ce deschide o mulțime de potențial pentru probleme de nivel înalt.

Poate o abordare hibridă, în care fiecare componentă are șansa de a serializa în mod explicit starea sa înainte de a coborî și apoi obține acea blob serializat de date când pornește data viitoare pentru a-și restabili starea. Încă lasă potențialul unei stări pierdute în liniște, dar cel puțin permite posibilitatea de a face o reîncărcare fără probleme.

BTW, există Cmsed by @rikkimax, care acceptă reîncărcarea componentelor. Nu sunt sigur dacă folosește vreo formă de transmitere a mesajelor sau un alt machanism în timpul rulării sau pur și simplu permite partajarea memoriei între componente.

În general, cred că arhitectural ar fi cea mai bună soluție pentru a menține această funcționalitate într-un cadru separat, fie unul de nivel superior precum Cmsed, fie unul complet generic (unul care este compatibil cu vibe.d, desigur) - pentru că ar trebui să fie posibil să îl separați și să evitați fluirea caracteristicilor în vibe.d în sine (există deja o mulțime de funcționalități care ar fi mai bine în Phobos, de exemplu). Reîncărcarea șabloanelor, pe de altă parte, ar fi doar un ajutor pentru dezvoltare și nu ar face parte din arhitectura generală.

* Dacă componenta A importă un modul din componenta B care definește o struct și apoi această structură este trimisă de la componenta A la componenta B, este încă posibil să obțineți aspecte de date incompatibile dacă A decide să schimbe aspectul struct după o reîncărcare. Deci, pentru a atenua acest lucru, ar fi necesar să urmăriți dependențele dintre componente și să reîncărcați simultan toate componentele afectate.

rikkimax comentat 30 iunie 2014

Cmsed nu acceptă încă reîncărcarea șabloanelor ext. în timpul rulării încă. Acest lucru este în mare parte din starea cadrului meu de actori Dakka. Deocamdată nu poate apela metode pe alte noduri. Dar aceasta nu este următoarea mea țintă, ci cealaltă. Actualul este actori singleton, da îngrozitor, dar hey grozav pentru clasele de controlor.

Politicile pe care urma să le folosesc erau destul de simple:

  • Actualizări șablon:
    • Cod regenerat
  • După codul regenerat pentru schimbarea șabloanelor sau rutelor
    • Recompilați șabloanele corespunzătoare
    • Opriți nodurile anterioare
    • Porniți noi noduri

  • Cu privire la modificările aduse modelelor de date
    • Recompilați toate rutele

Practic nu ar trebui să includă automat în compilație niciun cod care nu este necesar. Utilizați ruta ca fiind fișierul sursă care trebuie compilat, iar restul urmează ca să spunem așa. Dar adăugați căile de import corespunzătoare.

Acum acest lucru nu rezolvă problema dependenței. Metoda mea pentru acest lucru este de a avea un director prin acesta, care permite în esență un singur fișier binar de dependență și un director cu toate fișierele de import.
Șabloanele ar trebui să fie generate și apoi angajate în controlul versiunilor, astfel încât, dacă ați avut un pachet care oferă doar șabloane, atunci acestea vor fi disponibile pentru rute dacă se află în acel pachet de dependență.

Sunt îngrijorat de modul în care acest lucru va rezista la sfârșitul routerelor și îl împing pe atâtea procese diferite de solicitat. Dar cel puțin acest lucru este doar pentru testare și nu pentru utilizarea la nivel de producție.

Dar chiar acum aceasta este pur teorie. Sunt personal deschis să fac acest lucru mai puțin specific, dacă asta doriți voi.

zhaopuming comentat 30 iunie 2014

@ s-ludwig Sunt de acord cu gândurile tale despre separarea vibe.d de cadrul componentelor (cum ar fi akka). Cmsed arată interesant:)

Despre aspectul memoriei, există o abordare care să difere aspectele de date ale fiecărei modificări? Dar asta ar deveni prea complicat. În JVM pe care îl cunosc mai mult, hotswap-ul este o problemă foarte complicată care duce la un produs comercial, JRebel. Nu aș sugera să mergem atât de departe:-)

zhaopuming comentat 30 iunie 2014

@rikkimax Dakka folosește aceeași tehnică cu Akka pentru a trimite mesaje între actori? ca:

sau faceți ceva magie de timp pentru a face actor RPC la fel ca apelurile funcționale?

sau chiar mai bine, utilizați tehnici similare cu vibe.d, făcând apelurile asincronizate să arate ca sincronizate?

rikkimax comentat 30 iunie 2014

@zhaopuming Multă magie CTFE. Cu siguranță îmi plac lucrurile astea.

Ignorând faptul că până acum apelul de metodă la distanță nu este implementat (dar onChildError este un caz special) iată un exemplu de cod pe care îl folosesc pentru a testa. Rețineți că poate crea o instanță MyActorA la nivel local. Motivul pentru care nu este, se datorează caracteristicii capabilităților.
În esență, fiecare clasă are o listă de capabilități pe care le necesită pentru a fi utilizabile. Fiecare nod la pornire își poate înregistra capacitățile. Deci, pentru testare, este destul de ușor să îl separați.
https://github.com/rikkimax/dakka/blob/b4b9611e165c33ebdcb8afffbb3268775d9b3f2f/source/app.d

Acesta va accepta apelurile asincronizate și sincronizate, în funcție de dacă are o valoare returnată. Adică ref, out sau un tip return.

etcimon comentat 30 iunie 2014

dar ar fi predispus la erori silențioase de corupție a datelor atunci când, de exemplu, un aspect struct s-a schimbat după o reîncărcare.

Există, de asemenea, opțiunea de extragere frontală a datelor direct din unele stocări (cache?) Pentru a forța un API stabil pe acesta. Mă aplec mai mult către asta, dar trimiterea de date serializate ar putea fi, de asemenea, un tip stabil de opțiune API.

s-ludwig comentat 30 iunie 2014

Despre aspectul memoriei, există o abordare care să difere aspectele de date ale fiecărei modificări?

O idee ar fi crearea unei „amprente digitale” unice de fiecare tip care să identifice în mod unic aspectul datelor și să o trimită întotdeauna împreună cu datele reale. Receptorul ar putea apoi cel puțin să detecteze o nepotrivire și să efectueze o acțiune adecvată.

etcimon comentat 30 iunie 2014

Sau compilatorul de diete ar putea găsi modulele/fișierele în care sunt definite tipurile și le poate detecta modificările/le poate importa automat.

etcimon comentat 30 iunie 2014

Pe de altă parte, pentru iterații frecvente, mă gândesc că ar fi o idee bună să îmbunătățiți serveStaticFiles într-un serveDynamicFiles, pentru a putea analiza-înlocui un document html cu conținut care conține comenzi precum și unde $ 1 poate fi extras din adresa din routerul vibe.d sau, dintr-un magazin de valori-cheie, sau chiar pentru ACL. Această restricție a API poate servi la dezvoltarea unei interfețe rapide și dinamice cu vibe.d folosind fișiere html, modele javascript și serializare/deserializare json.

Sistemul de fișiere se poate dovedi o bază de date de documente excelentă vs. un DLL sau binar, Javascript este excelent pentru interactivitatea interfeței cu utilizatorul, iar JSON este un conector back-end excelent.

Pentru depanare, utilizarea unui html ar putea fi utilizată atunci când proiectați o interfață cu vibe.d ca backend (lucrurile din depanare apar într-un browser când faceți dublu clic pe fișierul html, dar nu este livrat de serverul vibe.d decât dacă adresa URL este interogată cu un steag specific)

de exemplu. Pentru redactarea unei postări de blog, a ar permite utilizarea practic a oricărei aplicații HTML WYSIWYG.

De asemenea, este mai ușor pentru un CMS să interfețe cu fișiere HTML cu un API restricționat, decât să interfețe cu un format de șablonare dinamic cu cod D (greu de analizat) în interiorul acestuia.

În cele din urmă, este mai ușor în acest fel pentru ORICE dezvoltator front-end din întreaga lume să implementeze șabloane terță parte, cum ar fi cele de pe http://themeforest.net . copy-paste?

MartinNowak comentat 17 iulie 2014

Cealaltă problemă este că randarea folosește șabloane, deci este puțin dificil să transmiteți argumentele printr-un indicator de funcție.

Problema principală este că argumentele alias sunt accesibile numai în funcțiile imbricate,
dar nu este posibil să compilați o funcție imbricată fără părinți (adică site-ul de apelare a randării).
Deci, fie putem reveni la logică, astfel încât șablonul de redare să apeleze înapoi pentru a fi hrăniți cu argumentele. Nu sunt sigur cum să implementăm exact acest lucru.
Sau încercăm să trecem toate argumentele sub formă de copii sau prin ref. Nu pare posibil să treceți Tipuri sau aliasuri la alte simboluri în acest fel.

s-ludwig comentat 17 iulie 2014

Aș face-o așa cum o face renderCompat și a transmite toate valorile ca o variantă [], care ar evita problemele în care altfel ar fi necesar un tip privat pentru a defini o semnătură de funcție internă (atunci când treci prin ref, de exemplu ). Dacă sunt trecute tipuri sau alte tipuri de aliasuri, codul ar putea pur și simplu să emită o notificare pragmatică și să revină la compilarea obișnuită.

MartinNowak comentat 17 iulie 2014

Aș face-o așa cum o face renderCompat și ați transmite toate valorile ca variantă []

Varianta ar evita cel puțin necesitatea de a importa cea mai mare parte a proiectului și vibe.d.

Dacă sunt trecute tipuri sau alte tipuri de aliasuri, codul ar putea pur și simplu să emită o notificare pragmatică și să revină la compilarea obișnuită.

Da, am ajuns și eu acolo, totuși jonglând cu alte idei.

Rămân două întrebări.

rikkimax comentat 24 iulie 2014

Am construit împachetări în jurul HTTPServerRequest și HTTPResponse (HTTPServerResponse a fost prea specific) pe Dakka https://github.com/rikkimax/dakka/blob/master/source/vibe-d_wrappers/dakka/vibe/client.d
Deci, teoretic, dacă ați putea configura corect Dakka și routerele de la ambele capete, ar fi posibil să îl utilizați pentru reîncărcarea în direct a rutelor ext.

De asemenea, pentru referință: https://github.com/rikkimax/skeleton https://github.com/rikkimax/livereload (livereload se ocupă de recompilarea și reluarea efectivă a nodurilor Dakka).

MartinNowak comentat 28 iulie 2014

M-am lăudat puțin cu asta și iată concluziile mele.

Încă nu am găsit o modalitate de a transmite date din aplicație către un partajat
bibliotecă fără a restricționa sever ceea ce este posibil cu o dietă
șablon.

  • Varianta nu permite nici măcar accesarea câmpurilor UDT-urilor și, astfel, nu acceptă intervale. Am putea încerca să venim cu o variantă mai bună și să folosim inputRangeObject.
  • Trecerea tipurilor reale ori de câte ori este posibil (trebuie să fie publică și non-Voldemort) ar rezolva multe probleme. Ar fi necesar să importați aplicația atunci când recompilați șablonul. Acest lucru ar fi aproape la fel de lent ca recompilarea întregii aplicații și necesită înșelăciune de conectare (--export-dynamic, conectarea șablonului la aplicație).
  • O altă opțiune ar fi recompilarea întregii aplicații, încărcarea acesteia ca o bibliotecă partajată și eliminarea funcției de redare.
    Acest lucru ar scăpa de toate problemele de trecere de tip.

Ultimele două soluții au dezavantajul sever, pe care le necesită pentru a importa aplicația.
Să ne recapitulăm obiectivele, vrem să accelerăm dezvoltarea recompilând automat șabloanele de dietă ori de câte ori se schimbă.
Așa cum am spus mai devreme, un filewatcher este drăguț, dar destul de banal de realizat cu un script ca acesta.

Deși funcționează destul de bine, trebuie să ajungem la timpul de 5s pentru a ajunge la aproximativ 1s.

Să o descompunem pentru un proiect simplu vibe.d (vibe.d/exemple/dietă).

recompilați

Începând cu versiunile 4.3 trebuie să rulezi dub build cu un libvibe-d.a pre-construit, după schimbarea șablonului diet.dt, linkerul are un nivel surprinzător de mare de 2.3. Ei bine, binarul final este de 15 milioane, iar libvibe-d.a este de 94 de milioane, deci linkerul are ceva de făcut, dar ld.gold poate face același lucru de 5 ori mai repede.
Devine și mai bun atunci când faceți legătura cu un libvibe-d.so partajat, deoarece linkerul nu trebuie să copieze codul în binar.
Acum, binarul final este de numai 940K, în timp ce libvibe-d.so are 13M, nu sunt sigur de unde provine micșorarea 94M -> 13M.

Reducerea timpului necesar pentru a compila aplicația va fi puțin mai dificilă. Pentru construcțiile de depanare, compilatorul își petrece o mare parte din timpul său de citire și analiză a tuturor fișierelor sursă importate.
Deci, ceea ce ar ajuta este reducerea numărului de module care trebuie deschise și procesate.
Iată o listă cu toate dependențele pentru acea mică aplicație. Cele 220 de fișiere (236626 LOC, 8 MB) aruncă o lumină diferită asupra 0.87s necesare pentru a compila aplicația.
Ar fi frumos să obținem importuri statice leneșe în D la un moment dat, dar până atunci
utilizarea importurilor locale este cea mai bună opțiune (alături de a nu importa nimic) de evitat
importuri inutile în cod client. De exemplu, atunci când recompilați o aplicație vibe.d, compilatorul
nu ar trebui să analizeze niciun antet openssl sau libevent2, deoarece acestea sunt
dependențe de vibe.d, nu de aplicație. De asemenea, aplicația nu folosește niciun cod std.datetime, dar modulul este încă analizat la fiecare recompilare.

Ultima parte importantă este cheltuirea prin dub în sine, care încarcă metadatele și verificările
versiuni git, dependențe și upgrade-uri. Deși ar putea exista un potențial
pentru a accelera acest lucru, ar putea fi în valoare de a integra scriptul de inotificare de mai sus în
dub în sine, astfel încât apelarea dub run --auto-reconstruire ar permite reconstruirea
aplicație din mers cu mult mai puțină cheltuială.

În general, cred că putem ajunge la 1s chiar și pentru aplicații de dimensiuni reale.
Această abordare merită mult mai mult IMO decât utilizarea unor șabloane de dietă amputate.