Sulla complessità accidentale dei sistemi supply chain
L’hardware computing hardware moderno è estremamente capace. Uno smartphone modesto eroga miliardi di FLOPS (operazioni in virgola mobile al secondo) pur memorizzando centinaia di gigabyte di dati. Uno smartphone singolo potrebbe tecnicamente eseguire un’allocazione predittiva dell’inventory allocation per una vasta rete retail. I dati storici richiederebbero una rappresentazione adeguata1 e, per l’elaborazione dei dati, bisognerebbe utilizzare tecniche più snelle come la differentiable programming. Così, sistemi supply chain ad alte prestazioni dovrebbero essere scontati. Sicuramente, le aziende possono permettersi qualcosa di un gradino sopra rispetto a uno smartphone per gestire e ottimizzare le loro supply chain. Eppure, un’osservazione casuale dei sistemi supply chain dei nostri clienti a Lokad indica esattamente il contrario: questi sistemi sono quasi sempre lenti e, spesso, tortuosamente tali.

I leader odierni del supply chain software (ERP, WMS, MRP, ecc.) faticano persino a sostenere 1 richiesta al secondo sul loro backend API. A Lokad, veniamo dolorosamente ricordati quotidianamente di tali prestazioni orribili, essendo in prima linea nel processo di data retrieval. Per una dozzina di clienti circa, il recupero iniziale dei dati ha richiesto quasi un mese2. La lentezza delle varie API rappresenta il 99,9% del problema. I sistemi in grado di sostenere 1MB/secondo per la loro data extraction sono pochi e rari. I sistemi che non ci costringono a re-estrarre inutilmente gli stessi dati più e più volte - per raggiungere le parti più aggiornate - sono ancora più rari. Questi sistemi tipicamente dispongono di oltre 100 risorse di calcolo in più rispetto a due decenni fa, eppure non sono fondamentalmente più veloci3 né svolgono le operazioni in modo radicalmente migliore. Alcuni dei fornitori più progressisti, che sfruttano il in-memory computing, richiedono diversi terabyte di RAM per gestire reti retail, il che è una quantità straordinariamente elevata4 di RAM, considerando ciò che viene fatto con tali risorse.
Questa “complessità accidentale” di molti (la maggior parte?) dei sistemi supply chain può essere ricondotta a due cause principali: in primo luogo, aspettative errate riguardo al progresso dell’hardware di calcolo stesso, e in secondo luogo, una mancanza di attenzione al design interno della soluzione.
Per quanto riguarda il progresso dell’hardware di calcolo, fino a un decennio fa non esisteva una singola (grande) azienda in cui la prima legge di Moore non fosse stata proposta decine di volte (di solito in modo errato). Si aveva l’impressione che i computer diventassero incredibilmente più veloci continuamente. Sfortunatamente, ciò ha smesso di essere banalmente vero dagli inizi degli anni 2000. Questa prospettiva errata di un progresso indefinito ha portato molte aziende software, ben oltre il mondo della supply chain, a commettere enormi errori. Molti dei problemi associati a Windows Vista (rilasciato nel 2006) potevano essere ricondotti alle aspettative originali - nel 2001, quando fu rilasciato Windows XP - degli ingegneri Microsoft, i quali si aspettavano che le CPU girassero a 6Ghz entro il 2006. Siamo ormai vicini alla fine del 2020, e le CPU di fascia alta per il gaming si aggirano a malapena intorno ai 5Ghz. L’hardware di calcolo non ha mai smesso di progredire; tuttavia, ha semplicemente smesso di farlo in maniera banale, almeno per quanto riguarda le aziende software.
Negli anni ‘80 e ‘90, non appena un software funzionava, anche se risultava un po’ lento alla data del rilascio, era scontato che l’anno successivo la sua velocità sarebbe migliorata, e l’anno dopo sarebbe stata eccellente. Aziende software aggressive come Microsoft giocavano molto bene questa carta: i loro ingegneri ricevevano (e ancora ricevono) l’hardware di calcolo migliore che il denaro può comprare, e spingevano sistematicamente le prestazioni del software al limite di ciò che era ritenuto accettabile, sapendo che l’hardware avrebbe essenzialmente risolto il problema delle prestazioni, in un anno o due. Dopo il disastro di Vista, i team ingegneristici di Microsoft hanno compreso l’ampiezza del problema e hanno cambiato rotta - Windows 7 è stato un notevole miglioramento. Eppure, ci è voluto un decennio affinché Windows recuperasse veramente sul fronte delle prestazioni. Oggi, la situazione è quasi esattamente l’opposto: i migliori team di Microsoft non scommettono più sull’hardware futuro e si concentrano quasi esclusivamente nel fornire prestazioni immediate superiori grazie a un software di eccellenza5.
Tuttavia, il mondo del software enterprise si è rivelato molto più lento nel notare il problema, continuando a sviluppare software durante gli anni 2010 come se l’hardware di calcolo futuro fosse sul punto di risolvere tutti i loro problemi, come era già successo in molte occasioni in passato. Sfortunatamente, per la maggior parte dei fornitori di software enterprise, mentre l’hardware di calcolo continua a progredire, un decennio fa ha smesso di farlo in maniera banale6, permettendo al fornitore di attendere semplicemente che le prestazioni migliorassero. Il software tende ad accumulare complessità (più funzionalità, più opzioni, più schermate, ecc.), e la naturale tendenza del software complesso è di rallentare nel tempo, non di migliorare - a meno che non vi sia un intenso sforzo dedicato in questo ambito.
Purtroppo, dal punto di vista delle vendite, le prestazioni sono per lo più un aspetto secondario. Le demo vengono effettuate con account dimostrativi che includono solo una frazione minuscola del carico di lavoro dei dati che il sistema affronterebbe in produzione. Inoltre, le schermate di interesse per il top management ricevono una quantità sproporzionata di rifiniture rispetto a quelle destinate agli impiegati operativi. Tuttavia, queste ultime sono esattamente le schermate che verranno utilizzate migliaia di volte al giorno e, di conseguenza, quelle che dovrebbero ricevere la massima attenzione. Sospetto che le API offrano frequentemente prestazioni scadenti perché pochi acquirenti verificano se le API stiano effettivamente garantendo prestazioni in linea con il loro scopo previsto. I fornitori di software lo sanno e allineano i loro investimenti ingegneristici di conseguenza.
Questo mi porta al secondo aspetto del problema delle prestazioni: la mancanza di attenzione al design interno della soluzione. Attualmente, sono necessarie decisioni strategiche di software design per sfruttare il grosso dei miglioramenti hardware in corso. Tuttavia, una decisione di design è un’arma a doppio taglio: tanto potenzia quanto limita. Serve una leadership forte per impegnarsi, sia sul fronte commerciale che tecnico, in una decisione di design. L’indecisione è più facile, ma, come illustrato dalla stragrande maggioranza del software enterprise, le prestazioni (e l’UX in generale) ne risentono notevolmente.
Una trappola del software moderno (non solo di quello enterprise) è l’eccesso di layers. I dati vengono copiati, trasmessi, aggregati, sincronizzati, … attraverso decine di strati interni al software. Di conseguenza, la maggior parte delle risorse di calcolo viene sprecata gestendo il “impianto idraulico interno” che, di per sé, non apporta alcun valore aggiunto. In termini di design, la soluzione è sia semplice da concepire che difficile da eseguire: è necessario fare un uso parsimonioso dei componenti di terze parti, specialmente quelli che comportano un qualche tipo di strato7. Dal punto di vista del fornitore di software, aggiungere un ulteriore strato è il modo più rapido per integrare ulteriori “funzionalità interessanti” nel prodotto, a discapito del gonfiore.
Da Lokad, abbiamo optato per uno stack ampiamente integrato progettando l’intera piattaforma attorno a un nucleo di compilatore. Dal lato negativo, perdiamo l’opzione di collegare facilmente qualsiasi progetto open source a caso al nostro design. Le integrazioni rimangono possibili, ma di solito richiedono cambiamenti più profondi nel compilatore stesso. Dal lato positivo, otteniamo prestazioni “bare metal” che sono solitamente considerate inimmaginabili per quanto riguarda il software enterprise. Nel complesso, considerando che i componenti open source stanno invecchiando male, questo approccio si è rivelato particolarmente efficace nell’ultimo decennio8.
La multitenancy mutualizzata è un’altra scelta di design che impatta radicalmente le prestazioni, almeno da una prospettiva di “bang for the buck”. La maggior parte del software enterprise - il software supply chain essendo uno tra questi - ha requisiti di risorse di calcolo fortemente intermittenti. Per esempio, all’estremo dello spettro, c’è la numerical recipe per le previsioni, che viene eseguita solo una volta al giorno (o giù di lì) ma deve elaborare l’intero storico dei dati ogni singola volta. Avere un set statico di risorse di calcolo9 dedicato a un cliente è altamente inefficiente.
Ancora una volta, da Lokad, abbiamo optato per un’infrastruttura completamente mutualizzata. Questo approccio riduce i nostri costi operativi cloud pur offrendo prestazioni che altrimenti non sarebbero economicamente sostenibili (i costi cloud supererebbero i benefici della supply chain). Per garantire una gestione fluida di tutti i carichi di lavoro, abbiamo progettato un alto grado di “predictability” per il nostro consumo di risorse di calcolo. Il DSL di Lokad (domain-specific programming language), chiamato Envision, è stato progettato per supportare questo impegno. È per questo che intere classi di costrutti di programmazione - come i loop arbitrari - non esistono in Envision: tali costrutti non sono compatibili con i requisiti di “alta predictability” che comporta l’elaborazione dei dati della supply chain.
In conclusione, non aspettatevi che un sistema supply chain obeso si metta in forma tanto presto se non lo è già. Mentre l’hardware di calcolo continua a progredire, è già abbastanza veloce. Se il sistema è lento, molto probabilmente è perché antagonizza il suo hardware sottostante - non perché l’hardware sia carente. Risolvere il problema è possibile, ma si tratta per lo più di una questione di design. Purtroppo, il design centrale del software è una delle cose che tende a risultare quasi impossibile da rimediare nel software enterprise dopo la fase di progettazione del prodotto. È possibile riprendersi, come dimostra Microsoft, ma non tutte le aziende (sia fornitore che cliente) possono permettersi il decennio necessario per farlo.
-
Nel 2012, ho pubblicato ReceiptStream, un piccolo progetto open source per dimostrare che memorizzare circa un anno di storia delle transazioni di Walmart a livello di carrello su una scheda SD non solo era fattibile, ma poteva essere realizzato con poche centinaia di righe di codice. ↩︎
-
Cerchiamo di eseguire un recupero incrementale dei dati se i sistemi ce lo permettono. Tuttavia, il recupero iniziale dei dati tipicamente risale a 3-5 anni fa, poiché avere un po’ di profondità storica è davvero utile per l’analisi della stagionalità. ↩︎
-
I terminali console possono sembrare antiquati, ma se quei sistemi sono riusciti a resistere per diversi decenni, significa che probabilmente avevano alcune qualità positive, come risposte a bassa latenza. Non c’è niente di più esasperante che avere un’interfaccia web moderna e accattivante in cui ogni aggiornamento della pagina richiede diversi secondi. ↩︎
-
Non sto dicendo che terabyte di RAM non possano essere utili per l’ottimizzazione della supply chain - ripetendo la citazione fittizia erroneamente attribuita a Bill Gates secondo cui “640K dovrebbero essere sufficienti per chiunque”. Il mio punto è che un uso irragionevole delle risorse di calcolo rappresenta un’opportunità sprecata per impiegarle in modo migliore. A dicembre 2020, non vedo alcun motivo per cui sia necessaria una tale quantità di memoria, considerando la (mancanza di) sofisticatezza delle numerical recipe coinvolte nel cosiddetto paradigma del “in-memory computing”. ↩︎
-
I miglioramenti delle prestazioni, quasi esclusivamente guidati dal software, apportati da .NET Core 1, .NET Core 2, .NET Core 3 e .NET 5 sono esemplari in questo senso. Alcuni miglioramenti di velocità si basano su istruzioni SIMD (single instruction, multiple data), tuttavia tali istruzioni difficilmente possono essere qualificate come hardware “del futuro”, dato che la maggior parte delle CPU vendute nell’ultimo decennio le possiede già. ↩︎
-
Le vulnerabilità hardware come Meltdown hanno avuto un impatto negativo sulle prestazioni dell’hardware di calcolo esistente. In futuro ci si possono aspettare ulteriori problemi simili. ↩︎
-
I layers si presentano in tutte le forme e dimensioni. Docker, HDFS, Python, NumPy, Pandas, TensorFlow, Postgres, Jupyter … sono tutti componenti di primaria importanza, eppure ciascuno di questi introduce un proprio livello software. ↩︎
-
Quando ho avviato Lokad nel 2008, decisi di creare il mio motore di forecasting. Eppure, a quel tempo R era la moda. Nel 2012 era Hadoop. Nel 2014 erano Python e SciPy. Nel 2016 era Scikit. Nel 2018 era TensorFlow. Nel 2020 è Julia. ↩︎
-
Il test decisivo per identificare se un presunto SaaS (Software as a Service) sfrutta un’architettura multitenant mutualizzata consiste nel verificare se è possibile registrarsi per un account gratuito. Se il fornitore non riesce a fornire un account gratuito, allora è quasi certo che stia operando come ASP (Application Service Provider) invece che come SaaS. ↩︎