Gran entrevista amb Cliff Click, el pare de la compilació JIT a Java

Gran entrevista amb Cliff Click, el pare de la compilació JIT a JavaCliff Cliff — CTO de Cratus (sensors IoT per a la millora de processos), fundador i cofundador de diverses startups (incloses Rocket Realtime School, Neurensic i H2O.ai) amb diverses sortides reeixides. Cliff va escriure el seu primer compilador als 15 anys (Pascal per al TRS Z-80)! És més conegut pel seu treball a C2 a Java (el mar dels nodes IR). Aquest compilador va mostrar al món que JIT podia produir codi d'alta qualitat, que va ser un dels factors en l'aparició de Java com una de les principals plataformes de programari modernes. Aleshores, Cliff va ajudar a Azul Systems a construir un mainframe de 864 nuclis amb programari Java pur que admetia les pauses de GC en un munt de 500 gigabytes en 10 mil·lisegons. En general, Cliff va aconseguir treballar en tots els aspectes de la JVM.

 
Aquest habrapost és una gran entrevista amb Cliff. Parlarem dels següents temes:

  • Transició a optimitzacions de baix nivell
  • Com fer una gran refactorització
  • Model de costos
  • Formació en optimització de baix nivell
  • Exemples pràctics de millora del rendiment
  • Per què crear el vostre propi llenguatge de programació
  • Carrera d'enginyer de rendiment
  • Reptes tècnics
  • Una mica sobre l'assignació de registres i els nuclis múltiples
  • El repte més gran de la vida

Les entrevistes les realitzen:

  • Andrei Satarin d'Amazon Web Services. En la seva carrera, va aconseguir treballar en projectes completament diferents: va provar la base de dades distribuïda NewSQL a Yandex, un sistema de detecció de núvols a Kaspersky Lab, un joc multijugador a Mail.ru i un servei de càlcul de preus de divises a Deutsche Bank. Interessat a provar sistemes distribuïts i backend a gran escala.
  • Vladimir Sitnikov de Netcracker. Deu anys de treball en el rendiment i escalabilitat del sistema operatiu NetCracker, programari utilitzat pels operadors de telecomunicacions per automatitzar els processos de gestió d'equips de xarxa i xarxa. Interessat en problemes de rendiment de Java i Oracle Database. Autor de més d'una dotzena de millores de rendiment al controlador JDBC oficial de PostgreSQL.

Transició a optimitzacions de baix nivell

Andrés: Ets un gran nom en el món de la compilació JIT, Java i el treball de rendiment en general, oi? 

Penya-segat: És així!

Andrés: Comencem amb algunes preguntes generals sobre el treball de performance. Què en penseu de l'elecció entre optimitzacions d'alt nivell i de baix nivell com treballar a nivell de CPU?

Penya-segat: Sí, aquí tot és senzill. El codi més ràpid és el que no s'executa mai. Per tant, sempre cal començar des d'un alt nivell, treballar amb algorismes. Una notació O millor superarà una notació O pitjor, tret que hi intervenguin constants prou grans. Les coses de baix nivell van per últim. Normalment, si heu optimitzat prou bé la resta de la vostra pila i encara queden algunes coses interessants, és un nivell baix. Però, com començar des d'un alt nivell? Com saps que s'ha fet prou feina d'alt nivell? Bé... de cap manera. No hi ha receptes ja fetes. Heu d'entendre el problema, decidir què fareu (per no fer passos innecessaris en el futur) i després podeu descobrir el perfilador, que pot dir alguna cosa útil. En algun moment, tu mateix t'adones que t'has desfet de les coses innecessàries i és hora de fer un ajustament de baix nivell. Sens dubte, aquest és un tipus d'art especial. Hi ha molta gent que fa coses innecessàries, però es mou tan ràpid que no tenen temps per preocupar-se per la productivitat. Però això és fins que la pregunta sorgeix sense embuts. Normalment el 99% de les vegades a ningú li importa el que faig, fins al moment en què apareix una cosa important en el camí crític que a ningú li importa. I aquí tothom comença a molestar-te sobre "per què no va funcionar perfectament des del principi". En general, sempre hi ha alguna cosa a millorar en el rendiment. Però el 99% de les vegades no tens contactes! Només estàs intentant fer que alguna cosa funcioni i en el procés descobreixes què és important. Mai es pot saber per endavant que aquesta peça ha de ser perfecta, així que, de fet, has de ser perfecte en tot. Però això és impossible i no ho fas. Sempre hi ha moltes coses per arreglar, i això és completament normal.

Com fer una gran refactorització

Andrés: Com treballes en una actuació? Aquest és un problema transversal. Per exemple, mai has hagut de treballar en problemes que sorgeixen de la intersecció de moltes funcionalitats existents?

Penya-segat: Intento evitar-ho. Si sé que el rendiment serà un problema, hi penso abans de començar a codificar, especialment amb estructures de dades. Però sovint ho descobreixes molt més tard. I després has d'extremar mesures i fer el que jo anomeno "reescriure i conquerir": has d'agafar una peça prou gran. Part del codi encara s'haurà de reescriure a causa de problemes de rendiment o alguna altra cosa. Sigui quin sigui el motiu de la reescriptura del codi, gairebé sempre és millor reescriure una peça més gran que una peça més petita. En aquest moment, tothom comença a tremolar de por: "Déu meu, no pots tocar tant de codi!" Però, de fet, aquest enfocament gairebé sempre funciona molt millor. Heu d'assumir immediatament un gran problema, dibuixar un cercle gran al seu voltant i dir: reescriuré tot el que hi ha dins del cercle. La vora és molt més petita que el contingut que hi ha dins que cal substituir. I si aquesta delimitació de límits us permet fer el treball interior perfectament, teniu les mans lliures, feu el que vulgueu. Un cop enteneu el problema, el procés de reescriptura és molt més fàcil, així que feu un gran mos!
Al mateix temps, quan feu una reescriptura gran i us adoneu que el rendiment serà un problema, podeu començar a preocupar-vos immediatament per això. Això normalment es converteix en coses senzilles com "no copieu dades, gestioneu les dades de la manera més senzilla possible, feu-les petites". En les reescriptures grans, hi ha maneres estàndard de millorar el rendiment. I gairebé sempre giren al voltant de les dades.

Model de costos

Andrés: En un dels podcasts vas parlar dels models de costos en el context de la productivitat. Pots explicar què volies dir amb això?

Penya-segat: Certament. Vaig néixer en una època en què el rendiment del processador era extremadament important. I aquesta època torna de nou: el destí no està exempt d'ironia. Vaig començar a viure en l'època de les màquines de vuit bits; el meu primer ordinador funcionava amb 256 bytes. Exactament bytes. Tot era molt petit. S'havien de comptar les instruccions i, a mesura que vam començar a pujar per la pila de llenguatges de programació, els llenguatges van agafar més i més. Hi havia Assembler, després Basic, després C i C es van encarregar de molts detalls, com l'assignació de registres i la selecció d'instruccions. Però tot estava molt clar allà, i si fes un punter a una instància d'una variable, llavors obtindria càrrega i es coneix el cost d'aquesta instrucció. El maquinari produeix un cert nombre de cicles de màquina, de manera que la velocitat d'execució de diferents coses es pot calcular simplement sumant totes les instruccions que vas a executar. Cada comparació/prova/branca/trucada/càrrega/emmagatzematge es podria afegir i dir: aquest és el temps d'execució per a tu. Quan treballeu per millorar el rendiment, definitivament prestareu atenció a quins números corresponen a petits cicles calents. 
Però tan bon punt canvieu a Java, Python i coses semblants, us allunyeu molt ràpidament del maquinari de baix nivell. Quin és el cost de trucar a un getter a Java? Si JIT a HotSpot és correcte alineat, es carregarà, però si no ho ha fet, serà una trucada de funció. Com que la trucada està en un bucle calent, anul·larà totes les altres optimitzacions d'aquest bucle. Per tant, el cost real serà molt més elevat. I immediatament es perd la capacitat de mirar un tros de codi i entendre que l'hauríem d'executar en termes de velocitat de rellotge del processador, memòria i memòria cau utilitzada. Tot això només esdevé interessant si realment entres en l'actuació.
Ara ens trobem en una situació en què la velocitat del processador amb prou feines ha augmentat durant una dècada. Els vells temps han tornat! Ja no podeu comptar amb un bon rendiment d'un sol fil. Però si de sobte entres en la informàtica paral·lela, és increïblement difícil, tothom et mira com James Bond. Aquí solen produir-se acceleracions deu vegades en llocs on algú ha equivocat alguna cosa. La concurrència requereix molta feina. Per obtenir aquesta acceleració de XNUMX vegades, heu d'entendre el model de costos. Què i quant costa? I per fer-ho, heu d'entendre com s'adapta la llengua al maquinari subjacent.
Martin Thompson va triar una paraula fantàstica per al seu bloc Simpatia mecànica! Heu d'entendre què farà el maquinari, com ho farà exactament i per què fa el que fa en primer lloc. Amb això, és bastant fàcil començar a comptar instruccions i esbrinar cap a on va el temps d'execució. Si no tens la formació adequada, només busques un gat negre en una habitació fosca. Veig gent optimitzant el rendiment tot el temps que no té ni idea de què dimonis estan fent. Pateixen molt i no avancen gaire. I quan agafo el mateix codi, introdueixo un parell de petits trucs i aconsegueixo una velocitat de cinc o deu vegades, em diuen: bé, això no és just, ja sabíem que eres millor. Increïble. De què estic parlant... el model de costos és sobre quin tipus de codi escriu i amb quina velocitat s'executa de mitjana en el panorama general.

Andrés: I com pots mantenir aquest volum al teu cap? Això s'aconsegueix amb més experiència, o? D'on ve aquesta experiència?

Penya-segat: Bé, no vaig obtenir la meva experiència de la manera més fàcil. Vaig programar a Assembly en els dies en què podies entendre totes les instruccions. Sembla estúpid, però des d'aleshores el conjunt d'instruccions Z80 sempre ha quedat al meu cap, a la meva memòria. No recordo els noms de les persones en un minut després de parlar, però recordo el codi escrit fa 40 anys. És curiós, sembla una síndrome"científic idiota».

Formació en optimització de baix nivell

Andrés: Hi ha una manera més fàcil d'entrar?

Penya-segat: Sí i no. El maquinari que fem servir no ha canviat gaire amb el pas del temps. Tothom utilitza x86, a excepció dels telèfons intel·ligents Arm. Si no esteu fent algun tipus d'incrustació hardcore, esteu fent el mateix. D'acord, a continuació. Les instruccions tampoc han canviat durant segles. Heu d'anar a escriure alguna cosa a l'Assemblea. No gaire, però suficient per començar a entendre. Estàs somrient, però parlo completament seriosament. Cal entendre la correspondència entre llenguatge i maquinari. Després d'això, heu d'anar a escriure una mica i fer un petit compilador de joguines per a un petit llenguatge de joguina. Semblant a una joguina significa que s'ha de fer en un període de temps raonable. Pot ser molt senzill, però ha de generar instruccions. L'acte de generar una instrucció us ajudarà a entendre el model de cost del pont entre el codi d'alt nivell que tothom escriu i el codi de màquina que s'executa al maquinari. Aquesta correspondència es gravarà al cervell en el moment en què s'escriu el compilador. Fins i tot el compilador més senzill. Després d'això, podeu començar a mirar Java i el fet que el seu abisme semàntic és molt més profund, i és molt més difícil construir ponts sobre ell. A Java, és molt més difícil entendre si el nostre pont ha resultat bo o dolent, què farà que es desfà i què no. Però necessiteu algun tipus de punt de partida on mireu el codi i entengueu: "sí, aquest captador s'hauria d'incorporar cada vegada". I després resulta que de vegades això passa, excepte en la situació en què el mètode es fa massa gran i el JIT comença a integrar-ho tot. El rendiment d'aquests llocs es pot predir a l'instant. Normalment, els captadors funcionen bé, però després mireu grans bucles calents i us adoneu que hi ha algunes trucades de funció flotant per aquí que no saben què estan fent. Aquest és el problema de l'ús generalitzat dels getters, el motiu pel qual no estan inlineats és que no està clar si són getters. Si teniu una base de codi súper petita, simplement podeu recordar-la i després dir: això és un getter i aquest és un setter. En una gran base de codi, cada funció viu la seva pròpia història, que, en general, ningú no coneix. El perfilador diu que hem perdut el 24% del temps en algun bucle i per entendre què fa aquest bucle, hem de mirar cada funció dins. És impossible entendre això sense estudiar la funció, i això alenteix seriosament el procés de comprensió. Per això no faig servir getters i setters, he arribat a un nou nivell!
On aconseguir el model de costos? Bé, pots llegir alguna cosa, és clar... Però crec que la millor manera és actuar. Fer un petit compilador serà la millor manera d'entendre el model de costos i ajustar-lo al vostre propi cap. Un petit compilador que seria adequat per programar un microones és una tasca per a un principiant. Bé, vull dir, si ja tens habilitats de programació, això hauria de ser suficient. Totes aquestes coses, com ara analitzar una cadena que teniu com una mena d'expressió algebraica, extreure instruccions per a operacions matemàtiques d'allà en l'ordre correcte, prendre els valors correctes dels registres, tot això es fa alhora. I mentre ho feu, quedarà imprès al vostre cervell. Crec que tothom sap què fa un compilador. I això donarà una comprensió del model de costos.

Exemples pràctics de millora del rendiment

Andrés: En què més hauries de prestar atenció quan treballes en productivitat?

Penya-segat: Estructures de dades. Per cert, sí, fa temps que no imparteixo aquestes classes... Escola de coets. Va ser divertit, però va requerir molt d'esforç, i també tinc una vida! D'ACORD. Així doncs, en una de les classes grans i interessants, "A on va el teu rendiment", vaig posar un exemple als estudiants: es van llegir dos gigabytes i mig de dades fintech d'un fitxer CSV i després van haver de calcular el nombre de productes venuts. . Dades regulars del mercat de paparres. Paquets UDP convertits a format de text des dels anys 70. Chicago Mercantile Exchange: tot tipus de coses com la mantega, el blat de moro, la soja, coses així. Calia comptar aquests productes, el nombre de transaccions, el volum mitjà de moviment de fons i mercaderies, etc. Són matemàtiques comercials bastant senzilles: trobeu el codi del producte (és a dir, 1-2 caràcters a la taula hash), obteniu la quantitat, afegiu-lo a un dels conjunts comercials, afegiu volum, afegiu valor i un parell de coses més. Matemàtiques molt senzilles. La implementació de la joguina va ser molt senzilla: tot està en un fitxer, llegeixo el fitxer i el passo, dividint els registres individuals en cadenes de Java, buscant-hi les coses necessàries i sumant-les segons les matemàtiques descrites anteriorment. I funciona a poca velocitat.

Amb aquest enfocament, és obvi què està passant, i la informàtica paral·lela no ajudarà, oi? Resulta que es pot aconseguir quintuplicar el rendiment simplement escollint les estructures de dades adequades. I això sorprèn fins i tot als programadors experimentats! En el meu cas particular, el truc era que no hauríeu de fer assignacions de memòria en un bucle calent. Bé, aquesta no és tota la veritat, però en general, no hauríeu de destacar "un cop a X" quan X és prou gran. Quan X és de dos gigabytes i mig, no hauríeu d'assignar res "un cop per lletra", o "un cop per línia", o "un cop per camp", res semblant. Aquí és on es passa el temps. Com funciona això? Imagineu-me fent una trucada String.split() o BufferedReader.readLine(). Readline fa una cadena a partir d'un conjunt de bytes que van passar per la xarxa, una vegada per cada línia, per a cadascun dels centenars de milions de línies. Agafo aquesta línia, l'analizo i la llenço. Per què el llençaré? Bé, ja ho he processat, això és tot. Per tant, per cada byte llegit d'aquests 2.7G, s'escriuran dos caràcters a la línia, és a dir, ja 5.4G, i no els necessito per a res més, així que es llençaran. Si ens fixem en l'amplada de banda de la memòria, carreguem 2.7 G que passa per la memòria i el bus de memòria del processador, i després s'envia el doble a la línia que es troba a la memòria, i tot això es desfà quan es crea cada línia nova. Però necessito llegir-lo, el maquinari el llegeix, encara que tot s'esquilli més tard. I l'he d'escriure perquè he creat una línia i les memòria cau estan plenes; la memòria cau no pot acomodar 2.7 G. Per tant, per cada byte que llegeixo, llegeixo dos bytes més i escric dos bytes més, i al final tenen una proporció de 4:1: en aquesta proporció estem malgastant ample de banda de memòria. I després resulta que si ho faig String.split() – Aquesta no és l'última vegada que faig això, pot haver-hi altres 6-7 camps a dins. Així, el codi clàssic de llegir CSV i després analitzar les cadenes provoca un malbaratament d'ample de banda de memòria d'uns 14:1 en relació amb el que realment voldríeu tenir. Si llenceu aquestes seleccions, podeu obtenir una acceleració de cinc vegades.

I no és tan difícil. Si mireu el codi des de l'angle correcte, tot esdevé bastant senzill un cop us adoneu del problema. No hauríeu de deixar d'assignar memòria del tot: l'únic problema és que assigneu alguna cosa i immediatament mor, i al llarg del camí crema un recurs important, que en aquest cas és l'amplada de banda de la memòria. I tot això provoca una caiguda de la productivitat. A x86 normalment necessiteu gravar activament els cicles del processador, però aquí heu cremat tota la memòria molt abans. La solució és reduir la quantitat de descàrrega. 
L'altra part del problema és que si executeu el perfilador quan s'esgota la banda de memòria, just quan passa, normalment esteu esperant que la memòria cau torni perquè està plena d'escombraries que acabeu de produir, totes aquestes línies. Per tant, cada operació de càrrega o emmagatzematge es torna lenta, perquè provoquen errors de memòria cau: tota la memòria cau s'ha tornat lenta, esperant que les escombraries la surtin. Per tant, el perfilador només mostrarà un soroll aleatori càlid escampat al llarg de tot el bucle; no hi haurà cap instrucció ni lloc al codi per separat. Només soroll. I si ens fixem en els cicles GC, tots són de la generació jove i súper ràpids: microsegons o mil·lisegons com a màxim. Després de tot, tot aquest record mor a l'instant. Dediqueu milers de milions de gigabytes, i ell els talla, els talla i els torna a tallar. Tot això passa molt ràpidament. Resulta que hi ha cicles de GC barats, soroll càlid al llarg de tot el cicle, però volem aconseguir una velocitat 5x. En aquest moment, alguna cosa hauria de tancar-se al teu cap i sonar: "Per què és això?!" El desbordament de la tira de memòria no es mostra al depurador clàssic; heu d'executar el depurador del comptador de rendiment del maquinari i veure-ho vosaltres mateixos i directament. Però això no es pot sospitar directament d'aquests tres símptomes. El tercer símptoma és quan mireu el que destaqueu, pregunteu al perfilador i ell respon: "Vas fer mil milions de files, però el GC va funcionar gratis". Tan aviat com això passa, t'adones que has creat massa objectes i has cremat tot el carril de memòria. Hi ha una manera d'esbrinar-ho, però no és obvi. 

El problema està en l'estructura de dades: l'estructura nua subjacent a tot el que passa, és massa gran, és de 2.7 G al disc, de manera que fer una còpia d'aquesta cosa és molt indesitjable: voleu carregar-la immediatament des del buffer de bytes de xarxa. als registres, per no llegir-escriure a la línia d'anada i tornada cinc vegades. Malauradament, Java no us ofereix aquesta biblioteca com a part del JDK per defecte. Però això és trivial, oi? Essencialment, es tracta de 5-10 línies de codi que s'utilitzaran per implementar el vostre propi carregador de cadenes de memòria intermèdia, que repeteix el comportament de la classe de cadenes, alhora que és un embolcall al voltant del buffer de bytes subjacent. Com a resultat, resulta que esteu treballant gairebé com amb cadenes, però de fet els punters a la memòria intermèdia s'estan movent allà i els bytes en brut no es copien enlloc i, per tant, els mateixos buffers es reutilitzen una i altra vegada, i el sistema operatiu està encantat d'assumir les coses per a les quals està dissenyat, com ara la doble memòria intermèdia oculta d'aquests buffers de bytes, i ja no esteu triturant un flux interminable de dades innecessàries. Per cert, enteneu que quan es treballa amb GC, es garanteix que cada assignació de memòria no serà visible per al processador després de l'últim cicle de GC? Per tant, tot això no pot estar a la memòria cau, i llavors es produeix un error 100% garantit. Quan es treballa amb un punter, a x86, restar un registre de la memòria requereix 1-2 cicles de rellotge, i tan aviat com això succeeix, pagues, pagues, pagues, perquè la memòria està activada. NOU cachés – i aquest és el cost de l'assignació de memòria. Valor real.

En altres paraules, les estructures de dades són el més difícil de canviar. I un cop us adoneu que heu escollit l'estructura de dades equivocada que acabarà amb el rendiment més endavant, normalment hi ha molta feina per fer, però si no ho feu, les coses empitjoraran. En primer lloc, cal pensar en les estructures de dades, això és important. El cost principal aquí recau en estructures de dades grans, que comencen a utilitzar-se a l'estil de "Vaig copiar l'estructura de dades X a l'estructura de dades Y perquè m'agrada més la forma de Y". Però l'operació de còpia (que sembla barata) en realitat malgasta ample de banda de memòria i aquí és on s'enterra tot el temps d'execució perdut. Si tinc una cadena gegant de JSON i vull convertir-la en un arbre DOM estructurat de POJOs o alguna cosa, l'operació d'analitzar aquesta cadena i construir el POJO, i després accedir-hi de nou més tard, comportarà un cost innecessari; no barat. Excepte si corres per POJO molt més sovint que no pas per una corda. En canvi, podeu provar de desxifrar la cadena i extreure només el que necessiteu d'allà, sense convertir-lo en cap POJO. Si tot això succeeix en un camí des del qual es requereix el màxim rendiment, no hi ha POJO per a vostè, cal que d'alguna manera caveu directament a la línia.

Per què crear el vostre propi llenguatge de programació

Andrés: Vas dir que per entendre el model de costos, cal escriure el teu propi llenguatge...

Penya-segat: No és un llenguatge, sinó un compilador. Un llenguatge i un compilador són dues coses diferents. La diferència més important està al teu cap. 

Andrés: Per cert, pel que jo sé, estàs experimentant amb la creació dels teus propis idiomes. Per a què?

Penya-segat: Perquè puc! Estic semi-jubilat, així que aquesta és la meva afició. He estat implementant els idiomes d'altres persones tota la meva vida. També he treballat molt el meu estil de codificació. I també perquè veig problemes en altres idiomes. Veig que hi ha millors maneres de fer coses familiars. I els utilitzaria. Estic cansat de veure problemes en mi mateix, en Java, en Python, en qualsevol altre llenguatge. Ara escric a React Native, JavaScript i Elm com un hobby que no es tracta de jubilació, sinó de treball actiu. També escric en Python i, molt probablement, continuaré treballant en l'aprenentatge automàtic per a backends Java. Hi ha molts idiomes populars i tots tenen característiques interessants. Cadascú és bo a la seva manera i podeu intentar reunir totes aquestes característiques. Per tant, estic estudiant coses que m'interessen, el comportament del llenguatge, intentant trobar una semàntica raonable. I fins ara ho estic aconseguint! En aquests moments estic lluitant amb la semàntica de la memòria, perquè vull tenir-la com en C i Java, i obtenir un model de memòria fort i una semàntica de memòria per a càrregues i emmagatzematges. Al mateix temps, tingueu inferència de tipus automàtica com a Haskell. Aquí, estic intentant barrejar la inferència de tipus Haskell amb el treball de memòria tant en C com en Java. Això és el que he estat fent durant els últims 2-3 mesos, per exemple.

Andrés: Si construeixes un llenguatge que pren millors aspectes d'altres llengües, creus que algú farà el contrari: agafa les teves idees i utilitza-les?

Penya-segat: així és exactament com apareixen els nous idiomes! Per què Java és semblant a C? Com que C tenia una bona sintaxi que tothom entenia i Java es va inspirar en aquesta sintaxi, afegint seguretat de tipus, comprovació de límits de matriu, GC, i també van millorar algunes coses de C. Van afegir les seves. Però es van inspirar molt, oi? Tothom s'aixeca sobre les espatlles dels gegants que han vingut abans que vostè, així és com s'avança.

Andrés: Tal com ho entenc, el vostre idioma serà segur per a la memòria. Heu pensat a implementar alguna cosa com un verificador de préstecs de Rust? L'has mirat, què en penses?

Penya-segat: Bé, he estat escrivint C durant anys, amb tot això malloc i gratuït, i gestionant manualment tota la vida. Ja sabeu, el 90-95% del temps de vida controlat manualment té la mateixa estructura. I és molt, molt dolorós fer-ho manualment. M'agradaria que el compilador simplement us digués què està passant allà i què heu aconseguit amb les vostres accions. Per a algunes coses, el verificador de préstecs ho fa fora de la caixa. I hauria de mostrar informació automàticament, entendre-ho tot i ni tan sols carregar-me amb la presentació d'aquesta comprensió. Ha de fer almenys una anàlisi d'escapament local, i només si falla, llavors ha d'afegir anotacions de tipus que descriguin la vida útil, i aquest esquema és molt més complex que un verificador de préstecs o, de fet, qualsevol verificador de memòria existent. L'elecció entre "tot està bé" i "no entenc res" - no, hi ha d'haver alguna cosa millor. 
Per tant, com a algú que ha escrit molt de codi en C, crec que tenir suport per al control automàtic de tota la vida és el més important. També estic fart de quant Java utilitza memòria i la principal queixa és el GC. Quan assigneu memòria a Java, no recuperareu la memòria que era local en l'últim cicle de GC. Aquest no és el cas dels idiomes amb una gestió de memòria més precisa. Si truqueu a malloc, obtindreu immediatament la memòria que normalment s'acabava d'utilitzar. Normalment fas algunes coses temporals amb la memòria i la retornes immediatament. I de seguida torna a la piscina malloc, i el següent cicle malloc la torna a treure. Per tant, l'ús real de la memòria es redueix al conjunt d'objectes vius en un moment determinat, més les fuites. I si tot no es filtra d'una manera completament indecent, la major part de la memòria acaba a la memòria cau i al processador, i funciona ràpidament. Però requereix molta gestió manual de la memòria amb malloc i trucada gratuïta en l'ordre correcte, al lloc correcte. Rust pot gestionar-ho correctament per si mateix i, en molts casos, ofereix un rendiment encara millor, ja que el consum de memòria es redueix només al càlcul actual, en lloc d'esperar al següent cicle GC per alliberar memòria. Com a resultat, vam aconseguir una manera molt interessant de millorar el rendiment. I bastant potent, vull dir, vaig fer aquestes coses quan processava dades per a fintech, i això em va permetre augmentar l'acceleració d'unes cinc vegades. Això és un gran impuls, sobretot en un món on els processadors no són més ràpids i encara estem esperant millores.

Carrera d'enginyer de rendiment

Andrés: També m'agradaria preguntar sobre les carreres en general. Vau agafar protagonisme amb el vostre treball JIT a HotSpot i després us vau traslladar a Azul, que també és una empresa JVM. Però ja estàvem treballant més en maquinari que en programari. I de sobte van passar a Big Data i Machine Learning, i després a la detecció de fraus. Com va passar això? Són àrees de desenvolupament molt diferents.

Penya-segat: He estat programant durant força temps i he aconseguit fer moltes classes diferents. I quan la gent diu: "Oh, ets tu qui va fer JIT per Java!", sempre és divertit. Però abans d'això, estava treballant en un clon de PostScript, el llenguatge que Apple va utilitzar una vegada per a les seves impressores làser. I abans vaig fer una implementació del llenguatge Forth. Crec que el tema comú per a mi és el desenvolupament d'eines. Tota la meva vida he estat fent eines amb les quals altres persones escriuen els seus programes genials. Però també vaig estar involucrat en el desenvolupament de sistemes operatius, controladors, depuradors a nivell de nucli, llenguatges per al desenvolupament del sistema operatiu, que van començar trivials, però amb el temps es van fer cada cop més complexos. Però el tema principal segueix sent el desenvolupament d'eines. Gran part de la meva vida va passar entre Azul i Sun, i va ser sobre Java. Però quan vaig entrar al Big Data i a l'aprenentatge automàtic, em vaig tornar a posar el barret de luxe i vaig dir: "Oh, ara tenim un problema no trivial, i hi ha moltes coses interessants que estan passant i gent fent coses". Aquest és un gran camí de desenvolupament a seguir.

Sí, m'agrada molt la informàtica distribuïda. La meva primera feina va ser com a estudiant de C, en un projecte publicitari. Es va distribuir informàticament en xips Zilog Z80 que recopilaven dades per a OCR analògic, produïts per un analitzador analògic real. Era un tema genial i completament boig. Però hi havia problemes, alguna part no es reconeixia correctament, així que calia treure una foto i ensenyar-la a una persona que ja sabia llegir amb els ulls i informar del que deia, i per tant hi havia feines amb dades, i aquestes feines. tenien la seva pròpia llengua. Hi havia un backend que processava tot això: Z80s funcionant en paral·lel amb terminals vt100 en funcionament, un per persona, i hi havia un model de programació paral·lel al Z80. Algun tros comú de memòria compartit per tots els Z80 dins d'una configuració en estrella; El pla posterior també es va compartir i la meitat de la memòria RAM es compartia dins de la xarxa i una altra meitat era privada o anava a una altra cosa. Un sistema distribuït en paral·lel significativament complex amb memòria compartida... semi-compartida. Quan va ser això... ni recordo, en algun lloc a mitjans dels anys 80. Fa força temps. 
Sí, suposem que fa 30 anys fa molt de temps. Els problemes relacionats amb la informàtica distribuïda existeixen des de fa molt de temps, la gent fa temps que està en guerra amb Beowulf-clusters. Aquests clústers semblen... Per exemple: hi ha Ethernet i el vostre x86 ràpid està connectat a aquesta Ethernet, i ara voleu obtenir una memòria compartida falsa, perquè ningú no podia fer codificació de computació distribuïda aleshores, era massa difícil i, per tant, hi havia era memòria compartida falsa amb pàgines de memòria de protecció a x86, i si escriviu a aquesta pàgina, aleshores vam dir a altres processadors que si accedeixen a la mateixa memòria compartida, caldria carregar-la des de vosaltres i, per tant, com un protocol per donar suport. va aparèixer la coherència de la memòria cau i el programari per a això. Concepte interessant. El veritable problema, és clar, era una altra cosa. Tot això va funcionar, però ràpidament vau tenir problemes de rendiment, perquè ningú entenia els models de rendiment a un nivell prou bo: quins patrons d'accés a la memòria hi havia, com assegurar-vos que els nodes no es fessin ping sense parar entre ells, etc.

El que em va ocórrer a H2O és que són els mateixos desenvolupadors els responsables de determinar on s'amaga el paral·lelisme i on no. Vaig idear un model de codificació que feia que escriure codi d'alt rendiment fos fàcil i senzill. Però escriure codi d'execució lenta és difícil, es veurà malament. Heu de tractar seriosament d'escriure codi lent, haureu d'utilitzar mètodes no estàndard. El codi de frenada és visible a primera vista. Com a resultat, normalment escriu codi que s'executa ràpidament, però has d'esbrinar què fer en el cas de la memòria compartida. Tot això està lligat a matrius grans i el comportament és similar a les matrius grans no volàtils en Java paral·lel. Vull dir, imagineu que dos fils escriuen en una matriu paral·lela, un d'ells guanya i l'altre, en conseqüència, perd, i no saps quin és quin. Si no són volàtils, l'ordre pot ser el que vulgueu, i això funciona molt bé. La gent es preocupa molt per l'ordre de les operacions, col·loquen volàtils als llocs adequats i esperen problemes de rendiment relacionats amb la memòria als llocs adequats. En cas contrari, simplement escriurien codi en forma de bucles d'1 a N, on N són alguns bilions, amb l'esperança que tots els casos complexos es tornin automàticament paral·lels, i això no funciona. Però a H2O això no és ni Java ni Scala; podeu considerar-lo "Java menys menys" si voleu. Aquest és un estil de programació molt clar i és similar a escriure codi C o Java senzill amb bucles i matrius. Però al mateix temps, la memòria es pot processar en terabytes. Encara faig servir H2O. El faig servir de tant en tant en diferents projectes, i segueix sent el més ràpid, desenes de vegades més ràpid que els seus competidors. Si feu Big Data amb dades en columna, és molt difícil superar H2O.

Reptes tècnics

Andrés: Quin ha estat el teu repte més gran en tota la teva carrera?

Penya-segat: Estem discutint la part tècnica o no tècnica del tema? Jo diria que els reptes més grans no són els tècnics. 
Pel que fa als reptes tècnics. Simplement els vaig derrotar. Ni tan sols sé quina va ser la més gran, però n'hi havia de força interessants que van costar força temps, lluita mental. Quan vaig anar a Sun, estava segur que faria un compilador ràpid, i un grup de gent gran va dir com a resposta que no ho tindria mai. Però vaig seguir aquest camí, vaig escriure un compilador a l'assignador de registres i va ser bastant ràpid. Era tan ràpid com el C1 modern, però l'assignador era molt més lent aleshores i, en retrospectiva, era un gran problema d'estructura de dades. El necessitava per escriure un assignador de registres gràfics i no entenia el dilema entre l'expressivitat del codi i la velocitat, que existia en aquella època i que era molt important. Va resultar que l'estructura de dades acostuma a superar la mida de la memòria cau en x86 d'aquella època i, per tant, si inicialment vaig suposar que l'assignador de registre funcionaria entre el 5 i el 10 per cent del temps total de fluctuació, en realitat va resultar ser 50 per cent.

Amb el pas del temps, el compilador es va tornar més net i més eficient, va deixar de generar codi terrible en més casos i el rendiment va començar a assemblar-se cada cop més al que produeix un compilador C. A menys, per descomptat, escriviu alguna merda que ni tan sols C accelera. . Si escriviu codi com C, obtindreu un rendiment com C en més casos. I com més anàveu, més sovint obteniu codi que coincideix asintòticament amb el nivell C, l'assignador de registres començava a semblar una cosa completa... independentment de si el vostre codi s'executa ràpid o lent. Vaig continuar treballant en l'assignador per fer-lo fer millors seleccions. Va ser cada cop més lent, però va donar un rendiment cada cop millor en els casos en què ningú més podia fer front. Podria submergir-me en un assignador de registres, enterrar-hi un mes de feina i, de sobte, tot el codi començaria a executar-se un 5% més ràpid. Això va passar una rere l'altra i l'assignador del registre es va convertir en una mena d'obra d'art: tothom l'estimava o l'odiava, i la gent de l'acadèmia feia preguntes sobre el tema "per què es fa tot d'aquesta manera", per què no? exploració de línia, i quina és la diferència. La resposta segueix sent la mateixa: un repartidor basat en la coloració de gràfics més un treball molt acurat amb el codi de memòria intermèdia equival a una arma de la victòria, la millor combinació que ningú pot derrotar. I això és una cosa poc evident. Tota la resta que hi fa el compilador són coses força estudiades, encara que també s'han portat a nivell d'art. Sempre vaig fer coses que havien de convertir el compilador en una obra d'art. Però res d'això va ser extraordinari, excepte l'assignador de registres. El truc és anar amb compte reduir sota càrrega i, si això passa (puc explicar-ho amb més detall si està interessat), això vol dir que es pot enfilar de manera més agressiva, sense el risc de caure en un torçament en el calendari d'actuació. En aquells dies, hi havia un munt de compiladors a gran escala, penjats amb adorns i xiulets, que tenien assignadors de registre, però ningú més podia fer-ho.

El problema és que si afegiu mètodes subjectes a inline, augmentant i augmentant l'àrea d'inline, el conjunt de valors utilitzats supera a l'instant el nombre de registres i heu de tallar-los. El nivell crític sol arribar quan l'assignador es rendeix, i un bon candidat per a un vessament val un altre, vendreu algunes coses generalment salvatges. El valor d'inlining aquí és que perds part de la sobrecàrrega, la sobrecàrrega per trucar i desar, pots veure els valors dins i pots optimitzar-los encara més. El cost de l'inserció és que es formen un gran nombre de valors en viu i, si el vostre assignador de registre s'esgota més del necessari, es perd immediatament. Per tant, la majoria dels distribuïdors tenen un problema: quan l'inline travessa una determinada línia, tot el món comença a reduir-se i la productivitat es pot tirar pel vàter. Els que implementen el compilador afegeixen algunes heurístiques: per exemple, aturar l'inline, començant per una mida prou gran, ja que les assignacions ho arruïnaran tot. Així és com es forma una torsió en el gràfic de rendiment: tu en línia, en línia, el rendiment creix lentament, i després boom! - cau com un gat ràpid perquè has folrat massa. Així funcionava tot abans de l'arribada de Java. Java requereix molt més en línia, així que vaig haver de fer que el meu assignador sigui molt més agressiu perquè s'anivella en lloc de bloquejar-se, i si enlineeu massa, comença a vessar, però després encara arriba el moment de "no més vessar". Aquesta és una observació interessant i em va sorgir del no-res, no és evident, però va donar els seus fruits. Vaig adoptar una línia agressiva i em va portar a llocs on el rendiment de Java i C treballen colze al costat. Estan molt a prop: puc escriure codi Java que sigui significativament més ràpid que el codi C i coses així, però de mitjana, en el panorama general de les coses, són aproximadament comparables. Crec que part d'aquest mèrit és l'assignador de registres, que em permet integrar-me de la manera més estúpida possible. Acabo d'incorporar tot el que veig. La pregunta aquí és si l'assignador funciona bé, si el resultat és un codi de treball intel·ligent. Aquest va ser un gran repte: entendre tot això i fer-ho funcionar.

Una mica sobre l'assignació de registres i els nuclis múltiples

Vladimir: problemes com l'assignació de registres semblen una mena de tema etern i sense fi. Em pregunto si mai hi ha hagut una idea que semblava prometedora i que després va fracassar a la pràctica?

Penya-segat: Per descomptat! L'assignació de registres és una àrea en la qual s'intenta trobar algunes heurístiques per resoldre un problema NP-complet. I mai es pot aconseguir una solució perfecta, oi? Això és senzillament impossible. Mira, la compilació Ahead of Time - també funciona malament. La conversa aquí tracta sobre alguns casos mitjans. Sobre el rendiment típic, perquè pugueu anar a mesurar quelcom que creieu que és un bon rendiment típic; després de tot, esteu treballant per millorar-lo! L'assignació de registres és un tema sobre el rendiment. Un cop tens el primer prototip, funciona i pinta el que cal, comença el treball de rendiment. Cal aprendre a mesurar bé. Per què és important? Si teniu dades clares, podeu mirar diferents àrees i veure: sí, aquí va ser útil, però allà és on es va trencar tot! Surten algunes bones idees, afegeixes noves heurístiques i de sobte tot comença a funcionar una mica millor de mitjana. O no comença. Vaig tenir un munt de casos en què estàvem lluitant pel rendiment del cinc per cent que diferenciava el nostre desenvolupament de l'assignador anterior. I cada vegada es veu així: en algun lloc es guanya, en algun lloc es perd. Si disposeu de bones eines d'anàlisi del rendiment, podeu trobar les idees perdudes i comprendre per què fracassen. Potser val la pena deixar-ho tot tal com està, o potser prendre un enfocament més seriós per posar a punt, o sortir i arreglar alguna cosa més. És un munt de coses! Vaig fer aquest truc genial, però també necessito aquest, i aquest i aquest, i la seva combinació total ofereix algunes millores. I els solitaris poden fracassar. Aquesta és la naturalesa del treball de rendiment en problemes NP-complets.

Vladimir: Un té la sensació que coses com pintar en repartidors són un problema que ja s'ha resolt. Bé, està decidit per tu, a jutjar pel que estàs dient, així que val la pena llavors...

Penya-segat: No es resol com a tal. Sou vosaltres qui heu de convertir-ho en “solucionat”. Hi ha problemes difícils i s'han de resoldre. Un cop fet això, és hora de treballar la productivitat. Heu d'enfocar aquest treball en conseqüència: fer benchmarks, recopilar mètriques, explicar situacions en què, quan vau tornar a una versió anterior, el vostre vell hack va començar a funcionar de nou (o viceversa, es va aturar). I no et rendeixis fins aconseguir alguna cosa. Com ja he dit, si hi ha idees genials que no van funcionar, però en l'àmbit de l'assignació de registres d'idees és aproximadament infinit. Podeu, per exemple, llegir publicacions científiques. Encara que ara aquesta zona ha començat a avançar molt més lentament i s'ha quedat més clar que en la seva joventut. No obstant això, hi ha innombrables persones que treballen en aquest camp i totes les seves idees val la pena provar-les, totes estan esperant a les bandes. I no pots dir com són de bons si no els proves. Què tan bé s'integren amb tota la resta del vostre assignador, perquè un assignador fa moltes coses i algunes idees del vostre assignador específic no funcionaran, però en un altre assignador ho faran fàcilment. La principal manera de guanyar per a l'assignador és treure les coses lentes fora del camí principal i obligar-les a dividir-se al llarg dels límits dels camins lents. Així que si voleu executar un GC, preneu el camí lent, desoptimitzeu, llenceu una excepció, totes aquestes coses, ja sabeu que aquestes coses són relativament rares. I són realment rars, vaig comprovar. Fes feina addicional i elimina moltes de les restriccions d'aquests camins lents, però realment no importa perquè són lents i poc transitats. Per exemple, un punter nul, no passa mai, oi? Heu de tenir diversos camins per a coses diferents, però no haurien d'interferir amb el principal. 

Vladimir: Què en penseu dels multi-nuclis, quan hi ha milers de nuclis alhora? És això una cosa útil?

Penya-segat: L'èxit de la GPU demostra que és força útil!

Vladimir: Són força especialitzats. Què passa amb els processadors de propòsit general?

Penya-segat: Bé, aquest era el model de negoci de Azul. La resposta va tornar en una època en què la gent realment estimava el rendiment previsible. Aleshores era difícil escriure codi paral·lel. El model de codificació H2O és altament escalable, però no és un model de propòsit general. Potser una mica més general que quan s'utilitza una GPU. Estem parlant de la complexitat de desenvolupar una cosa així o de la complexitat d'utilitzar-la? Per exemple, Azul em va ensenyar una lliçó interessant, una mica poc òbvia: els petits cachés són normals. 

El repte més gran de la vida

Vladimir: Què passa amb els reptes no tècnics?

Penya-segat: El repte més gran era no ser... amable i simpàtic amb la gent. I com a resultat, em vaig trobar constantment en situacions extremadament conflictives. Aquells en què sabia que les coses anaven malament, però no sabia com avançar amb aquells problemes i no els podia gestionar. D'aquesta manera van sorgir molts problemes a llarg termini, que van durar dècades. El fet que Java tingui compiladors C1 i C2 és una conseqüència directa d'això. El fet que no hi hagués cap compilació multinivell a Java durant deu anys consecutius també és una conseqüència directa. És obvi que necessitàvem un sistema així, però no és obvi per què no existia. Vaig tenir problemes amb un enginyer... o un grup d'enginyers. Hi havia una vegada, quan vaig començar a treballar a Sun, estava... D'acord, no només llavors, en general sempre tinc la meva pròpia opinió sobre tot. I vaig pensar que era cert que només podríeu prendre aquesta veritat vostra i dir-la de front. Sobretot perquè tenia una raó sorprenent la majoria del temps. I si no t'agrada aquest plantejament... sobretot si estàs equivocat evidentment i fas tonterias... En general, poca gent podria tolerar aquesta forma de comunicació. Encara que alguns podrien, com jo. He construït tota la meva vida sobre principis meritocràtics. Si em mostres alguna cosa malament, de seguida em donaré la volta i diré: has dit ximpleries. Al mateix temps, és clar, demano disculpes i tot això, n'anotaré els mèrits, si n'hi ha, i prendré altres accions correctes. D'altra banda, tinc una raó sorprenent sobre un percentatge sorprenentment gran del temps total. I no funciona molt bé en les relacions amb la gent. No estic intentant ser amable, però estic fent la pregunta sense embuts. "Això no funcionarà mai, perquè un, dos i tres". I van dir: "Oh!" Hi va haver altres conseqüències que probablement era millor ignorar: per exemple, les que van provocar el divorci de la meva dona i deu anys de depressió després d'això.

El repte és una lluita amb les persones, amb la seva percepció del que pots fer o no, què és important i què no. Hi havia molts reptes sobre l'estil de codificació. Encara escric molt de codi, i en aquells dies fins i tot vaig haver de frenar perquè feia massa tasques paral·leles i les feia malament, en lloc de centrar-me en una. Mirant enrere, vaig escriure la meitat del codi per a l'ordre Java JIT, l'ordre C2. El següent programador més ràpid va escriure la meitat de lent, el següent la meitat de lent, i va ser un descens exponencial. La setena persona d'aquesta fila va ser molt, molt lenta, això sempre passa! Vaig tocar molt de codi. Vaig mirar qui va escriure allò, sense excepció, vaig mirar el seu codi, vaig revisar cadascun d'ells i, tot i així, vaig continuar escrivint més jo mateix que cap d'ells. Aquest enfocament no funciona gaire bé amb la gent. A algunes persones no els agrada això. I quan no ho aconsegueixen, comencen tota mena de queixes. Per exemple, una vegada em van dir que deixés de programar perquè estava escrivint massa codi i posava en perill l'equip, i tot em va semblar una broma: home, si la resta de l'equip desapareix i jo segueixo escrivint codi, tu Només perdrà mig equips. D'altra banda, si segueixo escrivint codi i perds la meitat de l'equip, sembla molt mala gestió. Mai hi vaig pensar, mai no en vaig parlar, però encara estava en algun lloc del meu cap. El pensament estava girant al fons de la meva ment: "Esteu fent broma?" Per tant, el problema més gran era jo i les meves relacions amb la gent. Ara m'entenc molt millor, vaig ser líder d'equip per a programadors durant molt de temps, i ara li dic directament a la gent: ja saps, sóc qui sóc, i hauràs de tractar amb mi, està bé si em mantinc? aquí? I quan van començar a tractar-ho, tot va funcionar. De fet, no sóc ni dolent ni bo, no tinc males intencions ni aspiracions egoistes, és només la meva essència, i necessito viure amb això d'alguna manera.

Andrés: Fa poc que tothom va començar a parlar sobre l'autoconeixement per als introvertits i les habilitats suaus en general. Què pots dir d'això?

Penya-segat: Sí, aquesta va ser la visió i la lliçó que vaig aprendre del meu divorci de la meva dona. El que vaig aprendre del divorci va ser entendre'm a mi mateix. Així va ser com vaig començar a entendre els altres. Entendre com funciona aquesta interacció. Això va portar a descobriments un rere l'altre. Hi havia una consciència de qui sóc i què represento. Què estic fent: o estic preocupat per la tasca, o estic evitant el conflicte, o alguna cosa més, i aquest nivell d'autoconeixement m'ajuda realment a mantenir-me en control. Després d'això, tot va molt més fàcil. Una cosa que he descobert no només en mi mateix, sinó també en altres programadors és la incapacitat de verbalitzar els pensaments quan estàs en un estat d'estrès emocional. Per exemple, estàs assegut allà codificant, en un estat de flux, i després vénen corrents cap a tu i comencen a cridar histèrics que alguna cosa està trencada i que ara es prendran mesures extremes contra tu. I no pots dir ni una paraula perquè estàs en un estat d'estrès emocional. Els coneixements adquirits us permeten preparar-vos per aquest moment, sobreviure-hi i passar a un pla de retirada, després del qual podeu fer alguna cosa. Així que sí, quan comences a adonar-te de com funciona tot, és un gran esdeveniment que canvia la vida. 
Jo mateix no vaig trobar les paraules adequades, però vaig recordar la seqüència d'accions. La qüestió és que aquesta reacció és tant física com verbal, i necessites espai. Aquest espai, en el sentit zen. Això és exactament el que s'ha d'explicar i, de seguida, deixar-se a un costat, allunyar-se purament físicament. Quan callo verbalment, puc processar la situació emocionalment. A mesura que l'adrenalina arriba al teu cervell, et canvia en mode lluita o fugida, ja no pots dir res, no; ara ets un idiota, un enginyer assotat, incapaç de respondre decentment o fins i tot d'aturar l'atac, i l'atacant és lliure. per atacar una i altra vegada. Primer has de tornar a ser tu mateix, recuperar el control, sortir del mode "lluita o vol".

I per a això necessitem espai verbal. Només espai lliure. Si dius alguna cosa, pots dir-ho exactament, i després anar a trobar un "espai" per a tu mateix: anar a passejar pel parc, tancar-te a la dutxa, no importa. El més important és desconnectar temporalment d'aquesta situació. Tan bon punt us apagueu almenys uns segons, el control torna, comenceu a pensar amb sobrietat. "D'acord, no sóc una mena d'idiota, no faig coses estúpides, sóc una persona bastant útil". Un cop hagis pogut convèncer-te, és el moment de passar a la següent etapa: entendre què va passar. Et van atacar, l'atac va venir d'on no t'ho esperaves, va ser una emboscada deshonesta i vil. Això és dolent. El següent pas és entendre per què l'atacant ho necessitava. Realment per què? Potser perquè ell mateix està furiós? Per què està boig? Per exemple, perquè s'ha enganxat i no pot acceptar la responsabilitat? Aquesta és la manera de manejar amb cura tota la situació. Però això requereix marge de maniobra, espai verbal. El primer pas és trencar el contacte verbal. Eviteu la discussió amb paraules. Cancel·la-ho, marxa el més aviat possible. Si es tracta d'una conversa telefònica, només pengeu: aquesta és una habilitat que vaig aprendre en comunicar-me amb la meva exdona. Si la conversa no va bé, només cal dir "adéu" i penjar. Des de l'altra banda del telèfon: "bla bla bla", respons: "sí, adéu!" i penjar. Només has d'acabar la conversa. Cinc minuts més tard, quan et torna la capacitat de pensar amb raó, t'has refredat una mica, es fa possible pensar en tot, què va passar i què passarà després. I comenceu a formular una resposta reflexiva, en lloc de només reaccionar per emoció. Per a mi, l'avenç en l'autoconsciència va ser precisament el fet que en cas d'estrès emocional no puc parlar. Sortir d'aquest estat, pensar i planificar com respondre i compensar els problemes: aquests són els passos correctes en cas que no es pugui parlar. La manera més fàcil és fugir de la situació en què es manifesta l'estrès emocional i simplement deixar de participar en aquest estrès. Després d'això et tornes capaç de pensar, quan pots pensar, pots parlar, etc.

Per cert, a la cort, l'advocat contrari intenta fer-te això, ara està clar per què. Perquè té la capacitat de reprimir-te fins a un estat tal que no pots ni pronunciar el teu nom, per exemple. En un sentit molt real, no podràs parlar. Si us passa això, i si sabeu que us trobareu en un lloc on s'estan produint baralles verbals, en un lloc com la cort, podeu venir amb el vostre advocat. L'advocat us defensarà i aturarà l'atac verbal, i ho farà d'una manera totalment legal, i l'espai Zen perdut us tornarà. Per exemple, vaig haver de trucar a la meva família un parell de vegades, el jutge va ser molt amable amb això, però l'advocat contrari va cridar i em va cridar, no vaig poder ni dir ni una paraula. En aquests casos, utilitzar un mediador em funciona millor. El mediador atura tota aquesta pressió que s'aboca sobre tu en un corrent continu, trobes l'espai zen necessari, i amb ell torna la capacitat de parlar. Aquest és tot un camp de coneixement en el qual hi ha molt per estudiar, molt per descobrir dins de tu, i tot això es converteix en decisions estratègiques d'alt nivell i diferents per a diferents persones. Algunes persones no tenen els problemes descrits anteriorment; normalment, les persones que són vendes professionals no els tenen. Tota aquesta gent que es guanya la vida amb les paraules -cantants famosos, poetes, líders religiosos i polítics- sempre tenen alguna cosa a dir. No tenen aquests problemes, però jo sí.

Andrés: Va ser... inesperat. Genial, ja hem parlat molt i és hora d'acabar aquesta entrevista. Definitivament ens trobarem a la conferència i podrem continuar aquest diàleg. Ens veiem a Hydra!

Podeu continuar la vostra conversa amb Cliff a la conferència Hydra 2019, que se celebrarà de l'11 al 12 de juliol de 2019 a Sant Petersburg. Vindrà amb un informe "L'experiència de la memòria transaccional de maquinari Azul". Les entrades es poden comprar al lloc web oficial.

Font: www.habr.com

Afegeix comentari