Vinnaren i pepparkakshustävlingen!
2017-08-09, 10:01
  #73
Moderator
RostigHinks avatar
Citat:
Ursprungligen postat av DrSvenne
Alltså man kan ställa till med kaos om man gör lite pekararitmetik, tex

void *ptr = (void *) malloc(...);

use ptr

free(ptr + X);

X ska vara så stor att man hamnar utanför allokerbart utrymme
Man kan också åstadkomma tokerier med free i en segmenterad arkitektur om man lägger på för mycket i offset,
Gamla compilers varnade inte för sådana tramserier, nu vet jag inte vad som blir följden, men man kan ju
stöka till det.
När C++11 var klart så kunde man börja använda smartpekarna. Dessa uppför sig som vanliga pekare genom att operator* och operator-> är överlagrade. Det fina är dock att man inte kan köra pointer arithmetics på dem samt att de ser till att objektet de pekar på förstörs när pekaren antingen förstörs eller går ur scope. Med vanliga pekare får man själv se till att förstöra objektet och har man då flyttat pekaren...
Även operator bool är överlagrad så gamla C-rävar känner sig hemma med
Kod:
shared_ptr<int> foo(new int(42));
...
if (foo) {
...
}
Citat:
Ursprungligen postat av DrSvenne
Protected Mode[/b] är ju värdefullt genom att man kan relokera minnesinnehållet till en annan adress och inte behöva ändra på deskriptorn, så i teorin så kan man undvika fragmentering helt förutsatt att man har tillräckligt med swaputrymme el dyl.

I Real Mode däremot så kan man råka ställa till med allsköns kaos om man inte vet vad man gör.
Men så har vi den där lilla processen i hörnet som allokerat en sketen liten struct med 2 integers i statiskt. Vad gör man då? Bra kodningsregler kan förslagsvis säga att sådana statiska objekt ska läggas på processtacken.
__________________
Senast redigerad av RostigHink 2017-08-09 kl. 10:21.
Citera
2017-08-09, 10:24
  #74
Medlem
Citat:
Ursprungligen postat av MeanME
Bara för att språken kompileras till binärer betyder just inget mer än det.
Det saknar egentligen relevans.
Vad som betyder något är hur dessa binärer kommer ut.
Hur minneshantering och processorutnyttjande sker.
Hur garbagehanteringen sker.
Problemet med C är ju att minnet över tid fragmenteras.
Det finns ju tester där Java med sin garbagekontroll smäller både C och C++ på fingrarna.

Så vill man vara säker finns bara en sak att göra om hastigheten är av yttersta vikt.
Skriv en modul i C och en i C++ och testa.
Skriv "fulkod" och testa igen om det funkar bättre.
Dvs flippa loopar mm och se om det gör ett bättre jobb än kompilatorn.
Finns mycket hysch man kan hitta på med C och C++ för att få fart på det hela.
Så testa igen, och igen och igen...
Kolla på någon optimeringssida och titta på vad du kan göra.
Något annat finns det faktiskt inte att göra.

Eller så skiter man i de där millisekunderna och tar det onda med det goda för den lösningen man valt. Blir sällan optimalt men man måste inte alltid producera monsterhack, ibland är utvecklingstiden och umgänge med nära och kära betydligt viktigare än att optimera program in i absurdum.

Så jag vet inte varför performance kom in i bilden, det är en annan diskussion.

Ett språk är inte mer maskinära för att en kompilator genererar mer effektiv maskinkod eller de har ett bättre optimerat standardbibliotek etc.

Jag ville bara poängtera att ett programmeringsspråk inte avgör hur maskinära något är och att alla språk faktiskt kan kompileras till maskinkod.
Citera
2017-08-09, 13:31
  #75
Medlem
Citat:
Ursprungligen postat av EvulTomteFar
Så jag vet inte varför performance kom in i bilden, det är en annan diskussion.

Ett språk är inte mer maskinära för att en kompilator genererar mer effektiv maskinkod eller de har ett bättre optimerat standardbibliotek etc.

Jag ville bara poängtera att ett programmeringsspråk inte avgör hur maskinära något är och att alla språk faktiskt kan kompileras till maskinkod.
Jo, ett programmeringsspråk avgör högeligen hur maskinnära någonting är.

Maskinnära innebär t ex ett behov av att kunna arbeta mot absoluta adresser, samt att kunna hugga "events" från hårdvaran - dvs interrupt, traps, exceptions, ... Vidare så finns ofta behov av att kunna garantera ordning och timing för vissa operationer - t ex att två minnesceller måste läsas i viss ordning eller att inget interrupt får hoppa in mellan de två accesserna.

Alla riktiga språk är Turing-kompletta dvs du kan lösa godtycklig algoritm med mer eller mindre komplicerad kod. Men för att vara hårdvarunära måste språket ha ett antal attribut mm som gör att utvecklaren inte bara kan tala om vad som skall utföras utan även kan instruera om de specifika kraven som finns på hur jobbet skall göras.

Med ett språk som har kapacitet att vara maskinnära går det t ex att skapa strukturer som man kan överlagra över hårdvara och få de individuella fälten att mappa 1:1 med motsvarande register i t ex en UART. Och ett antal processorer har även koncept med multipla minnesrymder. Vanliga x86 t ex körs numera vanligen fullt minnesmappad - men den har även in/out som är instruktioner som jobbar i en helt annan adressrymd. Tar du 8051 så blir det ännu mer spännande - CODE, IDATA, EDATA, PDATA, ... samt behovet av att kunna skapa enbitars variabler.

Ett språk anpassat för lågnivåbruk tillåter dig att skriva en stor del - i princip allt utom kanske startup-koden - i det valda språket. Ett sämre anpassat språk blir däremot beroende av att någon tar fram en hel bunt med library-funktioner att anropa för att därefter via assembler (eller kompilerad C-kod) utföra det önskade uppdraget.

Skriver jag en funktion i ett språk som redan klarar lågnivå så kan jag dessutom ange att jag vill få funktionen inlinad. Lättare sagt än gjort att få t ex lisp att inline-expandera ett antal assemblerinstruktioner för att göra någon atomisk read/modify/write eller liknande på en "magisk" variabel i hårdvaran.
Citera
2017-08-09, 20:10
  #76
Medlem
Citat:
Ursprungligen postat av EvulTomteFar
Så jag vet inte varför performance kom in i bilden, det är en annan diskussion.

Ett språk är inte mer maskinära för att en kompilator genererar mer effektiv maskinkod eller de har ett bättre optimerat standardbibliotek etc.

Jag ville bara poängtera att ett programmeringsspråk inte avgör hur maskinära något är och att alla språk faktiskt kan kompileras till maskinkod.
Det fetstilta håller jag inte med om.

Ett helt statiskt språk som C går alltid att kompilera till 100%, men sedan sker en gradvis övergång där mindre och mindre går att kompilera ju dynamiskare språken blir.

Java går t.ex. fortfarande att kompilera, men inte optimera vid kompileringstillfället därför att den faktiska implementation fastställs först vid klassladdningen. Språket kräver jit-optimering för att vara effektivt, vilket innebär att en del av kompileringsarbetet skjuts upp till exekveringen.

Python är så dynamiskt att kompilatorn inte kan göra mer än att mekaniskt översätta koden till byte-kod som går fortare att ladda. Kompilatorns viktigaste uppgift blir att utföra en syntaxkontroll av källkoden.

I helt dynamiska språk som shell-script går det inte ens att utföra syntax-kontroll utan att lösa halt-problemet, än mindre att kompilera koden.

Ett maskinnära språk bör både gå att kompilera statiskt och använda en maskinmodell som avbildar målplattformens faktiska hårdvara. Java eoch C# är exempel som inte uppfyller något av kraven.
Citera
2017-08-09, 21:59
  #77
Medlem
Citat:
Ursprungligen postat av cellplast
Alla riktiga språk är Turing-kompletta dvs du kan lösa godtycklig algoritm med mer eller mindre komplicerad kod. Men för att vara hårdvarunära måste språket ha ett antal attribut mm som gör att utvecklaren inte bara kan tala om vad som skall utföras utan även kan instruera om de specifika kraven som finns på hur jobbet skall göras.

Man gjorde ju förr viss skillnad emellan högnivå resp lågnivå om språket hade definierat flyttalsoperationer eller inte. Det fanns ju tidigt sådana språk som inte kunde hantera flyttal alls . Tex ett 16-bitars flyttal är ganska värdelöst att använda. Eftersom för få bittar finns till användningen, precisionen blir helkass I somliga "högnivåspråk" var flyttal inte så väl definierat där man inte fick specificerat i hur talet såg ut internt. I ett språk med lågnivå och maskinnära möjligheter kan man se hur bitmönstret ser ut inne i flyttalet.

Det fanns flera sätt att koda flyttal internt i bits förr, men i takt med att man behövde kunna flytta flyttal mellan olika maskiner, så gjorde bla ANSI-kommitte'en mfl ett stort jobb med att ta fram standarder, IEEE 754.

Från och med 486 CPUn var mathcoprocessorn integrerad på chippet. Dessförrinnan så hade 386an antingen en separat coprocessor eller att mathrutinerna kördes i mjukvarumode, emulerades alltså

Man har dock framfört kritik emot att många av dagens CPUer inte kan adressera en enskild bit, man måste istället använda fulkod eller tricks för att kunna flippa en enskild bit

Citat:
Ursprungligen postat av RostigHink
Sedan lite självlärd C på universitetets PDP11-34 som körde unix system 6 och var till vårt fria förfogande. Kurser i C fanns inte då.

Ja, de tidiga C och Unixarna var ett rent h-e, många slags Unixar kom fram i ljuset, alla hade de sina egna egenheter. Solaris blev ju ett andningshål där man visste att viss kod fungerade fint. I synnerhet ioctl funktionen kunde fungera olika i olika maskiner, det fanns också idioter som lyckades stänga stdin och då var det bara att hoppas på en omstart...

Det fanns C med massor av macros i och de var olika ifrån utgåva till utgåva, man fick ångest varje gång man skulle kopiera kodsnuttar emellan olika arkitekturer, stdio.h och stdlib.h kunde vara olika ifrån gång till gång, ibland kopierade man hela header kod trädet, men när man sen skulle kompilera och länka en ny variant av tex stdlib så gick allt åt -he
och preprocessorn fick spel och bara matade ut tomfoolery, jaja

Då på den tiden så fanns det folk som själva satt och handjagade egen kod i stdio så man visste inte vilka ändringar som hade gjorts

Eftersom editorn emacs öppnade stdio.h i icke skrivskyddat läge per default så kunde de mindre erfarna tycka det var en enkel sak att ändra i den och så vart det tok igen..
Citera
2017-08-10, 07:42
  #78
Medlem
Citat:
Ursprungligen postat av DrSvenne
Man har dock framfört kritik emot att många av dagens CPUer inte kan adressera en enskild bit, man måste istället använda fulkod eller tricks för att kunna flippa en enskild bit
I stort sett samtliga processorarkitekturer är oförmögna att adressera en enskild bit - inte så konstigt eftersom minnesbussen inte är en bit bred. Vill du peta på en bit i en minnesmodul som har 64-bit minnesbredd så skrävs det att dessa 64 bit läses in och sedan en bit slås om och hela 64-bit värdet skrivs tillbaka igen. Dvs finns ingen väg runt read/modify/write.

Tar du 8051-processorn t ex så har den alltså RAM integrerat inne i processorn - och en viss byte-range av detta RAM är elektriskt kopplade så att processorn verkligen kan skriva eller läsa en enskild bit. Men det är då bara en väldigt liten del av processorns RAM som tillåter detta eftersom det är ogörbart att låta allt RAM ha sådan elektrisk inkoppling - samt att det snabbt blir väldigt stora adresser.

Finns däremot vanliga processorarkitekturer som i minneskontrollern har integrerat read/modify/write på bitnivå för att kunna emulera bit-adressering. ARM har t ex i minneskontrollern på vissa Cortex-processorer skapat alias-mappningar där en array av 32-bit integers i ett adressområde i minnet mappar mot ett annat adressområde i RAM. En skrivning av 0 eller icke-noll till en av dessa 32-bit integer gör då att minneskontrollern själv gör en atomisk read/modify/write för att skriva 0 eller 1 i enskild bit i en region av RAM där man har periferienheter minnesmappade. Alltså kan man ha
Kod:
int *uart1_rx_available = MAGIC_ADDRESS_FOR_UART1_RX_AVAILABLE_FLAG;
...
if (uart1_rx_available) uart1_process_received();
i stället för att behöva skriva
if (uart_rx_flags & 0x0400) uart1_process_received();

Och på samma sätt kan man sätta/nolla en flagga i ett kontroll-register genom att göra en 32-bit skrivning i stället för att behöva koda en explicit read/modify/write:
Kod:
flag_field = flag_field | (1u << 5);

Så man får en arkitektur som definitivt inte har bit-adressering och ett programspråk som definitivt inte har bit-variabler att kunna operera på enskilda bitar med en enda processorinstruktion och utan att t ex ett interrupt går in mitt emellan och råkar modifiera samma hårdvaruregister. Minneskontrollern kommer ju garantera att read/modify/write blir atomiskt utförd.

Men precis som tidigare så krävs det att programspråket kan allokera variabler av exakt storlek och placerade på absoluta adresser, eftersom det ju bara finns en enda adress i minnet där man kan placera en 32-bit int-variabel som vid läsning/skrivning kommer att mappas över till den specifika bit som motsvarar rx available-biten i just UART1. Och vill man göra atomisk test + toggling + hopp av den typ som används när man implementerar tråd-låsningsprimitiver och liknande, så behöver man fortfarande hjälp i språket att kunna utföra sådan atomisk special-instruktion i processorn. Dvs att programspråket t ex supportar inline-assembler eller supportar så kallade intrinsic-instruktioner - en "funktion" som vid kompileringen översätts till en specifik assemblerinstruktion.

Det går göra en del roligt med att hårdkoda in logik i minneskontroller - men ibland lurar det folk till farliga antaganden som biter när man växlar till annan arkitektur. I x86-världen fick folk snabbt lära sig att kunna typecasta godtyckliga pekare till int-pekare och läsa/skriva utan att bekymra sig om align - just för att Intel lärde minneskontroller att en unaligned access i minneskontrollern skall översättas till dubbla alignade läsningar + kombinering - eller till splittning i två alignade skrivningar. Intel ville helt enkelt vara snäll med folk som portade källkod från 8-bit processorer. Men vid flytt av samma kod till annan processor-arkitektur så blir unalignad access då däremot direkt "bus error" varvid programmet felavslutas. I en 8086 så blev programmen mindre när kompilator eller programmerare inte behövde producera multipla instruktioner för att kombinera värden från flera minnesadresseringar - men folk missade i stället att en variabelaccess kunde bli dubbla minnesaccesser. Och att de två minnesaccesserna inte behöver vara i samma cache-sida.
Citera
2017-08-10, 15:41
  #79
Medlem
Citat:
Ursprungligen postat av cellplast
I stort sett samtliga processorarkitekturer är oförmögna att adressera en enskild bit - inte så konstigt eftersom minnesbussen inte är en bit bred. Vill du peta på en bit i en minnesmodul som har 64-bit minnesbredd så skrävs det att dessa 64 bit läses in och sedan en bit slås om och hela 64-bit värdet skrivs tillbaka igen. Dvs finns ingen väg runt read/modify/write.

Ja med bitmasker och bitwise operationer så gör man ju sådant, Men det är det jag menar med fulkod, vanliga programmerare tycker det ser ut som just det - alltså "fulkod"

En annan företeelse som betraktades som fulkod i C var tex ? -operatorn, eller enrads if mm,
Mycket diskussioner fanns i C-s barndom om vad som var lämpligt, Med dåtidens skrivare och skärmar gick det knappt att se skillnad på semikolon och kolon, och det skapade mycket irritation. En del av de äldre programmerarna hade lupp med sig. Matrisskrivarna var så dåliga att måsvingarna knappt syntes, etc...
Så dåliga att somliga patchade sin egen C med BEGIN för { och END för }
Operatorn -> togs dock tacksamt emot

Citat:
Ursprungligen postat av cellplast
Men vid flytt av samma kod till annan processor-arkitektur så blir unalignad access då däremot direkt "bus error" varvid programmet felavslutas. I en 8086 så blev programmen mindre när kompilator eller programmerare inte behövde producera multipla instruktioner för att kombinera värden från flera minnesadresseringar - men folk missade i stället att en variabelaccess kunde bli dubbla minnesaccesser. Och att de två minnesaccesserna inte behöver vara i samma cache-sida.

Alignment gav ju upphov till en hel del förvirring, ofta hade det ju blivit bortglömd inställning i kompilatordirektiven att alignment skulle vara off resp on, Dvs koden skrivits för länge sedan och man hade glömt att generera en makefile där flaggan var satt/ickesatt. Makefiler var ju bra för där kunde man ju se vilka inställningar som var satta. Och en bortglömd del i kurserna, att det inte togs upp, varken makefiles eller alignment. Inte heller portning ifrån 16-bit kod till 32-bit, eftersom i 16-bit det var segmenterad adressering medans i 32-bit flat memory model adresseringen var flat.
Citera
2017-08-11, 08:38
  #80
Medlem
Citat:
Ursprungligen postat av DrSvenne
Ja med bitmasker och bitwise operationer så gör man ju sådant, Men det är det jag menar med fulkod, vanliga programmerare tycker det ser ut som just det - alltså "fulkod"
Elegans spelar ingen större roll - problemet är korrektheten. Dvs att inte få timing-problem med en read/modify/write.

Problemet är att:
Kod:
registerflags |= 0x0001;
i själva verket utförs som:
Kod:
load r1,[registerflags]
or r1,0x0001
store [registerflags],r1

Dvs kommer det ett interrupt efter att processorn laddat "registerflags" och interrupt-koden modifierar innehållet i registerflags, så kommer efterföljande store att skriva bort den ändring som interruptkoden införde.

En rejäl mängd av världens alla buggar kommer just från denna typ av kod, eftersom det är så svårt vid provkörning att upptäcka problemet - kanske inträffar en gång på miljarden. Om processorn kör loopen 1000/sekund så uppstår situationen i snitt en gång var 11:e dygn.

Men behövs alltså något sätt i språket för att säga att just den där sekvensen inte får brytas - och ännu krångligare i multikärna för då räcker det inte att stänga av interrupt eftersom ju en annan kärnan också kan köra en tråd som försöker modifiera samma registervärde.
Citera
2017-08-12, 02:32
  #81
Medlem
Citat:
Ursprungligen postat av cellplast
Elegans spelar ingen större roll - problemet är korrektheten. Dvs att inte få timing-problem med en read/modify/write.

Problemet är att:
Kod:
registerflags |= 0x0001;
i själva verket utförs som:
Kod:
load r1,[registerflags]
or r1,0x0001
store [registerflags],r1

Dvs kommer det ett interrupt efter att processorn laddat "registerflags" och interrupt-koden modifierar innehållet i registerflags, så kommer efterföljande store att skriva bort den ändring som interruptkoden införde.

Jo, man bör ju så klart att skriva interruptkoden så att interruptet bara gör det allra nödvändigaste och återställer sedan allt som det var innan interruptkoden kördes, En del mera avancerade sådana sparar undan hela register innehållet i en struct, när interruptkoden är klar så läggs detta tillbaks igen.

Man brukar också få förhindra att ett annat interrupt skulle hoppa in i ett pågående interrupt.

Ja det finns många varianter, men inte så lätt att lära ut, utan att man gör en mängd praktiska kodexempel och att programmerarna får träna på detta..

Inne i CPUn ser koden ofta sådan ut, det är bara enskilda primitiver som inte kan uppdelas mera
tex
if ( i >= 0 && i < 100) { sum = sum + i * i;}
är en enrads-if men expanderas till en mängd instruktioner (primitiver) i assembler

Men uttrycket primitiver används ibland även om datatyper som är primitiva, tex ints och unsigned ints

För multitråds programmering bör man ha semaforer,
ett annat fuskigare sätt är förstås att varje tråd har en lokal kopia av en variabel som mest bara behöver läsas, man kan sen ha en synk då och då, om den behöver uppdateras
och man kan ju rentav invalidera tex en elr fler pekare för att undvika att ngn programmerare skulle sitta och leka med en annan tråds data. Alltså Invalidera = sätta till null_ptr

En del trådar behöver ju inte omedelbar uppdatering utan den kan få snurra ganska många loopvarv innan man bryr sig om att göra en synkning
Ursäkta - är lite kass på att beskriva det här bara i text

Jag är dock inne på att cellplast m fl beskriver problemet bra, man kan inte simulera sådant här tillförlitligt i vanliga fall med vanliga simulerade/emulerade CPU-modeller eftersom alla instruktioner förutsätts ske atomärt och omedelbart, och helt utan fördröjning.

Tex UARTs är ju en annan grej att de är asynkrona, man kan ju aldrig veta när själva operationen på UART-en görs,
det går inte heller att veta om när data kommer att bli tillgängligt på porten med bara pollning. Istället hookar man ju ett interrupt att köra koden för "data tillgängligt"
Men de flesta UARTs körs ju i buffrad mode, så man kan ju bli förvirrad ibland, bara att styra om devicen till NULL-devicen så är problemet borta igen, hehe...
Citera
2017-08-13, 04:08
  #82
Medlem
Citat:
Ursprungligen postat av MeanME
Det finns ju tester där Java med sin garbagekontroll smäller både C och C++ på fingrarna.
Det finns det inte, är java snabbt i något test beror det på att programmet är mycket litet och kanske använder något i biblioteket som är skrivet i C/C++

Skall man få upp ordentligt med hastighet måste man koda för processorers cache och prefetchefers (såvida du inte har en mycket enkel cpu). För att göra det behöver man kontrollera minnet.

Lite beroende på vad man gör men ett C++ program kan vara nästan 100 gånger snabbare jämfört med java för vissa typer av arbeten och att programmeraren vet hur man gör för att processorn skall jobba optimalt
Citera
2017-08-17, 14:04
  #83
Medlem
MeanMEs avatar
Citat:
Ursprungligen postat av DrSvenne
Såklart att man kan säkert hitta Java-kod som går acceptabelt snabbt. Men allt svammel om att Java skulle vara bättre är bara helt totalfel. Java kan aldrig bli bättre än sin Java VM. Finns det buggar i Java VM så är det kört, och här är problemet att man kan inte testa på alla upptänkliga indata för det innebär ett oändligt set av indata, och så mycket exekveringstid har vi inte. Vilken Java VM du ändå bygger ihop (som brukar byggas med tex gcc) så kan du aldrig garantera att den är buggfri. Om du inte skulle ha oändliga CPU-resurser och oändlig CPU-tid att bevisa det på... Typ... Hoppas du begriper vad jag skriver här...

Vidare så finns det något gammalt bevis på att ett interpreterat språk aldrig kan bli så väloptimerat som ett kompilerat språk. Dvs det finns begränsningar hos de optimeringar som kan göras hos en interpretator, medans en kompilator har många fler val. Detta finns beskrivet i teorierna för kompilatordesign men minns inte hur det är formulerat.

Vad gäller embedded-programmering så körs ju dessa programmen i en ganska godartad miljö, dvs det mesta är ju känt om den CPU och minne som är programmets habitat. Det finns vanligen inga konkurrerande processer som processar interrupts mm. I en vanlig PC däremot så kan det variera enormt mycket.

För embedded programmering är det nästan alltid vettigast att allokera allt minne som behövs för körningen alltså under maxload redan i början. Man behöver inte använda malloc/free new/delete alls annat än vid uppstarten.

Vill man återanvända minne till olika ändamål så kan man ju använda union deklarationen om man nu vill behålla en slags parameterkontroll vid kompileringen. Språket Swift gör dock annorlunda, där kontrolleras inte parameteröverföringen alls utan anropad metod får själv parsa fram parametrarna, eller gissa sig fram, typ...

Man kan ju göra samma i C/C++ och skippa parameteröverföringen helt rentav med tex globaler istället, man spar ju på stackanropen då mm, etc...

För embedded programmering bör man undvika rekursion, om man inte kan garantera att rekursionen alltid terminerar, Man bör således alltid skriva rekursiv kod så att den alltid terminerar oavsett indata.

Garbage collector finns ju egentligen för att programmeraren är lat, Virtualisering av minnet i block kan ju undvika problemet med fragmentering, dvs att minnet delas upp som i ett filsystem med pekare till nästa cluster. Sådana minneshanterare har skrivits och medför ju naturligtvis en hel del fördelar, Särskilt i händelse av många allok/deallok av riktigt stora sammanhängande block. Men i händelse av abort() så kan det hända att allt inte frigöres korrekt, dvs det blir en "svans kvar" av allokerat minne.

Fragmentering av minne vet jag inte om man kan upptäcka idag, eftersom de flesta system har swap-utrymme, relokationen kan ju dock ta tid. I virtuella maskiner så kan man ju i alla fall i teorin tilldela mera RAM under körning och helt undvika relokering.

Virtuella maskiner innebär en mängd fördelar för testningsmöjligheter, att växla CPU-hastighet, I/O prestanda, RAM-mängd, etc -- Det är dock inte lätt att testa programkod under alla dessa förutsättningar. Man har ju hört talats om programmerare som slitit röven av sig för att göra ett mycket bra program, och så visat det sig att det bara snurrar bra på en värsting-PC, men oacceptabelt dåligt på en medioker PC, sådant kan ju upptäckas med att ha VMs som testbeds i den tidiga testfasen.

Numera har man så snabba nätverkslinjer att de sällan utgör utgör någon störning Men man kunde ju förr stöta på program som hade blockande nätverkspakethämtning eller blockande nätverkslyssning, och programmen var då "låsta" ifall linjen tex dött
Ber om ursäkt för sent svar, legat sjuk och har inte orkat svara...

Vi har nog haft denna diskussionen 5-6 ggr nu och varit rörande överens om hur man skall göra det, och i artikeln jag länkade till vill jag minnas visade hur man gör det med.
Så... det finns just inte mycket mer jag har att tillägga.

Men likväl gör inte alltid folk rätt och missar i elementa.
Vi ser det i nästan alla spel och i andra kommersiella produkter som släpps idag.
Vet inte hur många uppdateringar och buggfixar som blivit körda på de program bara jag har. Jag skulle tippa minst 100 kanske långt över 200 det är oräkneliga i vilket fall som helst.

Så det är bara att konstatera att det kan bli fel ibland.
Den som hävdar något annat vet inte vad den pratar om imho.

Sedan "om det finns buggar i Java WM så är det kört".
Ja det är det väl om det finns buggar i C kompilatorn med eller begränsningar/prestandabrister i dess libs? Så det är ju liksom inget argument i mina ögon.

Förutsätter man att det finns fel i den ena bör man ju ärligen göra samma antaganden för båda parter eller hur? Finns en faktor extra att ta hänsyn till det är dock sant.

Sedan har jag sett och läst så många tester om att java kan vara snabbare än C i vissa fall och för vissa jobb att jag tror nog utan att knappt ha skrivit något i java, kan nog räkna de större projekt jag gjort i java på ena handens fingrar, att det bör ligga något i det. Generellt nej men för vissa speciella uppgifter, där skulle jag sträcka mig till, troligen.
Citera
2017-08-18, 02:44
  #84
Medlem
Citat:
Ursprungligen postat av MeanME
Sedan har jag sett och läst så många tester om att java kan vara snabbare än C i vissa fall och för vissa jobb att jag tror nog utan att knappt ha skrivit något i java, kan nog räkna de större projekt jag gjort i java på ena handens fingrar, att det bör ligga något i det. Generellt nej men för vissa speciella uppgifter, där skulle jag sträcka mig till, troligen.
Omöjligt, isåfall jämför man inte likartad kod.
En GC är ineffektiv om man kodar logiken själv. Har man tillgång till färdiga komponenter skriven med annat mer effektivt språk (C/C++) så kan man självklart få upp hastigheten men det beror inte på javan
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback