Hvorfor aRts ikke bruger DCOP

Eftersom KDE droppede CORBA fuldstændigt, og i stedet bruger DCOP overalt, opstår naturligvis spørgsmålet hvorfor ikke aRts også gør det. Trods alt findes DCOP-understøttelse i KApplication, er godt vedligeholdt, forventes at integreres udmærket med libICE, og alt muligt andet.

Eftersom der (muligvis) vil være mange som spørger om det virkelig er nødvendigt at have MCOP foruden DCOP, så er svaret her. Misforstå mig ikke, jeg forsøger ikke at sige at “DCOP er dårlig”. Jeg forsøger kun at sige at “DCOP ikke er den rette løsning for aRts” (mens det er en god løsning for andre ting).

Først skal man forstå nøjagtigt hvad DCOP blev skrevet for. Oprettet på to dage under mødet KDE-TWO, var det hensigten at være så enkel som muligt, en virkelig “letvægts” kommunikationsprotokol. I særdeleshed udelod implementationen alt som kunne indebære kompleksitet, for eksempel et fuldstændigt begreb om hvordan datatyper skal kodes.

Selvom DCOP ikke bryder sig om visse ting (som hvordan man sender en streng på en netværkstransparent måde), skal dette gøres. Så alt som DCOP ikke gør overlades til Qt™ i KDE-programmerne som bruger DCOP i dag. Dette er i hovedsagen typehåndtering (som bruger Qt™'s serialiseringsoperator).

DCOP er en minimal protokol som gør det helt muligt for KDE-programmer at sende enkle meddelelser såsom “åbn et vindue som peger på http://www.kde.org” eller “dine indstillinger er ændrede”. Inde i aRts fokuseres imidlertid på andre ting.

Idéen er at små indstiksmoduler i aRts skal kommunikere med sådanne datastrukturer som “midi-begivenheder” og “sangpositionspegere” og “flydegrafer”.

Dette er komplekse datatyper, som skal sendes mellem forskellige objekter, og håndteres som strømme, eller parametre. MCOP sørger for et typebegreb til at definere komplekse datatyper ud fra enklere (ligesom struct'er og felter i C++). DCOP bryder sig ikke om typer i det hele taget, så dette problem skulle overlades til programmøren, såsom at skrive C++ klasser for typerne, og sikre sig at de kan serialisere på en rigtig måde (for eksempel understøttelse for Qt™'s serialiseringsoperator).

Men på den måde ville de ikke være tilgængelige for noget andet end direkte kodning i C++. I særdeleshed ville man ikke kunne oprette et scriptsprog som ville kunne kende til alle typer som et indstiksmodul kan gøre tilgængelige, eftersom de ikke ville være selvbeskrivende.

Samme argument gælder også grænseflader i stor udstrækning. DCOP-objekter gør ikke deres forhold, arvhierarkier, osv. tilgængelige. Hvis man ville skrive en objektbladrer som ville vise “hvilke egenskaber har dette objekt”, ville det mislykkes.

Selvom Matthias fortalte mig at man har en speciel funktion “functions” for hvert objekt som informerer om hvilke metoder som objektet understøtter, udelader dette ting såsom egenskaber, strømme og arvrelationer.

Dette gør at programmer som aRts-builder ikke ville fungere overhovedet. Men husk, det var ikke meningen at DCOP skulle være en objektmodel (eftersom Qt™ allerede har en med moc og lignende), heller ikke være noget som CORBA, men sørge for kommunikation mellem programmer.

Årsagen til at MCOP overhovedet findes er at den skal virke godt med strømme mellem objekter. aRts bruger mange små indstiksmoduler, som forbindes med strømme. CORBA-versionen af aRts var tvunget til at introducere en besværlig opdeling mellem “SynthModule-objekt”, som var de interne arbejdsmoduler som oprettede strømme, og “CORBA-grænseflade”, som var noget eksternt.

Meget kode bekymrede sig om at opnå at vekselvirkningen mellem “SynthModule-objekt” og “CORBA-grænsefladen” så naturlig ud, men den gjorde det aldrig, eftersom CORBA ikke kendte til noget om strømme overhovedet. MCOP gør det. Kig på koden (noget i stil med simplesoundserver_impl.cc). Adskilligt bedre! Strømme kan deklareres i modulernes grænseflade, og implementeres på en måde som ser naturlig ud.

Man kan ikke benægte det. En af grunderne til at jeg skrev MCOP var hurtighed. Her er et argument for at MCOP definitivt vil være hurtigere end DCOP (selv uden at angive tal).

Et kald i MCOP vil have et hoved med seks “long”. Det vil sige:

Efter dette følger parametrene. Bemærk at afkode dette går ekstremt hurtigt. Man kan bruge tabelopslag for at finde afkodningsfunktionen for objektet og metoden, hvilket betyder at kompleksiteten er O(1) [det tager lige lang tid uafhængig af hvor mange objekter som findes, og hvor mange funktioner som findes].

Hvis dette sammenlignes med DCOP, ser du at der er i det mindste

Disse er meget sværere at afkode, eftersom man skal tolke strengen, lede efter funktionen, osv.

Med DCOP sendes alle kald gennem en server (DCOPServer). Det betyder at håndteringen af et synkront kald ser sådan her ud:

I MCOP ser samme kald ud sådan her ud:

Antag at begge er rigtigt implementerede. MCOP's ikke-hierarkiske strategi bør være hurtigere med en faktor to, end DCOP's mand i midten-strategi. Bemærk dog at der naturligvis var grunde til at vælge DCOP-strategien, som er at hvis du har 20 programmer som kører, og hvert program taler med hvert andet program, så behøver man 20 forbindelser med DCOP, og 200 med MCOP. I tilfældet med multimedie er det dog ikke meningen at dette skal være et almindeligt scenario.

Jeg forsøgte at sammenligne MCOP og DCOP, med at gøre et kald som lægger to tal sammen. Jeg ændrede testdcop for at opnå dette. Testen var dog måske ikke præcis på DCOP-siden. Jeg kaldte metoden i samme proces som gjorde kaldet til DCOP, og jeg vidste ikke hvordan man blev af med en fejlsøgningsmeddelelse, så jeg brugte omdirigering af udskriften.

Testen brugte kun et objekt og en funktion, så resultaterne for DCOP forventes at blive mindre med flere objekt og funktioner, mens resultaterne for MCOP bør forblive de samme. Desuden var dcopserver-processen ikke forbundet til andre programmer, og det er måske sådan at hvis mange programmer er forbundne så mindskes overføringsydelsen.

Resultatet jeg fik var at mens DCOP fik lidt mere end 2000 kald pr sekund, fik MCOP noget mere end 8000 kald pr sekund. Det betyder en faktor 4. Jeg véd at MCOP ikke er afstemt for den maksimalt mulige hastighed endnu. (Som sammenligning: CORBA, med mico-implementationen, klarer noget mellem 1000 og 1500 kald pr sekund).

Hvis du vil have “rigtigere” data, så overvej at skrive et lille måleprogram for DCOP og send det til mig.

CORBA havde den behagelige funktion at man kunne bruge objekter som man havde implementeret, som “separat serverproces”, eller som “bibliotek”. Man kunne bruge samme kode for at gøre det, og CORBA bestemte transparent hvad der skulle gøres. Med DCOP, er det ikke rigtigt meningen, og så vidt jeg ved ikke egentlig muligt.

MCOP på den anden siden skulle understøtte dette fra begyndelsen. Så man kan køre en effekt inde i artsd. Men for en bølgeformseditor kan man også vælge at køre samme effekt inde i processen.

Mens DCOP i hovedsagen er en måde at kommunikere mellem programmer, er MCOP også en måde at kommunikere inde i programmerne. Især for multimediestrømme er dette vigtigt (eftersom man kan køre flere MCOP-objekter parallelt, for at løse en multimediaopgave i et program).

Selvom MCOP ikke gør det for øjeblikket, er mulighederne åbne for at implementere servicekvalitetsfunktioner. Noget i stil med at “den MIDI-begivenhed er virkelig rigtigt vigtig, sammenlignet med dette kald”. Eller noget som “skal være der til tiden”.

På den anden siden kan strømoverførsler integreres i MCOP-protokollen på en behagelig måde, og kombineres med QoS-ting. Under forudsætning af at protokollen kan ændres, bør MCOP strømoverførsler ikke blive virkelig langsommere end en konventionel TCP-strøm, men de vil være enklere og mere konsekvente at bruge.

Der er ingen grund til at basere mellemprogrammer for multimedie på Qt™. Ved at bestemme sig for det, og bruge alle de behagelige Qt™-strømme og andre ting, kan det let føre til at mellemprogrammer kun bliver en sag for Qt™-(eller i virkeligheden kun KDE). Jeg mener at hvis jeg nogensinde ser at GNOME også bruger DCOP, eller noget lignende, er det naturligvis beviset for at jeg har taget fejl.

Selvom jeg ved at DCOP i grunden ikke kender til de datatyper som den sender, så man ville kunne bruge DCOP uden Qt™, se hvordan den bruges i daglig KDE-brug: man sender typer rundt såsom QString, QRect, QPixmap, QCString, .... Disse bruger Qt™'s-serialisering. Så hvis nogen vælger at understøtte DCOP i et GNOME-program, skal han enten angive at han bruger QString,... typer (selvom han ikke gør det), og emulere måden som Qt™ bruger til strømme, eller også skulle han sende andre streng-, pixmap- og rect-typer rundt, og på den måde alligevel ikke kunne virke sammen med KDE-programmer.

Nå, under alle omstændigheder var det altid meningen at aRts var beregnet til at virke med eller uden KDE, med eller uden Qt™, med eller uden X11, og måske til og med med eller uden Linux® (og jeg har ikke engang indvendinger mod personer som tilretter den til operativsystemer som ikke er frie).

Min indstilling er at komponenter som ikke indgår i en grafisk grænseflade skal skrives uafhængig af denne, for at muliggøre at de deles mellem et større antal udviklere (og brugere).

Jeg indser at brug af to IPC-protokoller kan være ubekvemt. Desuden er begge to ikke standardiserede. Af de grunde som blev angivet ovenfor er det ikke muligt at skifte til DCOP. Hvis der er betydeligt interesse i at finde en måde at forene de to, så kan vi forsøge. Vi ville til og med kunne forsøge at få MCOP til at tale IIOP, når skulle vi have en CORBA ORB ;).

Jeg talte en del med Matthias Ettrich om fremtiden med de to protokoller, og vi fandt mange måde som tingene kunne gå videre. MCOP ville for eksempel kunne håndtere meddelelsekommunikationen i DCOP, og på denne måde få protokollerne nærmere til hinanden

Nogle mulige løsninger ville være:

Den værste mulighed er måske ikke at bruge hver protokol til alt det som den var beregnet til (der er nogle store forskelle i målene med deres konstruktion), og ikke forsøge slå dem sammen til et.