È comune prototipare in un linguaggio di livello superiore? [chiuso]


18

Attualmente sto giocando con l'idea di intraprendere un progetto che supera di gran lunga la mia attuale capacità di programmazione in un linguaggio in cui ho pochissima esperienza nel mondo reale (C). Sarebbe utile realizzare un prototipo in un linguaggio di livello superiore con cui ho più familiarità (come Perl / Python / Ruby / C #) solo per far andare avanti il ​​progetto complessivo?

Alla fine, il prodotto finale è sensibile alle prestazioni (è un motore di database), quindi la scelta di C, ma temo che non conoscere bene C mi farà perdere la foresta per gli alberi.

Durante la ricerca di domande simili, ho notato che un collega menzionava che i programmatori erano soliti prototipare in Prolog, per poi farlo girare in assembler.


4
Ho sentito di persone che avrebbero scritto assemblatore prima codificando ciò che volevano in C, quindi smontandolo e regolando manualmente l'assemblaggio risultante.
user16764

9
Non dimenticare che le prestazioni il più delle volte si riducono alla corretta selezione e implementazione dell'algoritmo, scrivendo codice parallelo per problemi imbarazzantimente paralleli e buone rappresentazioni dei dati. Non preoccuparti di C fino a quando non ottieni il design giusto.
Peter Smith,

1
@ user16764: In realtà lo ha fatto. Tranne che la lingua era Fortran. Ma abbiamo modificato a mano l'output del compilatore esattamente come descrivi.
S.Lott

C non è necessariamente più veloce. Soprattutto se le prestazioni sono legate all'IO. Anche per le prestazioni legate alla CPU, se non sei un esperto in C, probabilmente una VM ottimizzata può superare qualsiasi cosa tu scriva.
jiggy,

Uso spesso questa tecnica di prototipazione: un problema è espresso nel suo linguaggio più naturale, che finisce per essere implementato come DSL. Quindi, quando il prototipo è finito, invece di ricodificare una parte DSL in un linguaggio di livello inferiore, migliora l'implementazione di questo compilatore DSL, fino a quando le prestazioni sono accettabili.
SK-logic,

Risposte:


27

L'uso di C non rende automaticamente la tua applicazione più veloce. Quando hai la possibilità di scegliere un linguaggio di programmazione diverso per la tua piattaforma, lo consiglio vivamente.

Come ha affermato Bill Harlan :

È più semplice ottimizzare il codice corretto che correggere il codice ottimizzato . L'ottimizzazione prematura ostacola effettivamente l'ottimizzazione a lungo termine. L'ottimizzazione non necessaria distorce i progetti, distrugge la modularità e il nascondimento delle informazioni e rende il codice molto più difficile da modificare. I bug latenti richiedono più tempo per essere trovati. Scopriamo spesso, attraverso la profilazione, o cambiando macchine o compilatori, che abbiamo giudicato erroneamente lo sforzo computazionale del nostro codice. Indovina un po? Ora, l'ottimizzazione è molto più difficile di quanto dovesse essere.

Se riesci davvero a prevedere i problemi di prestazioni, prendi in considerazione l'uso del C ++. cprogramming.com lo esprime molto bene :

Ci si potrebbe chiedere, però, se vale la pena rinunciare alla riutilizzabilità di C ++ per ottenere il piccolo aumento delle prestazioni con C, soprattutto quando lattina C ++, ove necessario, essere scritto in uno stile di programmazione C .


Per rispondere meglio alla tua domanda reale: scriverei il codice in un linguaggio di livello superiore, non solo lo prototipo, e ottimizzerei solo in linguaggi di livello inferiore quando riscontri problemi di prestazioni.


25
+1: Inoltre, Perl, Python e Ruby possono chiamare funzioni C, quindi è possibile scrivere le parti sensibili alle prestazioni in C se necessario.
Larry Coleman,

Ho prototipato il codice di visione artificiale in Java; che si è scoperto in realtà era abbastanza veloce. Ricodificare in C sarebbe stato abbastanza semplice (basta scriverlo come C; usando l'
antipasto di

Ho scritto codice in tempo reale in Java. In quel particolare progetto, l'accesso ai file è stato fatto con C ++ e il codice in tempo reale era in Java - pazzo! Tuttavia, il codice in tempo reale è stato incredibilmente veloce. Non è stato molto complicato, ma ha gestito incredibili quantità di dati in pochissimo tempo. Quindi direi che puoi sicuramente usare linguaggi di alto livello per applicazioni sensibili alle prestazioni.
configuratore

@ Tim Williscroft: mi sembra di alzare questa pagina solo quando cerco su Google "Antipattern di fissazione primitiva". Cos'è quello?
SingleNegationElimination

@TokenMacGuy: l'ossessione primitiva ha più colpi (stesso antipasto)
Tim Williscroft,

7

Non sarebbe utile farlo, perché a) le parti di quelle lingue che traducono direttamente in C non sarebbero più semplici, e b) le parti che non si traducono direttamente in C sarebbero più difficili da riscrivere in C di se li avessi scritti in C in primo luogo.


+1 - Soprattutto perché sarebbe difficile spostare il codice OO su C se non si ha familiarità con la lingua, o renderebbe più imbarazzante l'uso della lingua di alto livello se si scrive in modo procedurale.
Jetti,

Si, esattamente. Sono preoccupato che potrei ancora pensare a concetti superiori che non sono facilmente traducibili in C, come se usassi troppa magia o zucchero.
Mark Canlas,

4

Questa non è una domanda con una risposta sì o no categorica. Mi permetta di pesare con un aneddoto.

Esempio 1

Mi è stato assegnato il compito di eseguire il porting di un gioco scritto in Java su Flash, AS3. In superficie, questo ha il potenziale per andare relativamente agevolmente. Dopotutto, potresti considerare un lavoro del genere più chiaro del normale lavoro del cliente, perché hai già una specifica funzionale completamente costruita sotto forma di gioco sorgente. Java e AS 3 sono entrambi linguaggi di alto livello e AS3 condivide molti tratti in comune con Java, come strutture di pacchetti, ereditarietà singola / interfaccia multipla, digitazione forte (opt-in) e nozioni di variabile pubblica / protetta / privata e dichiarazioni di funzione. All'epoca ero ancora molto ecologico con Java e completamente nuovo rispetto alla base di codice sorgente originale. Quindi mi sono tuffato per vedere cosa potevo trovare sperando che fosse facile e veloce.

A quanto pare, l'autore del codice aveva tentato di creare un motore astratto che potesse essere portato da Java in un altro ambiente indefinito. Questo mi ha dato la speranza che sarebbe stato semplice portarlo. Sfortunatamente, invece, ho scoperto che stavo guardando la prospettiva di reinventare Flash stesso sopra Flash, senza il vantaggio di Thread. Una porta letterale, come si è scoperto, sarebbe stata semplicemente una cattiva idea ... un incubo da esibizione. Inoltre, il gioco ha implementato un proprio linguaggio di scripting esterno personalizzato, che avrebbe significato creare un parser e un lexer per quella lingua se sperassi di usare tutti i file di dati di origine originali.

Alla fine, dati i vincoli di tempo e budget, il codice sorgente originale non ha aiutato molto. La parte più utile di averlo è che sapevo imitare con precisione il flusso di controllo della logica del gioco ... ma avevo davvero bisogno della fonte originale per quello? Probabilmente no.

Ma quell'esempio potrebbe non essere così rilevante perché è una specie di rovescio della tua situazione. Speravo di usare una base di codice che non avevo scritto, in una lingua che all'epoca non conoscevo per accelerare lo sviluppo in un ambiente che conoscevo molto bene. Quindi ecco un esempio diverso

Esempio 2

Notando cosa stava facendo lo sviluppatore Java nel tentativo di creare una base di codice portatile, ho iniziato a fare qualcosa di simile per me stesso nel mio lavoro Flash ... scrivendo codice che non si basava molto sull'estensione delle classi flash.display. * Ad esempio, e usando la composizione per creare viste. Non fare troppo affidamento su flash.event. * E invece scrivere un leggero sistema di trasmissione dei miei messaggi, non legato in particolare a un linguaggio o una piattaforma. Di recente ho finito un gioco usando detto framework e volevo vedere se sarebbe stato facile portarlo su C # (un linguaggio che conosco in quanto simile a Java e AS3) come progetto Unity 3D. A quanto pare, questo ha avuto molto più successo! Perché penso in modo più fluido in AS3 che in C #, avere gli algoritmi già scritti ha fatto risparmiare un sacco di tempo. Tutto quello che dovevo fare era semplicemente cambiare la sintassi, che non è

Quindi, proprio nella mia esperienza personale, non posso dire che la risposta sarà sempre sì o no. Dovresti considerare in che misura dipendi da particolari idiomi linguistici nella tua lingua di alto livello prescelta e se ricrearli sarà facile o difficile in C.


La tua seconda storia illustra come mi sento. Vorrei provare a mantenere l'implementazione del prototipo generica e magica / ingannevole, in modo tale che la maggior parte, se non tutte, le idee possano essere tradotte in C. Più facile a dirsi che a farsi, ma penso che a un livello abbastanza alto porti ancora. Ovviamente il diavolo è nei dettagli.
Mark Canlas,

@Mark Canlas "il diavolo è nei dettagli." Assolutamente. Penso che sia possibile che il tuo primo tentativo possa andare storto se non hai mai portato il codice tra lingue o ambienti prima solo perché è difficile prevedere tutti i potenziali problemi fino a quando non li hai incontrati.
scriptocalypse,

2

Penso che sarebbe utile iniziare con lo pseudocodice. Scrivere un prototipo in un'altra lingua sembra una potenziale perdita di tempo, dal momento che la tua lingua di livello superiore non è probabile che si traduca in "C" quasi come lo farà lo pseudocodice.

Inoltre, utilizzando lo pseudocodice, svilupperai una migliore comprensione del funzionamento effettivo del tuo sistema.

Durante lo stesso periodo di tempo in cui stai lavorando allo pseudocodice, dovresti studiare C. Quindi, una volta terminata la pianificazione, potresti essere pronto per implementare effettivamente la cosa.

Dal momento che il motivo proposto per scriverlo in un'altra lingua è stato quello di aiutare a far partire il design, potresti invece voler utilizzare alcuni diagrammi UML o qualcosa del genere per iniziare.


2

Puoi prototipare l'algoritmo - appianare gli errori di progettazione della logica di base, usando un linguaggio decisamente di "livello molto alto" (diciamo, Matlab, forse Ruby). Usalo per dimostrare che il tuo algoritmo funziona e funziona correttamente, quindi implementalo da zero in un linguaggio "di basso livello".

Non otterrai molto se scegli C ++ o anche Java o C # come "alto livello" e C come "basso livello" perché il guadagno in leggibilità non sarà significativo e la "traduzione" sarà ancora piuttosto dolorosa e piuttosto bug- prona. L'idea è l'essenza, il motore del tuo progetto nell'implementazione di alto livello non dovrebbe occupare più di uno o due schermi, essere facile da capire, facile da leggere e tutti gli avvertimenti per essere dolorosamente ovvi - in sostanza, un blocco funzionante, eseguibile diagramma.


2

Un motore di database riguarda principalmente la gestione degli I / O di basso livello in modo ottimale e la gestione efficiente di strutture complesse come b-tree ed elenchi collegati.

Quindi è sicuramente un problema C / C ++, anche se ci sono alcune implementazioni Java piuttosto buone là fuori.

Lo sviluppo di algoritmi corretti che funzionano bene è molto più semplice in un linguaggio di livello superiore. Di solito è il caso di provare diverse varianti e confrontare i risultati. È quindi possibile tradurre l'algoritmo "vincente" in C.

Una soluzione di compromesso potrebbe essere quella di scrivere l'implementazione iniziale in uno dei linguaggi JVM di livello superiore (vengono in mente Jython, Groovy) e quindi spostare classe per classe su Java quando l'implementazione si stabilizza.


2

Non penso che sia comune, ma è fatto. Uno degli architetti più nitidi con cui abbia mai lavorato usava fare la sua modellazione in Python e quindi implementare quel codice in C ++.

In generale, per renderlo utile, penso che tu debba davvero eseguire algoritmi complessi e altamente ottimizzabili che non sono facilmente espressi in modo semplice nella lingua di destinazione. Per la maggior parte delle situazioni di "mondo reale / affari", è relativamente facile esprimere l'intento di alto livello nella stessa lingua che stiamo prendendo di mira e un'implementazione in tale linguaggio soddisfa i nostri requisiti di prestazione, quindi non c'è bisogno / desiderio di modellare in un livello superiore lingua di livello.

Data la tua situazione, in cui hai una migliore conoscenza di una lingua di livello superiore, ho potuto vedere questa metodologia funzionare bene a breve termine. Non solo ti fornirà una tabella di marcia per tenere traccia delle cose, ma se hai domande sarai in grado di porle con maggiore precisione.


1

Attualmente sto lavorando a un progetto che è scritto in C "a causa delle prestazioni" (questa era la motivazione originale), ma in effetti se profilato rivela che passa la maggior parte del suo tempo in attesa di altri sistemi (un DB, altre app scritte in Java, "eventi" su un socket).

Se usi l'algoritmo sbagliato ottieni cattive prestazioni anche in C (ad es. Se fai una ricerca lineare di una chiave, "poiché C non ha tabelle hash e non vogliamo usare altre librerie", vai più lentamente che se fallo con un linguaggio che ha tabelle hash o simili come C ++, Java, C #, Python ... e così via).

Se sei costretto a farlo in C per qualsiasi motivo, allora prototipare in un'altra lingua che conosci per me non è una cattiva idea solo se prototipi sapendo quali "problemi" dovresti fare l'implementazione in C effettiva, è difficile se non sei sicuro con C. (Presto scoprirai ad esempio che le librerie std C / C non hanno contenitori, solo array "semplici"; hai bisogno di librerie non std). Inoltre C non è OO, quindi se stai prototipando in modo OO, sarà più difficile.

Riassumendo, la cosa migliore da fare è fare l'implementazione effettiva nel tuo linguaggio di "prototipazione" e, se necessario, scrivere funzioni ad alta intensità di CPU in C, ma se solo C è accettabile, imparalo meglio prima di fare il prototipo in altri lingue e ovviamente prima di scrivere l'implementazione.


1

Esistono molte applicazioni critiche per le prestazioni scritte in un linguaggio di livello superiore.

Ho programmato in Assembler e C in passato, e sebbene sia un po 'bello sentirsi così vicino al metallo, il loro uso è molto limitato al giorno d'oggi.

Ci sono così tante cose che ostacoleranno le prestazioni, che dubito che raggiungerai mai la parte in cui il linguaggio stesso è il fattore limitante. Questo sta considerando che è C vs C #.

Supponi di ottenere un aumento delle prestazioni del 10% -15% in base alla lingua. Questo non è nulla in confronto agli ordini di aumento di grandezza nell'implementazione dell'algoritmo corretto.

Quando stai programmando in C #, avrai molto più tempo per concentrarti sull'architettura e l'implementazione di algoritmi / strutture di dati, portando così a migliori ottimizzazioni di livello superiore.

Nel mondo reale sei sempre limitato nel tempo, quindi trascorri il tuo tempo nella parte giusta del progetto.


0

Sono curioso di sapere quale sia il tuo piano per crearlo effettivamente in C? Stai andando a prototipare e quindi imparare C, e quindi ricodificarlo in C? A me sembra che i proverbiali "occhi siano più grandi dello stomaco" in cui penso che molti programmatori vengano catturati mentre apprendono nuove tecnologie (so di averlo). Quello che voglio dire è che stai cercando di progettare qualcosa che sia chiaramente sensibile alle prestazioni senza ancora conoscere i dettagli del linguaggio in cui ritieni che alla fine debba essere scritto, in pratica vuoi già iniziare a progettare un'app C prima di te conoscere C quando è meglio trascorrere del tempo prima di imparare C e quindi è possibile ottenere maggiori informazioni su come scrivere l'applicazione desiderata. Forse ho scambiato la domanda e hai intenzione di consegnarla a un altro programmatore per costruire il programma in C,


A volte "Non farlo". è la risposta corretta a "Come faccio X?"
Larry Coleman,

0

Il prototipo viene eseguito, a volte, per comprendere il problema che si sta tentando di risolvere. E a volte, per conoscere le tecnologie sottostanti se non ne hai già familiarità.

Per il caso menzionato, stai considerando di realizzare un prototipo in un linguaggio di scripting, ad esempio python, e di creare il codice effettivo in C.

Valutare alcune possibilità:

1 . Prototipi in Python e scrivi il software in C.

La prototipazione in un linguaggio di scripting può aiutare dove si desidera verificare rapidamente l' output rispetto all'input . Questo è utile se devi principalmente testare la tua logica per risolvere un problema. Inoltre, utile se vuoi mettere rapidamente insieme una demo per altre persone.

Qualunque codice tu abbia scritto in Python non verrà utilizzato nel software finale. Ma può essere d'aiuto se stai trasmettendo il tuo prototipo a qualcuno che può leggere Python e scrivere in C. Qui, la prototipazione può aiutare a comunicare un'idea .

Questo metodo è appropriato per testare la fattibilità logica della soluzione.

2 . Prototipi in C e scrivi il software in C.

Il prototipo in C, che è nuovo per te, ha due vantaggi. Uno, mentre scrivi il prototipo, puoi capire le parti pertinenti della lingua , della libreria, dell'API, delle insidie, ecc. Due, mentre costruisci il software finale, puoi iniziare dal prototipo stesso che ti fa risparmiare tempo e riutilizza il codice .

Questo metodo è adatto per testare la fattibilità logica e tecnologica della soluzione.

3 . È possibile prendere in considerazione metodi non codificanti per la prototipazione in base al problema attuale.

Se è un pezzo di logica e idee che vuoi prototipare; anche pseudo codice , diagrammi di flusso e diagrammi a blocchi su carta sono buoni.

Se si tratta di un prototipo dell'interfaccia utente, prendere in considerazione uno strumento di simulazione dell'interfaccia utente o, di nuovo, un po 'di carta.


0

Penso che dovresti prototipare in una lingua che conosci (Pytho / Ruby / C # cosa no) in modo che:

  1. Sfruttate al meglio le strutture / librerie fornite dalla lingua.
  2. Trascorri il tuo tempo a decidere le scelte di progettazione anziché le limitazioni linguistiche.

Successivamente, è possibile utilizzare uno strumento di profilazione per trovare aree del collo di bottiglia. Reimplementare in C / C ++. Ripeti il ​​passaggio sopra alcune volte, chissà che il tuo prototipo potrebbe essere "abbastanza veloce"!


0

Non penso che tu stia guadagnando qualcosa dall'approccio che hai descritto e diverse persone hanno descritto il perché in qualche dettaglio.

Un progetto a cui sono stato coinvolto ha utilizzato questo tipo di approccio: sviluppo di librerie matematiche per le architetture Cell / BE e Power7. Le funzioni sono state modellate in Haskell (usando CoCoNUT) e le funzioni di output erano in assembly ottimizzato per una particolare architettura di destinazione.

In questo caso gli obiettivi erano prestazioni elevate con istruzioni di assemblaggio ottimizzate e la capacità di indirizzare più architetture.

Cibo per, spero che tu non muoia di fame :)


0

Per un motore di database ad alte prestazioni sarà presumibilmente necessario:

  • multi-filettatura,
  • gestione esplicita della memoria,
  • notifiche asincrone,
  • semafori o primitive di sincronizzazione,
  • facile accesso alle funzioni di file system di basso livello.

Gli algoritmi scelti sono fondamentali per le prestazioni.

Il consiglio generale è di iniziare con un linguaggio di alto livello, quindi migrare solo i bit che devono essere ottimizzati in un linguaggio di livello inferiore.

Tuttavia , il linguaggio di alto livello che scegli deve essere in grado di supportare gli algoritmi che devi scrivere: e gli algoritmi efficienti qui possono in definitiva essere dominati dal controllo del threading, dall'uso efficiente della memoria e dall'uso delle migliori operazioni di file system di basso livello a disposizione. Quindi, se l'obiettivo finale è la prestazione, non è possibile prototipare in linguaggi che non supportano le primitive che è necessario utilizzare.

Se devi testare il tuo prototipo (o altre persone devono sviluppare software contro le sue interfacce), devi anche lavorare in una lingua che supporti le API previste. È quindi possibile consentire ad altre persone di testare il proprio codice ed eseguire i propri test di regressione durante l'ottimizzazione.

Queste considerazioni probabilmente escludono molte lingue per la prototipazione di alto livello in questo caso - e probabilmente tutte quelle che hai citato (tranne forse C #). Ma puoi, ovviamente, pseudo-codice in qualsiasi lingua (incluso l'inglese) e, se necessario, puoi prototipare parti del progetto (funzioni di ordinamento, ad esempio) nella tua lingua preferita.

La stretta relazione tra C ++ e C (e differenze di prestazione trascurabili) significa che ci sono pochissimi motivi per non preferire C ++ rispetto a C nel prodotto finale.

(Sto rispondendo sul presupposto che hai bisogno di un motore di database ad alte prestazioni per uno scopo particolare: se le tue intenzioni sono più modeste, presumibilmente, raccoglieresti un motore esistente dallo scaffale).


-2

Penso che la fama di C sia meritata, perché il magnifico prodotto Unix è stato scritto in C. Tuttavia, rispetto alle persone che conoscono meglio C, sono piuttosto scettico sul perché debba essere usato. Si dice che Ken Thompson (dopo aver scritto una prima versione di Unix in linguaggio assembly) abbia iniziato a scrivere Unix a Fortran, ma abbia rinunciato dopo una settimana o un mese e abbia iniziato a usare C che era stato sviluppato dal suo collega Ken Ritchie a lo stesso tempo.

Sono rimasto sbalordito nel leggere recentemente che Fortran è più veloce di C e C ++.

Richard Mullins


1
come risponde alla domanda posta?
moscerino del
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.