Μεγάλη συνέντευξη με τον Cliff Click, τον πατέρα της συλλογής JIT στην Java

Μεγάλη συνέντευξη με τον Cliff Click, τον πατέρα της συλλογής JIT στην JavaCliff Click — CTO της Cratus (αισθητήρες IoT για βελτίωση διαδικασιών), ιδρυτής και συνιδρυτής αρκετών startups (συμπεριλαμβανομένων των Rocket Realtime School, Neurensic και H2O.ai) με αρκετές επιτυχημένες εξόδους. Ο Cliff έγραψε τον πρώτο του μεταγλωττιστή σε ηλικία 15 ετών (Πασκάλ για το TRS Z-80)! Είναι περισσότερο γνωστός για τη δουλειά του στο C2 στην Java (the Sea of ​​​​Nodes IR). Αυτός ο μεταγλωττιστής έδειξε στον κόσμο ότι το JIT μπορούσε να παράγει κώδικα υψηλής ποιότητας, ο οποίος ήταν ένας από τους παράγοντες για την ανάδειξη της Java ως μίας από τις κύριες σύγχρονες πλατφόρμες λογισμικού. Στη συνέχεια, ο Cliff βοήθησε την Azul Systems να δημιουργήσει ένα mainframe 864 πυρήνων με καθαρό λογισμικό Java που υποστήριζε παύσεις GC σε ένα σωρό 500 gigabyte μέσα σε 10 χιλιοστά του δευτερολέπτου. Σε γενικές γραμμές, ο Cliff κατάφερε να εργαστεί σε όλες τις πτυχές του JVM.

 
Αυτό το habrapost είναι μια υπέροχη συνέντευξη με τον Cliff. Θα μιλήσουμε για τα εξής θέματα:

  • Μετάβαση σε βελτιστοποιήσεις χαμηλού επιπέδου
  • Πώς να κάνετε ένα μεγάλο refactoring
  • Μοντέλο κόστους
  • Εκπαίδευση βελτιστοποίησης χαμηλού επιπέδου
  • Πρακτικά παραδείγματα βελτίωσης της απόδοσης
  • Γιατί να δημιουργήσετε τη δική σας γλώσσα προγραμματισμού
  • Καριέρα Μηχανικού Απόδοσης
  • Τεχνικές Προκλήσεις
  • Λίγα λόγια για την κατανομή καταχωρητών και τους πολλαπλούς πυρήνες
  • Η μεγαλύτερη πρόκληση στη ζωή

Η συνέντευξη γίνεται από:

  • Αντρέι Σαταρίν από το Amazon Web Services. Στην καριέρα του, κατάφερε να εργαστεί σε εντελώς διαφορετικά έργα: δοκίμασε τη διανεμημένη βάση δεδομένων NewSQL στο Yandex, ένα σύστημα ανίχνευσης cloud στο Kaspersky Lab, ένα παιχνίδι για πολλούς παίκτες στο Mail.ru και μια υπηρεσία για τον υπολογισμό των τιμών συναλλάγματος στην Deutsche Bank. Ενδιαφέρομαι για τη δοκιμή μεγάλης κλίμακας backend και κατανεμημένων συστημάτων.
  • Βλαντιμίρ Σίτνικοφ από το Netcracker. Δέκα χρόνια δουλειάς για την απόδοση και την επεκτασιμότητα του NetCracker OS, λογισμικού που χρησιμοποιείται από τηλεπικοινωνιακούς φορείς για την αυτοματοποίηση των διαδικασιών διαχείρισης εξοπλισμού δικτύου και δικτύου. Ενδιαφέρεστε για ζητήματα απόδοσης της Java και της Oracle Database. Συγγραφέας περισσότερων από δώδεκα βελτιώσεων απόδοσης στο επίσημο πρόγραμμα οδήγησης PostgreSQL JDBC.

Μετάβαση σε βελτιστοποιήσεις χαμηλού επιπέδου

Ανδρέας: Είσαι μεγάλο όνομα στον κόσμο της μεταγλώττισης JIT, της Java και της δουλειάς επιδόσεων γενικότερα, σωστά; 

Γκρεμός: Ειναι ετσι!

Ανδρέας: Ας ξεκινήσουμε με μερικές γενικές ερωτήσεις σχετικά με την εργασία απόδοσης. Τι πιστεύετε για την επιλογή μεταξύ βελτιστοποιήσεων υψηλού και χαμηλού επιπέδου, όπως η εργασία σε επίπεδο CPU;

Γκρεμός: Ναι, όλα είναι απλά εδώ. Ο πιο γρήγορος κώδικας είναι αυτός που δεν εκτελείται ποτέ. Επομένως, πρέπει πάντα να ξεκινάτε από υψηλό επίπεδο, να εργάζεστε σε αλγόριθμους. Ένας καλύτερος συμβολισμός O θα νικήσει έναν χειρότερο συμβολισμό O, εκτός εάν παρεμβαίνουν κάποιες αρκετά μεγάλες σταθερές. Τα χαμηλού επιπέδου πάνε τελευταία. Συνήθως, αν έχετε βελτιστοποιήσει αρκετά καλά την υπόλοιπη στοίβα σας και υπάρχουν ακόμα ενδιαφέροντα πράγματα, αυτό είναι χαμηλό επίπεδο. Πώς όμως να ξεκινήσετε από ένα υψηλό επίπεδο; Πώς γνωρίζετε ότι έχει γίνει αρκετή εργασία υψηλού επιπέδου; Λοιπόν... σε καμία περίπτωση. Δεν υπάρχουν έτοιμες συνταγές. Πρέπει να κατανοήσετε το πρόβλημα, να αποφασίσετε τι θα κάνετε (για να μην κάνετε περιττά βήματα στο μέλλον) και μετά μπορείτε να αποκαλύψετε το προφίλ, το οποίο μπορεί να πει κάτι χρήσιμο. Κάποια στιγμή, συνειδητοποιείς και εσύ ότι έχεις ξεφορτωθεί τα περιττά πράγματα και ήρθε η ώρα να κάνεις λεπτομέρεια χαμηλού επιπέδου. Αυτό είναι σίγουρα ένα ιδιαίτερο είδος τέχνης. Υπάρχουν πολλοί άνθρωποι που κάνουν περιττά πράγματα, αλλά κινούνται τόσο γρήγορα που δεν έχουν χρόνο να ανησυχούν για την παραγωγικότητα. Αλλά αυτό μέχρι να τεθεί το ερώτημα ωμά. Συνήθως στο 99% των περιπτώσεων κανείς δεν ενδιαφέρεται για το τι κάνω, μέχρι τη στιγμή που ένα σημαντικό πράγμα έρχεται στο κρίσιμο μονοπάτι που κανείς δεν ενδιαφέρεται. Και εδώ όλοι αρχίζουν να σας γκρινιάζουν για το "γιατί δεν λειτούργησε τέλεια από την αρχή". Σε γενικές γραμμές, υπάρχει πάντα κάτι για βελτίωση στην απόδοση. Αλλά το 99% των περιπτώσεων δεν έχετε δυνητικούς πελάτες! Απλώς προσπαθείς να κάνεις κάτι να δουλέψει και στην πορεία καταλαβαίνεις τι είναι σημαντικό. Δεν μπορείς ποτέ να ξέρεις εκ των προτέρων ότι αυτό το κομμάτι πρέπει να είναι τέλειο, οπότε, στην πραγματικότητα, πρέπει να είσαι τέλειος σε όλα. Αλλά αυτό είναι αδύνατο και δεν το κάνεις. Υπάρχουν πάντα πολλά πράγματα να διορθωθούν - και αυτό είναι απολύτως φυσιολογικό.

Πώς να κάνετε ένα μεγάλο refactoring

Ανδρέας: Πώς δουλεύεις σε μια παράσταση; Αυτό είναι ένα εγκάρσιο πρόβλημα. Για παράδειγμα, χρειάστηκε ποτέ να εργαστείτε για προβλήματα που προκύπτουν από τη διασταύρωση πολλών υπαρχουσών λειτουργιών;

Γκρεμός: Προσπαθώ να το αποφύγω. Αν ξέρω ότι η απόδοση θα είναι ένα πρόβλημα, το σκέφτομαι πριν ξεκινήσω την κωδικοποίηση, ειδικά με τις δομές δεδομένων. Συχνά όμως όλα αυτά τα ανακαλύπτεις πολύ αργότερα. Και μετά πρέπει να πας στα ακραία μέτρα και να κάνεις αυτό που ονομάζω «ξανάγραψε και κατάκτησε»: πρέπει να αρπάξεις ένα αρκετά μεγάλο κομμάτι. Κάποιος από τον κώδικα θα πρέπει ακόμα να ξαναγραφτεί λόγω προβλημάτων απόδοσης ή κάτι άλλο. Όποιος κι αν είναι ο λόγος για την επανεγγραφή του κώδικα, είναι σχεδόν πάντα καλύτερο να ξαναγράψετε ένα μεγαλύτερο κομμάτι από ένα μικρότερο κομμάτι. Αυτή τη στιγμή, όλοι αρχίζουν να τρέμουν από φόβο: «Θεέ μου, δεν μπορείς να αγγίξεις τόσο πολύ κώδικα!» Αλλά στην πραγματικότητα, αυτή η προσέγγιση λειτουργεί σχεδόν πάντα πολύ καλύτερα. Πρέπει να αντιμετωπίσετε αμέσως ένα μεγάλο πρόβλημα, να σχεδιάσετε έναν μεγάλο κύκλο γύρω του και να πείτε: Θα ξαναγράψω τα πάντα μέσα στον κύκλο. Το περίγραμμα είναι πολύ μικρότερο από το περιεχόμενο μέσα σε αυτό που πρέπει να αντικατασταθεί. Και αν μια τέτοια οριοθέτηση των ορίων σας επιτρέπει να κάνετε τέλεια τη δουλειά μέσα, τα χέρια σας είναι ελεύθερα, κάντε ό,τι θέλετε. Μόλις καταλάβετε το πρόβλημα, η διαδικασία επανεγγραφής είναι πολύ πιο εύκολη, οπότε πάρτε μια μεγάλη μπουκιά!
Ταυτόχρονα, όταν κάνετε μια μεγάλη επανεγγραφή και συνειδητοποιήσετε ότι η απόδοση θα είναι ένα πρόβλημα, μπορείτε να αρχίσετε αμέσως να ανησυχείτε για αυτό. Αυτό συνήθως μετατρέπεται σε απλά πράγματα όπως "μην αντιγράψετε δεδομένα, διαχειριστείτε τα δεδομένα όσο το δυνατόν πιο απλά, κάντε τα μικρά". Σε μεγάλες επανεγγραφές, υπάρχουν τυπικοί τρόποι βελτίωσης της απόδοσης. Και σχεδόν πάντα περιστρέφονται γύρω από δεδομένα.

Μοντέλο κόστους

Ανδρέας: Σε ένα από τα podcast μιλήσατε για μοντέλα κόστους στο πλαίσιο της παραγωγικότητας. Μπορείτε να εξηγήσετε τι εννοούσατε με αυτό;

Γκρεμός: Σίγουρα. Γεννήθηκα σε μια εποχή που η απόδοση του επεξεργαστή ήταν εξαιρετικά σημαντική. Και αυτή η εποχή επιστρέφει ξανά - η μοίρα δεν είναι χωρίς ειρωνεία. Άρχισα να ζω στην εποχή των μηχανών οκτώ bit· ο πρώτος μου υπολογιστής λειτουργούσε με 256 byte. Ακριβώς bytes. Όλα ήταν πολύ μικρά. Έπρεπε να μετρηθούν οι οδηγίες και καθώς αρχίσαμε να ανεβαίνουμε στη στοίβα γλωσσών προγραμματισμού, οι γλώσσες έπαιρναν όλο και περισσότερες. Υπήρχε το Assembler, μετά το Basic, μετά το C, και το C φρόντισε για πολλές λεπτομέρειες, όπως την κατανομή του μητρώου και την επιλογή εντολών. Αλλά όλα ήταν αρκετά ξεκάθαρα εκεί, και αν έκανα έναν δείκτη σε μια παρουσία μιας μεταβλητής, τότε θα έπαιρνα φορτίο και το κόστος αυτής της εντολής είναι γνωστό. Το υλικό παράγει έναν ορισμένο αριθμό κύκλων μηχανής, επομένως η ταχύτητα εκτέλεσης διαφορετικών πραγμάτων μπορεί να υπολογιστεί απλά αθροίζοντας όλες τις οδηγίες που πρόκειται να εκτελέσετε. Κάθε σύγκριση/δοκιμή/υποκατάστημα/κλήση/φόρτωση/κατάστημα θα μπορούσε να προστεθεί και να ειπωθεί: αυτός είναι ο χρόνος εκτέλεσης για εσάς. Όταν εργάζεστε για τη βελτίωση της απόδοσης, σίγουρα θα δώσετε προσοχή σε ποιους αριθμούς αντιστοιχούν σε μικρούς κύκλους καυτών. 
Αλλά μόλις μεταβείτε σε Java, Python και παρόμοια πράγματα, απομακρύνεστε πολύ γρήγορα από το υλικό χαμηλού επιπέδου. Ποιο είναι το κόστος κλήσης ενός λήπτη στην Java; Εάν το JIT στο HotSpot είναι σωστό εγγραμμένος, θα φορτώσει, αλλά αν δεν το έκανε αυτό, θα είναι κλήση συνάρτησης. Δεδομένου ότι η κλήση είναι σε hot loop, θα παρακάμψει όλες τις άλλες βελτιστοποιήσεις σε αυτόν τον βρόχο. Επομένως, το πραγματικό κόστος θα είναι πολύ υψηλότερο. Και χάνετε αμέσως τη δυνατότητα να κοιτάξετε ένα κομμάτι κώδικα και να καταλάβετε ότι πρέπει να το εκτελέσουμε όσον αφορά την ταχύτητα του ρολογιού του επεξεργαστή, τη μνήμη και την προσωρινή μνήμη που χρησιμοποιείται. Όλα αυτά γίνονται ενδιαφέροντα μόνο αν μπεις πραγματικά στην παράσταση.
Τώρα βρισκόμαστε σε μια κατάσταση όπου οι ταχύτητες των επεξεργαστών δεν έχουν αυξηθεί σχεδόν για μια δεκαετία. Οι παλιές εποχές επέστρεψαν! Δεν μπορείτε πλέον να βασίζεστε σε καλή απόδοση ενός νήματος. Αλλά αν ξαφνικά μπείτε σε παράλληλους υπολογιστές, είναι απίστευτα δύσκολο, όλοι σας κοιτούν όπως ο Τζέιμς Μποντ. Οι δεκαπλάσιες επιταχύνσεις εδώ συνήθως συμβαίνουν σε μέρη όπου κάποιος έχει μπερδέψει κάτι. Ο συγχρονισμός θέλει πολλή δουλειά. Για να επιτύχετε αυτή την XNUMXx επιτάχυνση, πρέπει να κατανοήσετε το μοντέλο κόστους. Τι και πόσο κοστίζει. Και για να το κάνετε αυτό, πρέπει να καταλάβετε πώς ταιριάζει η γλώσσα στο υποκείμενο υλικό.
Ο Martin Thompson διάλεξε μια υπέροχη λέξη για το blog του Μηχανική Συμπάθεια! Πρέπει να καταλάβετε τι πρόκειται να κάνει το υλικό, πώς ακριβώς θα το κάνει και γιατί κάνει αυτό που κάνει αρχικά. Χρησιμοποιώντας αυτό, είναι αρκετά εύκολο να αρχίσετε να μετράτε εντολές και να υπολογίζετε πού πηγαίνει ο χρόνος εκτέλεσης. Αν δεν έχετε την κατάλληλη εκπαίδευση, απλά ψάχνετε για μια μαύρη γάτα σε ένα σκοτεινό δωμάτιο. Βλέπω ανθρώπους να βελτιστοποιούν την απόδοση όλη την ώρα που δεν έχουν ιδέα τι διάολο κάνουν. Υποφέρουν πολύ και δεν κάνουν μεγάλη πρόοδο. Και όταν παίρνω το ίδιο κομμάτι κώδικα, κάνω μερικές μικρές εισβολές και παίρνω πενταπλάσια ή δεκαπλάσια επιτάχυνση, είναι σαν: Λοιπόν, αυτό δεν είναι δίκαιο, ξέραμε ήδη ότι ήσουν καλύτερος. Φοβερο. Για ποιο πράγμα μιλάω... το μοντέλο κόστους αφορά το είδος του κώδικα που γράφετε και πόσο γρήγορα τρέχει κατά μέσο όρο στη μεγάλη εικόνα.

Ανδρέας: Και πώς μπορείς να κρατήσεις τέτοιο όγκο στο κεφάλι σου; Αυτό επιτυγχάνεται με περισσότερη εμπειρία ή; Από πού προέρχεται μια τέτοια εμπειρία;

Γκρεμός: Λοιπόν, δεν πήρα την εμπειρία μου με τον πιο εύκολο τρόπο. Προγραμμάτισα στη Συνέλευση την εποχή που μπορούσατε να καταλάβετε κάθε οδηγία. Ακούγεται ανόητο, αλλά από τότε το σετ οδηγιών Z80 έμεινε πάντα στο κεφάλι μου, στη μνήμη μου. Δεν θυμάμαι τα ονόματα των ανθρώπων μέσα σε ένα λεπτό μετά τη συζήτηση, αλλά θυμάμαι κώδικα που γράφτηκε πριν από 40 χρόνια. Είναι αστείο, μοιάζει με σύνδρομο»ηλίθιος επιστήμονας».

Εκπαίδευση βελτιστοποίησης χαμηλού επιπέδου

Ανδρέας: Υπάρχει πιο εύκολος τρόπος να μπεις;

Γκρεμός: Ναι και ΟΧΙ. Το υλικό που χρησιμοποιούμε όλοι δεν έχει αλλάξει τόσο πολύ με την πάροδο του χρόνου. Όλοι χρησιμοποιούν x86, με εξαίρεση τα Arm smartphones. Εάν δεν κάνετε κάποιο είδος σκληροπυρηνικής ενσωμάτωσης, κάνετε το ίδιο πράγμα. Εντάξει, επόμενο. Οι οδηγίες επίσης δεν έχουν αλλάξει εδώ και αιώνες. Πρέπει να πας και να γράψεις κάτι στη Συνέλευση. Όχι πολλά, αλλά αρκετά για να αρχίσουμε να καταλαβαίνουμε. Χαμογελάς, αλλά μιλάω πολύ σοβαρά. Πρέπει να κατανοήσετε την αντιστοιχία μεταξύ γλώσσας και υλικού. Μετά από αυτό πρέπει να πάτε και να γράψετε λίγο και να φτιάξετε ένα μικρό μεταγλωττιστή παιχνιδιών για μια μικρή γλώσσα παιχνιδιού. Το παιχνίδι σαν παιχνίδι σημαίνει ότι πρέπει να κατασκευαστεί σε εύλογο χρονικό διάστημα. Μπορεί να είναι εξαιρετικά απλό, αλλά πρέπει να παράγει οδηγίες. Η πράξη της δημιουργίας μιας εντολής θα σας βοηθήσει να κατανοήσετε το μοντέλο κόστους για τη γέφυρα μεταξύ του κώδικα υψηλού επιπέδου που γράφουν όλοι και του κώδικα μηχανής που εκτελείται στο υλικό. Αυτή η αλληλογραφία θα καεί στον εγκέφαλο τη στιγμή που θα γραφτεί ο μεταγλωττιστής. Ακόμα και ο πιο απλός μεταγλωττιστής. Μετά από αυτό, μπορείτε να αρχίσετε να εξετάζετε την Java και το γεγονός ότι το σημασιολογικό της χάσμα είναι πολύ βαθύτερο και είναι πολύ πιο δύσκολο να χτίσετε γέφυρες πάνω της. Στην Java, είναι πολύ πιο δύσκολο να καταλάβουμε αν η γέφυρά μας έγινε καλή ή κακή, τι θα την κάνει να καταρρεύσει και τι όχι. Χρειάζεστε, όμως, κάποιου είδους σημείο εκκίνησης όπου θα κοιτάξετε τον κώδικα και θα καταλάβετε: «Ναι, αυτός ο λήπτης πρέπει να είναι ενσωματωμένος κάθε φορά». Και τότε αποδεικνύεται ότι μερικές φορές αυτό συμβαίνει, εκτός από την περίπτωση που η μέθοδος γίνεται πολύ μεγάλη και το JIT αρχίζει να ενσωματώνει τα πάντα. Η απόδοση τέτοιων χώρων μπορεί να προβλεφθεί αμέσως. Συνήθως τα getters λειτουργούν καλά, αλλά μετά κοιτάς μεγάλους hot loop και συνειδητοποιείς ότι υπάρχουν κάποιες κλήσεις συναρτήσεων που αιωρούνται εκεί γύρω που δεν ξέρουν τι κάνουν. Αυτό είναι το πρόβλημα με την ευρεία χρήση των ληπτών, ο λόγος για τον οποίο δεν είναι γραμμωμένοι είναι ότι δεν είναι ξεκάθαρο αν είναι γκέτες. Εάν έχετε μια πολύ μικρή βάση κώδικα, μπορείτε απλά να τον θυμηθείτε και μετά να πείτε: αυτός είναι ένας λήπτης και αυτός είναι ένας ρυθμιστής. Σε μια μεγάλη βάση κώδικα, κάθε συνάρτηση ζει τη δική της ιστορία, η οποία, γενικά, δεν είναι γνωστή σε κανέναν. Ο προγραμματιστής λέει ότι χάσαμε το 24% του χρόνου σε κάποιο βρόχο και για να καταλάβουμε τι κάνει αυτός ο βρόχος, πρέπει να δούμε κάθε συνάρτηση μέσα. Είναι αδύνατο να το καταλάβουμε αυτό χωρίς να μελετήσουμε τη συνάρτηση και αυτό επιβραδύνει σοβαρά τη διαδικασία κατανόησης. Γι' αυτό δεν χρησιμοποιώ getters και setters, έχω φτάσει σε νέο επίπεδο!
Πού να βρείτε το μοντέλο κόστους; Λοιπόν, μπορείτε να διαβάσετε κάτι, φυσικά... Αλλά νομίζω ότι ο καλύτερος τρόπος είναι να ενεργήσετε. Η δημιουργία ενός μικρού μεταγλωττιστή θα είναι ο καλύτερος τρόπος για να κατανοήσετε το μοντέλο κόστους και να το χωρέσετε στο μυαλό σας. Ένας μικρός μεταγλωττιστής που θα ήταν κατάλληλος για τον προγραμματισμό ενός φούρνου μικροκυμάτων είναι μια εργασία για έναν αρχάριο. Λοιπόν, εννοώ, εάν έχετε ήδη δεξιότητες προγραμματισμού, τότε αυτό θα είναι αρκετό. Όλα αυτά τα πράγματα όπως η ανάλυση μιας συμβολοσειράς που έχετε ως κάποιο είδος αλγεβρικής έκφρασης, η εξαγωγή οδηγιών για μαθηματικές πράξεις από εκεί με τη σωστή σειρά, η λήψη των σωστών τιμών από τους καταχωρητές - όλα αυτά γίνονται ταυτόχρονα. Και ενώ το κάνετε, θα αποτυπωθεί στον εγκέφαλό σας. Νομίζω ότι όλοι γνωρίζουν τι κάνει ένας μεταγλωττιστής. Και αυτό θα δώσει μια κατανόηση του μοντέλου κόστους.

Πρακτικά παραδείγματα βελτίωσης της απόδοσης

Ανδρέας: Τι άλλο πρέπει να προσέχετε όταν εργάζεστε για την παραγωγικότητα;

Γκρεμός: ΔΟΜΕΣ ΔΕΔΟΜΕΝΩΝ. Παρεμπιπτόντως, ναι, δεν έχω διδάξει αυτά τα μαθήματα για πολύ καιρό… Σχολή Πύραυλων. Ήταν διασκεδαστικό, αλλά απαιτούσε πολλή προσπάθεια, και έχω και μια ζωή! ΕΝΤΑΞΕΙ. Έτσι, σε ένα από τα μεγάλα και ενδιαφέροντα μαθήματα, «Πού πάει η απόδοσή σας», έδωσα στους μαθητές ένα παράδειγμα: δυόμισι gigabyte δεδομένων fintech διαβάστηκαν από ένα αρχείο CSV και στη συνέχεια έπρεπε να υπολογίσουν τον αριθμό των προϊόντων που πουλήθηκαν . Τακτικά δεδομένα αγοράς. Τα πακέτα UDP μετατράπηκαν σε μορφή κειμένου από τη δεκαετία του '70. Chicago Mercantile Exchange - όλα τα είδη όπως βούτυρο, καλαμπόκι, σόγια, τέτοια πράγματα. Ήταν απαραίτητο να μετρηθούν αυτά τα προϊόντα, ο αριθμός των συναλλαγών, ο μέσος όγκος κίνησης κεφαλαίων και αγαθών κ.λπ. Είναι πολύ απλά μαθηματικά συναλλαγών: βρείτε τον κωδικό προϊόντος (που είναι 1-2 χαρακτήρες στον πίνακα κατακερματισμού), λάβετε το ποσό, προσθέστε το σε ένα από τα σύνολα συναλλαγών, προσθέστε όγκο, προσθέστε αξία και μερικά άλλα πράγματα. Πολύ απλά μαθηματικά. Η εφαρμογή του παιχνιδιού ήταν πολύ απλή: τα πάντα βρίσκονται σε ένα αρχείο, διαβάζω το αρχείο και μετακινούμαι μέσα σε αυτό, χωρίζοντας μεμονωμένες εγγραφές σε συμβολοσειρές Java, αναζητώντας τα απαραίτητα πράγματα σε αυτές και προσθέτοντάς τα σύμφωνα με τα μαθηματικά που περιγράφονται παραπάνω. Και λειτουργεί με χαμηλή ταχύτητα.

Με αυτή την προσέγγιση, είναι προφανές τι συμβαίνει και οι παράλληλοι υπολογιστές δεν θα βοηθήσουν, σωστά; Αποδεικνύεται ότι μια πενταπλάσια αύξηση στην απόδοση μπορεί να επιτευχθεί απλώς με την επιλογή των σωστών δομών δεδομένων. Και αυτό εκπλήσσει ακόμη και έμπειρους προγραμματιστές! Στη συγκεκριμένη περίπτωσή μου, το κόλπο ήταν ότι δεν πρέπει να κάνετε εκχωρήσεις μνήμης σε ένα hot loop. Λοιπόν, αυτή δεν είναι όλη η αλήθεια, αλλά γενικά - δεν πρέπει να επισημάνετε "μία φορά στο Χ" όταν το Χ είναι αρκετά μεγάλο. Όταν το X είναι δυόμισι gigabyte, δεν πρέπει να εκχωρείτε τίποτα "μία φορά ανά γράμμα", ή "μία ανά γραμμή" ή "μία φορά ανά πεδίο", κάτι τέτοιο. Εδώ ξοδεύεται ο χρόνος. Πώς λειτουργεί ακόμα αυτό; Φανταστείτε να κάνω μια κλήση String.split() ή BufferedReader.readLine(). Readline δημιουργεί μια συμβολοσειρά από ένα σύνολο byte που ήρθαν στο δίκτυο, μία φορά για κάθε γραμμή, για κάθε μία από τις εκατοντάδες εκατομμύρια γραμμές. Παίρνω αυτή τη γραμμή, την αναλύω και την πετάω. Γιατί το πετάω - καλά, το έχω ήδη επεξεργαστεί, αυτό είναι όλο. Έτσι, για κάθε byte που διαβάζεται από αυτά τα 2.7G, θα γράφονται δύο χαρακτήρες στη γραμμή, δηλαδή ήδη 5.4G, και δεν τους χρειάζομαι για τίποτα περαιτέρω, επομένως πετιούνται. Αν κοιτάξετε το εύρος ζώνης μνήμης, φορτώνουμε 2.7 G που περνάει από τη μνήμη και το δίαυλο μνήμης στον επεξεργαστή, και στη συνέχεια αποστέλλεται διπλάσια στη γραμμή που βρίσκεται στη μνήμη και όλα αυτά ξεφτίζουν όταν δημιουργείται κάθε νέα γραμμή. Αλλά πρέπει να το διαβάσω, το υλικό το διαβάζει, ακόμα κι αν όλα είναι ξεφτισμένα αργότερα. Και πρέπει να το γράψω γιατί δημιούργησα μια γραμμή και οι κρυφές μνήμες είναι γεμάτες - η κρυφή μνήμη δεν μπορεί να φιλοξενήσει 2.7G. Έτσι, για κάθε byte που διαβάζω, διαβάζω άλλα δύο byte και γράφω άλλα δύο byte, και στο τέλος έχουν αναλογία 4:1 - σε αυτήν την αναλογία σπαταλάμε εύρος ζώνης μνήμης. Και τότε αποδεικνύεται ότι αν το κάνω String.split() – δεν είναι η τελευταία φορά που το κάνω αυτό, μπορεί να υπάρχουν άλλα 6-7 πεδία μέσα. Έτσι, ο κλασικός κώδικας ανάγνωσης CSV και στη συνέχεια ανάλυσης των συμβολοσειρών οδηγεί σε σπατάλη εύρους ζώνης μνήμης περίπου 14:1 σε σχέση με αυτό που πραγματικά θα θέλατε να έχετε. Εάν πετάξετε αυτές τις επιλογές, μπορείτε να πάρετε μια πενταπλάσια επιτάχυνση.

Και δεν είναι τόσο δύσκολο. Αν κοιτάξετε τον κώδικα από τη σωστή γωνία, όλα γίνονται αρκετά απλά μόλις αντιληφθείτε το πρόβλημα. Δεν πρέπει να σταματήσετε να εκχωρείτε εντελώς τη μνήμη: το μόνο πρόβλημα είναι ότι εκχωρείτε κάτι και αυτό πεθαίνει αμέσως και στην πορεία καίει έναν σημαντικό πόρο, ο οποίος σε αυτήν την περίπτωση είναι το εύρος ζώνης μνήμης. Και όλα αυτά έχουν ως αποτέλεσμα την πτώση της παραγωγικότητας. Στο x86 συνήθως χρειάζεται να κάψετε ενεργά τους κύκλους του επεξεργαστή, αλλά εδώ κάψατε όλη τη μνήμη πολύ νωρίτερα. Η λύση είναι να μειωθεί η ποσότητα της απόρριψης. 
Το άλλο μέρος του προβλήματος είναι ότι αν εκτελέσετε το προφίλ όταν τελειώσει η λωρίδα της μνήμης, ακριβώς τη στιγμή που συμβαίνει, συνήθως περιμένετε να επιστρέψει η προσωρινή μνήμη επειδή είναι γεμάτη σκουπίδια που μόλις δημιουργήσατε, όλες αυτές οι γραμμές. Επομένως, κάθε λειτουργία φόρτωσης ή αποθήκευσης γίνεται αργή, επειδή οδηγούν σε αστοχίες της προσωρινής μνήμης - ολόκληρη η προσωρινή μνήμη έχει γίνει αργή, περιμένοντας να φύγουν τα σκουπίδια. Επομένως, η συσκευή προφίλ θα εμφανίζει απλώς ζεστό τυχαίο θόρυβο που κηλιδώνεται σε ολόκληρο τον βρόχο - δεν θα υπάρχει ξεχωριστή καυτή οδηγία ή θέση στον κώδικα. Μόνο θόρυβος. Και αν κοιτάξετε τους κύκλους GC, είναι όλοι Νεαρής Γενιάς και εξαιρετικά γρήγοροι - μικροδευτερόλεπτα ή χιλιοστά του δευτερολέπτου το μέγιστο. Άλλωστε όλη αυτή η μνήμη πεθαίνει ακαριαία. Διαθέτετε δισεκατομμύρια gigabyte, και τα κόβει, τα κόβει και τα ξανακόβει. Όλα αυτά γίνονται πολύ γρήγορα. Αποδεικνύεται ότι υπάρχουν φθηνοί κύκλοι GC, ζεστός θόρυβος σε όλο τον κύκλο, αλλά θέλουμε να επιτύχουμε 5x επιτάχυνση. Αυτή τη στιγμή, κάτι πρέπει να κλείσει στο κεφάλι σας και να ακούγεται: "γιατί είναι αυτό;" Η υπερχείλιση της λωρίδας μνήμης δεν εμφανίζεται στο κλασικό πρόγραμμα εντοπισμού σφαλμάτων, πρέπει να εκτελέσετε το πρόγραμμα εντοπισμού σφαλμάτων μετρητή απόδοσης υλικού και να το δείτε μόνοι σας και απευθείας. Αλλά αυτό δεν μπορεί να υποψιαστεί άμεσα από αυτά τα τρία συμπτώματα. Το τρίτο σύμπτωμα είναι όταν κοιτάζετε αυτό που επισημαίνετε, ρωτάτε τον προγραμματιστή και απαντά: «Κάνατε ένα δισεκατομμύριο σειρές, αλλά το GC λειτούργησε δωρεάν». Μόλις συμβεί αυτό, συνειδητοποιείτε ότι έχετε δημιουργήσει πάρα πολλά αντικείμενα και έχετε κάψει ολόκληρη τη λωρίδα μνήμης. Υπάρχει τρόπος να το καταλάβετε αυτό, αλλά δεν είναι προφανές. 

Το πρόβλημα βρίσκεται στη δομή δεδομένων: η γυμνή δομή που κρύβεται πίσω από όλα όσα συμβαίνουν, είναι πολύ μεγάλη, είναι 2.7 G στο δίσκο, επομένως η δημιουργία αντιγράφου αυτού του πράγματος είναι πολύ ανεπιθύμητη - θέλετε να το φορτώσετε αμέσως από την προσωρινή μνήμη byte δικτύου στους καταχωρητές, ώστε να μην γίνεται ανάγνωση-εγγραφή στη γραμμή μπρος-πίσω πέντε φορές. Δυστυχώς, η Java δεν σας παρέχει μια τέτοια βιβλιοθήκη ως μέρος του JDK από προεπιλογή. Αλλά αυτό είναι ασήμαντο, σωστά; Ουσιαστικά, αυτές είναι 5-10 γραμμές κώδικα που θα χρησιμοποιηθούν για την υλοποίηση του δικού σας φορτωτή συμβολοσειρών προσωρινής αποθήκευσης, ο οποίος επαναλαμβάνει τη συμπεριφορά της κλάσης συμβολοσειράς, ενώ είναι ένα περιτύλιγμα γύρω από την υποκείμενη προσωρινή μνήμη byte. Ως αποτέλεσμα, αποδεικνύεται ότι εργάζεστε σχεδόν σαν με συμβολοσειρές, αλλά στην πραγματικότητα οι δείκτες προς το buffer μετακινούνται εκεί και τα ακατέργαστα byte δεν αντιγράφονται πουθενά, και έτσι τα ίδια buffer επαναχρησιμοποιούνται ξανά και ξανά, και το λειτουργικό σύστημα είναι στην ευχάριστη θέση να αναλάβει τα πράγματα για τα οποία έχει σχεδιαστεί, όπως η κρυφή διπλή αποθήκευση αυτών των byte buffer, και δεν θα αλέσετε πλέον μια ατελείωτη ροή περιττών δεδομένων. Παρεμπιπτόντως, καταλαβαίνετε ότι όταν εργάζεστε με GC, είναι εγγυημένο ότι κάθε εκχώρηση μνήμης δεν θα είναι ορατή στον επεξεργαστή μετά τον τελευταίο κύκλο GC; Επομένως, όλα αυτά δεν μπορούν να βρίσκονται στην κρυφή μνήμη και, στη συνέχεια, εμφανίζεται μια 100% εγγυημένη απώλεια. Όταν εργάζεστε με δείκτη, στο x86, η αφαίρεση ενός καταχωρητή από τη μνήμη διαρκεί 1-2 κύκλους ρολογιού και μόλις συμβεί αυτό, πληρώνετε, πληρώνετε, πληρώνετε, επειδή η μνήμη είναι όλη ενεργοποιημένη ΕΝΝΕΑ κρυφές μνήμες – και αυτό είναι το κόστος της εκχώρησης μνήμης. Πραγματική αξία.

Με άλλα λόγια, οι δομές δεδομένων είναι το πιο δύσκολο πράγμα να αλλάξει. Και μόλις συνειδητοποιήσετε ότι έχετε επιλέξει λάθος δομή δεδομένων που θα σκοτώσει την απόδοση αργότερα, συνήθως υπάρχει πολλή δουλειά να γίνει, αλλά αν δεν το κάνετε, τα πράγματα θα χειροτερέψουν. Πρώτα απ 'όλα, πρέπει να σκεφτείτε τις δομές δεδομένων, αυτό είναι σημαντικό. Το κύριο κόστος εδώ πέφτει στις παχιές δομές δεδομένων, οι οποίες αρχίζουν να χρησιμοποιούνται με το στυλ «Αντέγραψα τη δομή δεδομένων X στη δομή δεδομένων Y επειδή μου αρέσει περισσότερο το σχήμα του Y». Αλλά η λειτουργία αντιγραφής (που φαίνεται φθηνή) στην πραγματικότητα σπαταλά το εύρος ζώνης της μνήμης και εκεί θάβεται όλος ο χαμένος χρόνος εκτέλεσης. Εάν έχω μια τεράστια συμβολοσειρά JSON και θέλω να τη μετατρέψω σε ένα δομημένο δέντρο DOM POJO ή κάτι τέτοιο, η λειτουργία ανάλυσης αυτής της συμβολοσειράς και δημιουργίας του POJO και, στη συνέχεια, πρόσβαση στο POJO ξανά αργότερα, θα έχει ως αποτέλεσμα περιττό κόστος - είναι όχι φθηνό. Εκτός αν τρέχετε γύρω από τα POJO πολύ πιο συχνά από ό, τι τρέχετε γύρω από μια χορδή. Παρεμπιπτόντως, μπορείτε να προσπαθήσετε να αποκρυπτογραφήσετε τη συμβολοσειρά και να εξαγάγετε μόνο ό,τι χρειάζεστε από εκεί, χωρίς να το μετατρέψετε σε οποιοδήποτε POJO. Εάν όλα αυτά συμβαίνουν σε μια διαδρομή από την οποία απαιτείται μέγιστη απόδοση, χωρίς POJO για εσάς, πρέπει με κάποιο τρόπο να σκάψετε απευθείας στη γραμμή.

Γιατί να δημιουργήσετε τη δική σας γλώσσα προγραμματισμού

Ανδρέας: Είπατε ότι για να κατανοήσετε το μοντέλο κόστους, πρέπει να γράψετε τη δική σας μικρή γλώσσα...

Γκρεμός: Όχι γλώσσα, αλλά μεταγλωττιστής. Μια γλώσσα και ένας μεταγλωττιστής είναι δύο διαφορετικά πράγματα. Η πιο σημαντική διαφορά είναι στο κεφάλι σου. 

Ανδρέας: Παρεμπιπτόντως, από όσο γνωρίζω, πειραματίζεστε με τη δημιουργία των δικών σας γλωσσών. Για τι?

Γκρεμός: Επειδή μπορώ! Είμαι ημισυνταξιούχος, άρα αυτό είναι το χόμπι μου. Εφαρμόζω τις γλώσσες των άλλων σε όλη μου τη ζωή. Δούλεψα επίσης πολύ στο στυλ κωδικοποίησης μου. Και επίσης επειδή βλέπω προβλήματα σε άλλες γλώσσες. Βλέπω ότι υπάρχουν καλύτεροι τρόποι να κάνεις γνωστά πράγματα. Και θα τα χρησιμοποιούσα. Έχω βαρεθεί να βλέπω προβλήματα στον εαυτό μου, στην Java, στην Python, σε οποιαδήποτε άλλη γλώσσα. Τώρα γράφω σε React Native, JavaScript και Elm ως χόμπι που δεν αφορά τη συνταξιοδότηση, αλλά την ενεργό εργασία. Γράφω επίσης σε Python και, πιθανότατα, θα συνεχίσω να εργάζομαι στη μηχανική εκμάθηση για backends Java. Υπάρχουν πολλές δημοφιλείς γλώσσες και όλες έχουν ενδιαφέροντα χαρακτηριστικά. Ο καθένας είναι καλός με τον δικό του τρόπο και μπορείτε να προσπαθήσετε να συγκεντρώσετε όλα αυτά τα χαρακτηριστικά. Έτσι, μελετώ πράγματα που με ενδιαφέρουν, τη συμπεριφορά της γλώσσας, προσπαθώντας να καταλήξω σε λογική σημασιολογία. Και μέχρι στιγμής τα καταφέρνω! Αυτή τη στιγμή παλεύω με τη σημασιολογία της μνήμης, γιατί θέλω να την έχω όπως σε C και Java, και να αποκτήσω ένα ισχυρό μοντέλο μνήμης και σημασιολογία μνήμης για φορτώσεις και αποθήκευση. Ταυτόχρονα, έχετε αυτόματη συμπέρασμα τύπου όπως στο Haskell. Εδώ, προσπαθώ να συνδυάσω συμπέρασμα τύπου Haskell με εργασία μνήμης τόσο σε C όσο και σε Java. Αυτό κάνω για παράδειγμα τους τελευταίους 2-3 μήνες.

Ανδρέας: Αν δημιουργήσετε μια γλώσσα που παίρνει καλύτερες πτυχές από άλλες γλώσσες, πιστεύετε ότι κάποιος θα κάνει το αντίθετο: να πάρει τις ιδέες σας και να τις χρησιμοποιήσει;

Γκρεμός: Έτσι ακριβώς εμφανίζονται οι νέες γλώσσες! Γιατί η Java είναι παρόμοια με τη C; Επειδή το C είχε μια καλή σύνταξη που όλοι καταλάβαιναν και η Java εμπνεύστηκε από αυτή τη σύνταξη, προσθέτοντας ασφάλεια τύπου, έλεγχο ορίων πίνακα, GC, και βελτίωσαν επίσης κάποια πράγματα από το C. Πρόσθεσαν τα δικά τους. Αλλά εμπνεύστηκαν αρκετά, σωστά; Όλοι στέκονται στους ώμους των γιγάντων που ήρθαν πριν από εσάς - έτσι γίνεται η πρόοδος.

Ανδρέας: Όπως καταλαβαίνω, η γλώσσα σας θα είναι ασφαλής για τη μνήμη. Σκεφτήκατε να εφαρμόσετε κάτι σαν δάνειο από τη Rust; Τον έχεις κοιτάξει, τι γνώμη έχεις για αυτόν;

Γκρεμός: Λοιπόν, γράφω C εδώ και χρόνια, με όλο αυτό το malloc και δωρεάν, και διαχειρίζομαι χειροκίνητα τη διάρκεια ζωής. Ξέρετε, το 90-95% του χρόνου ζωής που ελέγχεται με το χέρι έχει την ίδια δομή. Και είναι πολύ, πολύ οδυνηρό να το κάνεις με το χέρι. Θα ήθελα ο μεταγλωττιστής απλώς να σας πει τι συμβαίνει εκεί και τι πετύχατε με τις ενέργειές σας. Για ορισμένα πράγματα, το δάνειο πούλι το κάνει αυτό από το κουτί. Και θα πρέπει να εμφανίζει αυτόματα πληροφορίες, να κατανοεί τα πάντα και να μην με επιβαρύνει καν με την παρουσίαση αυτής της κατανόησης. Πρέπει να κάνει τουλάχιστον τοπική ανάλυση διαφυγής, και μόνο εάν αποτύχει, τότε χρειάζεται να προσθέσει σχολιασμούς τύπου που θα περιγράφουν τη διάρκεια ζωής - και ένα τέτοιο σχήμα είναι πολύ πιο περίπλοκο από έναν έλεγχο δανεισμού ή, μάλιστα, από οποιονδήποτε υπάρχοντα έλεγχο μνήμης. Η επιλογή μεταξύ "όλα είναι καλά" και "Δεν καταλαβαίνω τίποτα" - όχι, πρέπει να υπάρχει κάτι καλύτερο. 
Έτσι, ως κάποιος που έχει γράψει πολύ κώδικα σε C, νομίζω ότι η υποστήριξη για αυτόματο έλεγχο διάρκειας ζωής είναι το πιο σημαντικό πράγμα. Έχω επίσης βαρεθεί με το πόσο η Java χρησιμοποιεί μνήμη και το κύριο παράπονο είναι το GC. Όταν εκχωρείτε μνήμη σε Java, δεν θα λάβετε πίσω τη μνήμη που ήταν τοπική στον τελευταίο κύκλο GC. Αυτό δεν συμβαίνει σε γλώσσες με πιο ακριβή διαχείριση μνήμης. Εάν καλέσετε το malloc, λαμβάνετε αμέσως τη μνήμη που συνήθως χρησιμοποιήθηκε. Συνήθως κάνετε κάποια προσωρινά πράγματα με τη μνήμη και την επιστρέφετε αμέσως πίσω. Και αμέσως επιστρέφει στην πισίνα του malloc, και ο επόμενος κύκλος malloc το βγάζει ξανά. Επομένως, η πραγματική χρήση μνήμης μειώνεται στο σύνολο των ζωντανών αντικειμένων σε μια δεδομένη στιγμή, συν τις διαρροές. Και αν όλα δεν διαρρέουν με εντελώς απρεπή τρόπο, το μεγαλύτερο μέρος της μνήμης καταλήγει σε κρυφές μνήμες και στον επεξεργαστή και λειτουργεί γρήγορα. Αλλά απαιτεί πολλή χειροκίνητη διαχείριση μνήμης με malloc και δωρεάν κλήση με τη σωστή σειρά, στη σωστή θέση. Το Rust μπορεί να το χειριστεί σωστά από μόνο του και σε πολλές περιπτώσεις προσφέρει ακόμη καλύτερη απόδοση, καθώς η κατανάλωση μνήμης περιορίζεται στον τρέχοντα υπολογισμό - σε αντίθεση με την αναμονή για τον επόμενο κύκλο GC για να ελευθερωθεί μνήμη. Ως αποτέλεσμα, έχουμε έναν πολύ ενδιαφέρον τρόπο για να βελτιώσουμε την απόδοση. Και αρκετά ισχυρό - εννοώ, έκανα τέτοια πράγματα κατά την επεξεργασία δεδομένων για το fintech, και αυτό μου επέτρεψε να επιτύχω επιτάχυνση περίπου πέντε φορές. Αυτή είναι μια αρκετά μεγάλη ώθηση, ειδικά σε έναν κόσμο όπου οι επεξεργαστές δεν γίνονται πιο γρήγοροι και ακόμα περιμένουμε βελτιώσεις.

Καριέρα Μηχανικού Απόδοσης

Ανδρέας: Θα ήθελα επίσης να ρωτήσω για τις καριέρες γενικά. Αναδειχθήκατε με τη δουλειά σας στο JIT στο HotSpot και στη συνέχεια μετακομίσατε στην Azul, η οποία είναι επίσης εταιρεία JVM. Αλλά ήδη εργαζόμασταν περισσότερο σε υλικό παρά σε λογισμικό. Και μετά ξαφνικά μεταπήδησαν σε Big Data και Machine Learning και μετά στον εντοπισμό απάτης. Πως εγινε αυτο? Αυτοί είναι πολύ διαφορετικοί τομείς ανάπτυξης.

Γκρεμός: Ασχολούμαι με τον προγραμματισμό για αρκετό καιρό και έχω καταφέρει να παρακολουθήσω πολλά διαφορετικά μαθήματα. Και όταν οι άνθρωποι λένε: "Ω, είσαι αυτός που έκανε το JIT για την Java!", είναι πάντα αστείο. Αλλά πριν από αυτό, δούλευα σε έναν κλώνο του PostScript - τη γλώσσα που χρησιμοποιούσε κάποτε η Apple για τους εκτυπωτές λέιζερ της. Και πριν από αυτό έκανα μια υλοποίηση της γλώσσας Forth. Νομίζω ότι ένα κοινό θέμα για μένα είναι η ανάπτυξη εργαλείων. Όλη μου τη ζωή φτιάχνω εργαλεία με τα οποία άλλοι άνθρωποι γράφουν τα ωραία τους προγράμματα. Αλλά συμμετείχα επίσης στην ανάπτυξη λειτουργικών συστημάτων, προγραμμάτων οδήγησης, εντοπιστών σφαλμάτων σε επίπεδο πυρήνα, γλωσσών για ανάπτυξη λειτουργικού συστήματος, που ξεκίνησαν ασήμαντα, αλλά με τον καιρό έγιναν όλο και πιο περίπλοκα. Αλλά το κύριο θέμα εξακολουθεί να είναι η ανάπτυξη εργαλείων. Ένα μεγάλο μέρος της ζωής μου πέρασε μεταξύ Azul και Sun, και αφορούσε την Java. Αλλά όταν μπήκα στο Big Data και τη Machine Learning, φόρεσα ξανά το φανταχτερό μου καπέλο και είπα: «Ω, τώρα έχουμε ένα μη τετριμμένο πρόβλημα, και υπάρχουν πολλά ενδιαφέροντα πράγματα που συμβαίνουν και άνθρωποι κάνουν πράγματα». Αυτό είναι ένα μεγάλο μονοπάτι ανάπτυξης που πρέπει να ακολουθήσετε.

Ναι, μου αρέσει πολύ η κατανεμημένη πληροφορική. Η πρώτη μου δουλειά ήταν ως φοιτητής στο Γ, σε ένα διαφημιστικό έργο. Αυτό διανεμήθηκε υπολογιστικά σε τσιπ Zilog Z80 που συνέλεγαν δεδομένα για αναλογικό OCR, που παρήχθη από έναν πραγματικό αναλογικό αναλυτή. Ήταν ένα κουλ και εντελώς τρελό θέμα. Αλλά υπήρχαν προβλήματα, κάποιο μέρος δεν αναγνωρίστηκε σωστά, επομένως έπρεπε να βγάλετε μια φωτογραφία και να τη δείξετε σε ένα άτομο που μπορούσε ήδη να διαβάσει με τα μάτια του και να αναφέρει τι έλεγε, και επομένως υπήρχαν εργασίες με δεδομένα και αυτές οι εργασίες είχαν τη δική τους γλώσσα. Υπήρχε ένα backend που επεξεργαζόταν όλα αυτά - Z80s που λειτουργούσαν παράλληλα με τερματικά vt100 που λειτουργούσαν - ένα ανά άτομο, και υπήρχε ένα μοντέλο παράλληλου προγραμματισμού στο Z80. Κάποιο κοινό κομμάτι μνήμης που μοιράζονται όλα τα Z80 σε μια διαμόρφωση αστεριού. Το backplane ήταν επίσης κοινόχρηστο και η μισή μνήμη RAM ήταν κοινή στο δίκτυο και η άλλη μισή ήταν ιδιωτική ή πήγε σε κάτι άλλο. Ένα ουσιαστικά πολύπλοκο παράλληλο κατανεμημένο σύστημα με κοινή... ημι-κοινή μνήμη. Πότε ήταν αυτό... Δεν μπορώ καν να θυμηθώ, κάπου στα μέσα της δεκαετίας του '80. Πριν από πολύ καιρό. 
Ναι, ας υποθέσουμε ότι 30 χρόνια είναι πολύ καιρό πριν. Τα προβλήματα που σχετίζονται με τους κατανεμημένους υπολογιστές υπάρχουν εδώ και πολύ καιρό· οι άνθρωποι εδώ και πολύ καιρό βρίσκονται σε πόλεμο με Beowulf-συστάδες. Τέτοια συμπλέγματα μοιάζουν με... Για παράδειγμα: υπάρχει Ethernet και το γρήγορο x86 σας είναι συνδεδεμένο σε αυτό το Ethernet, και τώρα θέλετε να αποκτήσετε ψεύτικη κοινόχρηστη μνήμη, επειδή κανείς δεν μπορούσε να κάνει κατανεμημένη κωδικοποίηση υπολογιστών τότε, ήταν πολύ δύσκολο και επομένως εκεί ήταν ψεύτικη κοινόχρηστη μνήμη με σελίδες μνήμης προστασίας στο x86 και αν γράψατε σε αυτήν τη σελίδα, τότε είπαμε σε άλλους επεξεργαστές ότι εάν έχουν πρόσβαση στην ίδια κοινόχρηστη μνήμη, θα πρέπει να φορτωθεί από εσάς, και επομένως κάτι σαν πρωτόκολλο για υποστήριξη Εμφανίστηκε συνοχή της κρυφής μνήμης και λογισμικό για αυτό. Ενδιαφέρουσα έννοια. Το πραγματικό πρόβλημα, φυσικά, ήταν κάτι άλλο. Όλα αυτά λειτούργησαν, αλλά γρήγορα αντιμετωπίσατε προβλήματα απόδοσης, επειδή κανείς δεν κατάλαβε τα μοντέλα απόδοσης σε αρκετά καλό επίπεδο - ποια μοτίβα πρόσβασης στη μνήμη υπήρχαν, πώς να βεβαιωθείτε ότι οι κόμβοι δεν πραγματοποιούσαν ατελείωτα ping μεταξύ τους και ούτω καθεξής.

Αυτό που κατέληξα στο H2O είναι ότι οι ίδιοι οι προγραμματιστές είναι αυτοί που είναι υπεύθυνοι για τον προσδιορισμό πού κρύβεται ο παραλληλισμός και πού όχι. Βρήκα ένα μοντέλο κωδικοποίησης που έκανε τη σύνταξη κώδικα υψηλής απόδοσης εύκολη και απλή. Αλλά η σύνταξη κώδικα αργής εκτέλεσης είναι δύσκολη, θα φαίνεται άσχημη. Πρέπει να προσπαθήσετε σοβαρά να γράψετε αργό κώδικα, θα πρέπει να χρησιμοποιήσετε μη τυπικές μεθόδους. Ο κωδικός πέδησης είναι ορατός με την πρώτη ματιά. Ως αποτέλεσμα, συνήθως γράφετε κώδικα που εκτελείται γρήγορα, αλλά πρέπει να καταλάβετε τι να κάνετε στην περίπτωση της κοινόχρηστης μνήμης. Όλα αυτά συνδέονται με μεγάλους πίνακες και η συμπεριφορά εκεί είναι παρόμοια με τους μη πτητικούς μεγάλους πίνακες σε παράλληλη Java. Θέλω να πω, φανταστείτε ότι δύο νήματα γράφουν σε έναν παράλληλο πίνακα, το ένα κερδίζει και το άλλο, κατά συνέπεια, χάνει και δεν ξέρετε ποιο είναι ποιο. Εάν δεν είναι ασταθείς, τότε η σειρά μπορεί να είναι ό,τι θέλετε - και αυτό λειτουργεί πολύ καλά. Οι άνθρωποι ενδιαφέρονται πραγματικά για τη σειρά των λειτουργιών, τοποθετούν τα πτητικά στα σωστά σημεία και αναμένουν προβλήματα απόδοσης που σχετίζονται με τη μνήμη στα σωστά σημεία. Διαφορετικά, θα έγραφαν απλώς κώδικα με τη μορφή βρόχων από το 1 έως το N, όπου το N είναι μερικά τρισεκατομμύρια, με την ελπίδα ότι όλες οι περίπλοκες περιπτώσεις θα γίνουν αυτόματα παράλληλες - και δεν λειτουργεί εκεί. Αλλά στο H2O αυτό δεν είναι ούτε Java ούτε Scala· μπορείτε να το θεωρήσετε "Java μείον μείον" αν θέλετε. Αυτό είναι ένα πολύ σαφές στυλ προγραμματισμού και μοιάζει με τη σύνταξη απλού κώδικα C ή Java με βρόχους και πίνακες. Αλλά ταυτόχρονα, η μνήμη μπορεί να επεξεργαστεί σε terabyte. Εξακολουθώ να χρησιμοποιώ H2O. Το χρησιμοποιώ κατά καιρούς σε διαφορετικά έργα - και εξακολουθεί να είναι το πιο γρήγορο πράγμα, δεκάδες φορές πιο γρήγορο από τους ανταγωνιστές του. Εάν κάνετε Big Data με δεδομένα στήλης, είναι πολύ δύσκολο να νικήσετε το H2O.

Τεχνικές Προκλήσεις

Ανδρέας: Ποια ήταν η μεγαλύτερη πρόκληση σε όλη σας την καριέρα;

Γκρεμός: Συζητάμε το τεχνικό ή μη κομμάτι του θέματος; Θα έλεγα ότι οι μεγαλύτερες προκλήσεις δεν είναι τεχνικές. 
Όσο για τις τεχνικές προκλήσεις. Απλώς τους νίκησα. Δεν ξέρω καν ποιο ήταν το μεγαλύτερο, αλλά υπήρχαν μερικά αρκετά ενδιαφέροντα που χρειάστηκαν πολύ χρόνο, ψυχική πάλη. Όταν πήγα στη Sun, ήμουν σίγουρος ότι θα έφτιαχνα έναν γρήγορο μεταγλωττιστή και ένα σωρό ηλικιωμένοι είπαν σε απάντηση ότι δεν θα τα καταφέρω ποτέ. Αλλά ακολούθησα αυτό το μονοπάτι, έγραψα έναν μεταγλωττιστή στον κατανεμητή καταχωρητή και ήταν αρκετά γρήγορο. Ήταν τόσο γρήγορο όσο το σύγχρονο C1, αλλά ο κατανεμητής ήταν πολύ πιο αργός τότε, και εκ των υστέρων ήταν ένα μεγάλο πρόβλημα δομής δεδομένων. Το χρειαζόμουν για να γράψω έναν κατανεμητή γραφικών καταχωρητών και δεν καταλάβαινα το δίλημμα μεταξύ εκφραστικότητας κώδικα και ταχύτητας, που υπήρχε εκείνη την εποχή και ήταν πολύ σημαντικό. Αποδείχθηκε ότι η δομή δεδομένων συνήθως υπερβαίνει το μέγεθος της κρυφής μνήμης σε x86 εκείνης της εποχής, και επομένως, αν αρχικά υπέθεσα ότι ο εκχωρητής καταχωρητή θα λειτουργούσε το 5-10 τοις εκατό του συνολικού χρόνου jitter, τότε στην πραγματικότητα αποδείχθηκε ότι ήταν 50 τοις εκατό.

Καθώς περνούσε ο καιρός, ο μεταγλωττιστής γινόταν καθαρότερος και αποτελεσματικότερος, σταμάτησε να παράγει τρομερό κώδικα σε περισσότερες περιπτώσεις και η απόδοση άρχισε να μοιάζει όλο και περισσότερο με αυτό που παράγει ένας μεταγλωττιστής C. Εκτός, φυσικά, αν γράψετε μερικές βλακείες που ακόμη και το C δεν επιταχύνει . Εάν γράψετε κώδικα όπως C, θα έχετε απόδοση όπως C σε περισσότερες περιπτώσεις. Και όσο προχωρούσες, τόσο πιο συχνά έπαιρνες κώδικα που ασυμπτωτικά συνέπιπτε με το επίπεδο C, ο εκχωρητής καταχωρητή άρχισε να μοιάζει με κάτι ολοκληρωμένο... ανεξάρτητα από το αν ο κώδικάς σου τρέχει γρήγορα ή αργά. Συνέχισα να εργάζομαι στον κατανεμητή για να κάνει καλύτερες επιλογές. Γινόταν όλο και πιο αργός, αλλά έδινε όλο και καλύτερες επιδόσεις σε περιπτώσεις που κανείς άλλος δεν μπορούσε να αντεπεξέλθει. Θα μπορούσα να βουτήξω σε έναν κατανεμητή μητρώου, να θάψω έναν μήνα εργασίας εκεί και ξαφνικά ολόκληρος ο κώδικας θα άρχιζε να εκτελείται 5% πιο γρήγορα. Αυτό συνέβαινε πολλές φορές και ο κατανεμητής του μητρώου έγινε κάτι σαν έργο τέχνης - όλοι το λάτρεψαν ή το μισούσαν, και άτομα από την ακαδημία έκαναν ερωτήσεις σχετικά με το θέμα "γιατί γίνονται όλα με αυτόν τον τρόπο", γιατί όχι σάρωση γραμμής, και ποια είναι η διαφορά. Η απάντηση εξακολουθεί να είναι η ίδια: ένας κατανεμητής που βασίζεται στο χρωματισμό γραφημάτων συν πολύ προσεκτική εργασία με τον κωδικό buffer ισοδυναμεί με ένα όπλο νίκης, τον καλύτερο συνδυασμό που κανείς δεν μπορεί να νικήσει. Και αυτό είναι κάτι μάλλον μη προφανές. Όλα τα άλλα που κάνει ο μεταγλωττιστής εκεί είναι αρκετά καλά μελετημένα, αν και έχουν φτάσει και στο επίπεδο της τέχνης. Πάντα έκανα πράγματα που έπρεπε να μετατρέψουν τον μεταγλωττιστή σε έργο τέχνης. Αλλά τίποτα από αυτά δεν ήταν κάτι το εξαιρετικό - εκτός από τον κατανεμητή μητρώου. Το κόλπο είναι να είσαι προσεκτικός περικόψει υπό φορτίο και, αν συμβεί αυτό (μπορώ να εξηγήσω λεπτομερέστερα αν ενδιαφέρομαι), αυτό σημαίνει ότι μπορείτε να ενσωματωθείτε πιο επιθετικά, χωρίς τον κίνδυνο να πέσετε πάνω από μια στροφή στο πρόγραμμα απόδοσης. Εκείνες τις μέρες, υπήρχαν ένα σωρό μεταγλωττιστές πλήρους κλίμακας, κρεμασμένες με μπιχλιμπίδια και σφυρίχτρες, που είχαν κατανεμητές μητρώου, αλλά κανείς άλλος δεν μπορούσε να το κάνει.

Το πρόβλημα είναι ότι, εάν προσθέσετε μεθόδους που υπόκεινται σε ένθεση, αύξηση και αύξηση της περιοχής ενσωμάτωσης, το σύνολο των χρησιμοποιούμενων τιμών ξεπερνάει αμέσως τον αριθμό των καταχωρητών και πρέπει να τους κόψετε. Το κρίσιμο επίπεδο συνήθως έρχεται όταν ο κατανεμητής εγκαταλείπει, και ένας καλός υποψήφιος για διαρροή αξίζει τον άλλο, θα πουλήσετε κάποια γενικά άγρια ​​πράγματα. Η αξία της ενσωμάτωσης εδώ είναι ότι χάνετε μέρος των γενικών εξόδων, των γενικών εξόδων για κλήση και αποθήκευση, μπορείτε να δείτε τις τιμές μέσα και να τις βελτιστοποιήσετε περαιτέρω. Το κόστος της ενσωμάτωσης είναι ότι σχηματίζεται ένας μεγάλος αριθμός ζωντανών τιμών και εάν ο κατανεμητής του μητρώου σας καεί περισσότερο από όσο χρειάζεται, χάνετε αμέσως. Ως εκ τούτου, οι περισσότεροι κατανεμητές έχουν ένα πρόβλημα: όταν η εσωτερική γραμμή διασχίζει μια συγκεκριμένη γραμμή, τα πάντα στον κόσμο αρχίζουν να μειώνονται και η παραγωγικότητα μπορεί να μειωθεί στην τουαλέτα. Αυτοί που εφαρμόζουν τον μεταγλωττιστή προσθέτουν κάποια ευρετικά: για παράδειγμα, να σταματήσουν την ενσωμάτωση, ξεκινώντας με κάποιο αρκετά μεγάλο μέγεθος, καθώς οι εκχωρήσεις θα καταστρέψουν τα πάντα. Έτσι δημιουργείται μια στροφή στο γράφημα απόδοσης - εσείς inline, inline, η απόδοση σιγά σιγά μεγαλώνει - και μετά μπουμ! – πέφτει σαν γρύλος γρηγορότερος γιατί βάλατε πάρα πολύ. Έτσι λειτουργούσαν όλα πριν από την εμφάνιση της Java. Η Java απαιτεί πολύ περισσότερη ενσωμάτωση, γι' αυτό έπρεπε να κάνω τον κατανεμητή μου πολύ πιο επιθετικό, ώστε να ισοπεδώνεται αντί να κολλάει, και αν εισάγετε υπερβολικά πολύ, αρχίζει να χύνεται, αλλά στη συνέχεια έρχεται η στιγμή "no more spilling". Αυτή είναι μια ενδιαφέρουσα παρατήρηση και μου ήρθε από το πουθενά, όχι προφανές, αλλά απέδωσε καλά. Ασχολήθηκα με επιθετικό inlining και με πήγε σε μέρη όπου οι επιδόσεις Java και C λειτουργούν δίπλα-δίπλα. Είναι πολύ κοντά - μπορώ να γράψω κώδικα Java που είναι πολύ πιο γρήγορος από τον κώδικα C και τέτοια πράγματα, αλλά κατά μέσο όρο, στη μεγάλη εικόνα των πραγμάτων, είναι περίπου συγκρίσιμα. Νομίζω ότι μέρος αυτής της αξίας είναι ο κατανεμητής μητρώου, ο οποίος μου επιτρέπει να ενσωματώνομαι όσο πιο ανόητα γίνεται. Απλώς εγγράφω όλα όσα βλέπω. Το ερώτημα εδώ είναι αν ο κατανεμητής λειτουργεί καλά, εάν το αποτέλεσμα είναι κώδικας που λειτουργεί έξυπνα. Αυτή ήταν μια μεγάλη πρόκληση: να καταλάβουμε όλα αυτά και να τα κάνουμε να λειτουργήσουν.

Λίγα λόγια για την κατανομή καταχωρητών και τους πολλαπλούς πυρήνες

Βλαδίμηρος: Προβλήματα όπως η εκχώρηση μητρώου μοιάζουν με κάποιο αιώνιο, ατελείωτο θέμα. Αναρωτιέμαι αν υπήρξε ποτέ μια ιδέα που φαινόταν πολλά υποσχόμενη και στη συνέχεια απέτυχε στην πράξη;

Γκρεμός: Σίγουρα! Η εκχώρηση μητρώου είναι μια περιοχή στην οποία προσπαθείτε να βρείτε κάποια ευρετικά για να λύσετε ένα πρόβλημα NP-complete. Και ποτέ δεν μπορείς να πετύχεις μια τέλεια λύση, σωστά; Αυτό είναι απλά αδύνατο. Κοίτα, συλλογή Ahead of Time - λειτουργεί επίσης άσχημα. Η συζήτηση εδώ αφορά κάποιες μέτριες περιπτώσεις. Σχετικά με την τυπική απόδοση, ώστε να μπορείτε να πάτε και να μετρήσετε κάτι που πιστεύετε ότι είναι καλή τυπική απόδοση - τελικά, εργάζεστε για να το βελτιώσετε! Η κατανομή του μητρώου είναι ένα θέμα σχετικά με την απόδοση. Μόλις έχετε το πρώτο πρωτότυπο, λειτουργεί και ζωγραφίζει ό,τι χρειάζεται, ξεκινά η εργασία απόδοσης. Πρέπει να μάθετε να μετράτε καλά. Γιατί είναι σημαντικό? Εάν έχετε ξεκάθαρα δεδομένα, μπορείτε να δείτε διαφορετικούς τομείς και να δείτε: ναι, βοήθησε εδώ, αλλά εκεί χάλασαν όλα! Προκύπτουν μερικές καλές ιδέες, προσθέτετε νέα ευρετικά και ξαφνικά όλα αρχίζουν να λειτουργούν λίγο καλύτερα κατά μέσο όρο. Ή δεν ξεκινά. Είχα ένα σωρό περιπτώσεις όπου παλεύαμε για την απόδοση πέντε τοις εκατό που διαφοροποιούσε την ανάπτυξή μας από τον προηγούμενο κατανεμητή. Και κάθε φορά μοιάζει με αυτό: κάπου κερδίζεις, κάπου χάνεις. Εάν διαθέτετε καλά εργαλεία ανάλυσης απόδοσης, μπορείτε να βρείτε τις χαμένες ιδέες και να καταλάβετε γιατί αποτυγχάνουν. Ίσως αξίζει να τα αφήσετε όλα ως έχουν, ή ίσως να ακολουθήσετε μια πιο σοβαρή προσέγγιση για την τελειοποίηση ή να βγείτε έξω και να διορθώσετε κάτι άλλο. Είναι ένα σωρό πράγματα! Έκανα αυτό το υπέροχο hack, αλλά χρειάζομαι και αυτό, και αυτό και αυτό - και ο συνολικός συνδυασμός τους δίνει κάποιες βελτιώσεις. Και οι μοναχικοί μπορεί να αποτύχουν. Αυτή είναι η φύση της εργασίας απόδοσης σε προβλήματα NP-complete.

Βλαδίμηρος: Έχει κανείς την αίσθηση ότι πράγματα όπως το βάψιμο σε κατανεμητές είναι ένα πρόβλημα που έχει ήδη λυθεί. Λοιπόν, είναι αποφασισμένο για εσάς, αν κρίνω από αυτά που λέτε, άρα αξίζει τον κόπο τότε…

Γκρεμός: Δεν λύνεται ως τέτοιο. Είστε εσείς που πρέπει να το μετατρέψετε σε «λυμένο». Υπάρχουν δύσκολα προβλήματα και πρέπει να λυθούν. Μόλις γίνει αυτό, ήρθε η ώρα να εργαστούμε για την παραγωγικότητα. Πρέπει να προσεγγίσετε αυτήν την εργασία αναλόγως - κάντε δείκτες αναφοράς, συλλέξτε μετρήσεις, εξηγήστε καταστάσεις κατά τις οποίες, όταν επιστρέψατε σε μια προηγούμενη έκδοση, το παλιό σας hack άρχισε να λειτουργεί ξανά (ή το αντίστροφο, σταμάτησε). Και μην τα παρατάς μέχρι να πετύχεις κάτι. Όπως είπα ήδη, αν υπάρχουν καλές ιδέες που δεν λειτούργησαν, αλλά στον τομέα της κατανομής μητρώων ιδεών είναι περίπου ατελείωτες. Μπορείτε, για παράδειγμα, να διαβάσετε επιστημονικές δημοσιεύσεις. Αν και τώρα αυτός ο τομέας έχει αρχίσει να κινείται πολύ πιο αργά και έχει γίνει πιο ξεκάθαρος από ότι στα νιάτα του. Ωστόσο, υπάρχουν αμέτρητοι άνθρωποι που εργάζονται σε αυτόν τον τομέα και όλες οι ιδέες τους αξίζει να δοκιμαστούν, όλοι περιμένουν στα φτερά. Και δεν μπορείς να καταλάβεις πόσο καλά είναι αν δεν τα δοκιμάσεις. Πόσο καλά ενσωματώνονται με οτιδήποτε άλλο στον κατανεμητή σας, επειδή ένας κατανεμητής κάνει πολλά πράγματα και ορισμένες ιδέες δεν θα λειτουργήσουν στον συγκεκριμένο κατανεμητή σας, αλλά σε έναν άλλο κατανεμητή θα λειτουργήσουν εύκολα. Ο κύριος τρόπος για να κερδίσετε για τον κατανεμητή είναι να τραβήξετε το αργό υλικό έξω από την κύρια διαδρομή και να το αναγκάσετε να χωριστεί κατά μήκος των ορίων των αργών μονοπατιών. Έτσι, εάν θέλετε να εκτελέσετε ένα GC, ακολουθήστε το αργό μονοπάτι, αποβελτιστοποιήστε, κάντε μια εξαίρεση, όλα αυτά - ξέρετε ότι αυτά τα πράγματα είναι σχετικά σπάνια. Και είναι πραγματικά σπάνια, το έλεγξα. Κάνεις επιπλέον δουλειά και αφαιρεί πολλούς από τους περιορισμούς σε αυτά τα αργά μονοπάτια, αλλά δεν έχει ιδιαίτερη σημασία γιατί είναι αργά και σπάνια ταξιδεύουν. Για παράδειγμα, ένας μηδενικός δείκτης - δεν συμβαίνει ποτέ, σωστά; Πρέπει να έχετε πολλά μονοπάτια για διαφορετικά πράγματα, αλλά δεν πρέπει να παρεμβαίνουν στο κύριο. 

Βλαδίμηρος: Τι πιστεύετε για τους πολλαπλούς πυρήνες, όταν υπάρχουν χιλιάδες πυρήνες ταυτόχρονα; Είναι χρήσιμο πράγμα αυτό;

Γκρεμός: Η επιτυχία της GPU δείχνει ότι είναι αρκετά χρήσιμο!

Βλαδίμηρος: Είναι αρκετά εξειδικευμένοι. Τι γίνεται με τους επεξεργαστές γενικής χρήσης;

Γκρεμός: Λοιπόν, αυτό ήταν το επιχειρηματικό μοντέλο της Azul. Η απάντηση ήρθε πίσω σε μια εποχή που ο κόσμος αγαπούσε πραγματικά τις προβλέψιμες επιδόσεις. Ήταν δύσκολο να γράψω παράλληλο κώδικα τότε. Το μοντέλο κωδικοποίησης H2O είναι πολύ επεκτάσιμο, αλλά δεν είναι μοντέλο γενικού σκοπού. Ίσως λίγο πιο γενικό από ό,τι όταν χρησιμοποιείτε μια GPU. Μιλάμε για την πολυπλοκότητα της ανάπτυξης ενός τέτοιου πράγματος ή την πολυπλοκότητα της χρήσης του; Για παράδειγμα, η Azul μου δίδαξε ένα ενδιαφέρον μάθημα, ένα μάλλον μη προφανές: οι μικρές κρυφές μνήμες είναι φυσιολογικές. 

Η μεγαλύτερη πρόκληση στη ζωή

Βλαδίμηρος: Τι γίνεται με τις μη τεχνικές προκλήσεις;

Γκρεμός: Η μεγαλύτερη πρόκληση ήταν να μην είσαι... ευγενικός και ευγενικός με τους ανθρώπους. Και ως αποτέλεσμα, βρισκόμουν συνεχώς σε εξαιρετικά συγκρουσιακές καταστάσεις. Εκείνοι όπου ήξερα ότι τα πράγματα πήγαιναν στραβά, αλλά δεν ήξεραν πώς να προχωρήσουν με αυτά τα προβλήματα και δεν μπορούσαν να τα διαχειριστούν. Με αυτόν τον τρόπο προέκυψαν πολλά μακροχρόνια προβλήματα, που κράτησαν δεκαετίες. Το γεγονός ότι η Java διαθέτει μεταγλωττιστές C1 και C2 είναι άμεση συνέπεια αυτού. Το γεγονός ότι δεν υπήρχε μεταγλώττιση πολλαπλών επιπέδων στην Java για δέκα συνεχόμενα χρόνια είναι επίσης άμεση συνέπεια. Είναι προφανές ότι χρειαζόμασταν ένα τέτοιο σύστημα, αλλά δεν είναι προφανές γιατί δεν υπήρχε. Είχα προβλήματα με έναν μηχανικό... ή με μια ομάδα μηχανικών. Μια φορά κι έναν καιρό που ξεκίνησα να δουλεύω στη Sun ήμουν... Εντάξει, όχι μόνο τότε, γενικά έχω πάντα τη δική μου άποψη για όλα. Και σκέφτηκα ότι ήταν αλήθεια ότι μπορούσες να πάρεις αυτή την αλήθεια σου και να την πεις κατάματα. Ειδικά από τη στιγμή που είχα συγκλονιστικά δίκιο τις περισσότερες φορές. Και αν δεν σας αρέσει αυτή η προσέγγιση... ειδικά αν προφανώς κάνετε λάθος και κάνετε ανοησίες... Γενικά, λίγοι άνθρωποι θα μπορούσαν να ανεχθούν αυτή τη μορφή επικοινωνίας. Αν και κάποιοι θα μπορούσαν, όπως εγώ. Έχω χτίσει όλη μου τη ζωή πάνω σε αξιοκρατικές αρχές. Αν μου δείξεις κάτι λάθος, θα γυρίσω αμέσως και θα σου πω: είπες βλακείες. Ταυτόχρονα, φυσικά, ζητώ συγγνώμη και όλα αυτά, θα σημειώσω τα πλεονεκτήματα, εάν υπάρχουν, και θα προβώ σε άλλες σωστές ενέργειες. Από την άλλη, έχω σοκαριστικά δίκιο για ένα συγκλονιστικά μεγάλο ποσοστό του συνολικού χρόνου. Και δεν λειτουργεί πολύ καλά στις σχέσεις με τους ανθρώπους. Δεν προσπαθώ να είμαι καλός, αλλά κάνω την ερώτηση ωμά. «Αυτό δεν θα λειτουργήσει ποτέ, γιατί ένα, δύο και τρία». Και ήταν σαν, "Ω!" Υπήρχαν και άλλες συνέπειες που ήταν μάλλον καλύτερο να αγνοήσω: για παράδειγμα, εκείνες που οδήγησαν σε διαζύγιο από τη γυναίκα μου και δέκα χρόνια κατάθλιψης μετά από αυτό.

Η πρόκληση είναι ένας αγώνας με τους ανθρώπους, με την αντίληψή τους για το τι μπορείς ή δεν μπορείς να κάνεις, τι είναι σημαντικό και τι όχι. Υπήρχαν πολλές προκλήσεις σχετικά με το στυλ κωδικοποίησης. Γράφω ακόμα πολύ κώδικα, και εκείνες τις μέρες έπρεπε ακόμη και να επιβραδύνω γιατί έκανα πάρα πολλές παράλληλες εργασίες και τις έκανα άσχημα, αντί να εστιάζω σε μία. Κοιτάζοντας πίσω, έγραψα τον μισό κώδικα για την εντολή Java JIT, την εντολή C2. Ο επόμενος ταχύτερος κωδικοποιητής έγραψε το μισό πιο αργό, το επόμενο μισό πιο αργό, και ήταν μια εκθετική πτώση. Το έβδομο άτομο σε αυτή τη σειρά ήταν πολύ, πολύ αργό - αυτό συμβαίνει πάντα! Άγγιξα πολύ κώδικα. Κοίταξα ποιος έγραψε τι, χωρίς εξαίρεση, κοίταξα τον κώδικά τους, εξέτασα το καθένα από αυτά και συνέχισα να γράφω περισσότερα ο ίδιος από οποιονδήποτε από αυτούς. Αυτή η προσέγγιση δεν λειτουργεί πολύ καλά με τους ανθρώπους. Σε κάποιους δεν αρέσει αυτό. Και όταν δεν μπορούν να το διαχειριστούν, αρχίζουν κάθε λογής παράπονα. Για παράδειγμα, κάποτε μου είπαν να σταματήσω την κωδικοποίηση επειδή έγραφα πάρα πολύ κώδικα και αυτό έθετε σε κίνδυνο την ομάδα, και όλα μου φάνηκαν σαν αστείο: φίλε, αν εξαφανιστεί η υπόλοιπη ομάδα και συνεχίσω να γράφω κώδικα, εσύ Θα χάσουν μόνο μισές ομάδες. Από την άλλη, αν συνεχίσω να γράφω κώδικα και χάσετε τη μισή ομάδα, αυτό ακούγεται σαν πολύ κακή διαχείριση. Ποτέ δεν το σκέφτηκα πραγματικά, ποτέ δεν το μίλησα, αλλά ήταν ακόμα κάπου στο μυαλό μου. Η σκέψη στριφογύριζε στο πίσω μέρος του μυαλού μου: «Πλάκα με κάνεις;» Άρα, το μεγαλύτερο πρόβλημα ήμουν εγώ και οι σχέσεις μου με τους ανθρώπους. Τώρα καταλαβαίνω τον εαυτό μου πολύ καλύτερα, ήμουν επικεφαλής της ομάδας για προγραμματιστές για μεγάλο χρονικό διάστημα, και τώρα λέω απευθείας στους ανθρώπους: ξέρετε, είμαι αυτός που είμαι και θα πρέπει να ασχοληθείτε μαζί μου - είναι εντάξει αν σταθώ εδώ? Και όταν άρχισαν να ασχολούνται με αυτό, όλα λειτούργησαν. Στην πραγματικότητα, δεν είμαι ούτε κακός ούτε καλός, δεν έχω κακές προθέσεις ή εγωιστικές φιλοδοξίες, είναι απλώς η ουσία μου και πρέπει να ζήσω με αυτό με κάποιο τρόπο.

Ανδρέας: Μόλις πρόσφατα όλοι άρχισαν να μιλούν για την αυτογνωσία για τους εσωστρεφείς, και γενικά για soft skills. Τι μπορείτε να πείτε για αυτό;

Γκρεμός: Ναι, αυτή ήταν η διορατικότητα και το μάθημα που πήρα από το διαζύγιό μου με τη γυναίκα μου. Αυτό που έμαθα από το διαζύγιο ήταν να καταλάβω τον εαυτό μου. Έτσι άρχισα να καταλαβαίνω τους άλλους. Κατανοήστε πώς λειτουργεί αυτή η αλληλεπίδραση. Αυτό οδήγησε σε ανακαλύψεις η μία μετά την άλλη. Υπήρχε συνειδητοποίηση του ποιος είμαι και τι αντιπροσωπεύω. Τι κάνω: είτε με απασχολεί το έργο, είτε αποφεύγω τη σύγκρουση, είτε κάτι άλλο - και αυτό το επίπεδο αυτογνωσίας βοηθά πραγματικά να διατηρώ τον εαυτό μου υπό τον έλεγχο. Μετά από αυτό όλα πάνε πολύ πιο εύκολα. Ένα πράγμα που ανακάλυψα όχι μόνο στον εαυτό μου, αλλά και σε άλλους προγραμματιστές είναι η αδυναμία να εκφράσεις λεκτικές σκέψεις όταν βρίσκεσαι σε κατάσταση συναισθηματικού στρες. Για παράδειγμα, κάθεστε εκεί κωδικοποιώντας, σε κατάσταση ροής, και μετά έρχονται τρέχοντας κοντά σας και αρχίζουν να ουρλιάζουν υστερικά ότι κάτι έχει σπάσει και τώρα θα ληφθούν ακραία μέτρα εναντίον σας. Και δεν μπορείτε να πείτε λέξη επειδή είστε σε κατάσταση συναισθηματικού στρες. Η αποκτηθείσα γνώση σας επιτρέπει να προετοιμαστείτε για αυτή τη στιγμή, να την επιβιώσετε και να προχωρήσετε σε ένα σχέδιο υποχώρησης, μετά από το οποίο μπορείτε να κάνετε κάτι. Οπότε ναι, όταν αρχίζεις να συνειδητοποιείς πώς λειτουργούν όλα, είναι ένα τεράστιο γεγονός που σου αλλάζει τη ζωή. 
Εγώ ο ίδιος δεν μπορούσα να βρω τις σωστές λέξεις, αλλά θυμήθηκα τη σειρά των ενεργειών. Το θέμα είναι ότι αυτή η αντίδραση είναι τόσο φυσική όσο και λεκτική και χρειάζεσαι χώρο. Τέτοιος χώρος, με την έννοια του Ζεν. Αυτό είναι ακριβώς αυτό που πρέπει να εξηγηθεί και στη συνέχεια να παραμεριστεί αμέσως - καθαρά σωματικά απομακρυνθείτε. Όταν παραμένω σιωπηλός προφορικά, μπορώ να επεξεργαστώ την κατάσταση συναισθηματικά. Καθώς η αδρεναλίνη φτάνει στον εγκέφαλό σας, σας μετατρέπει σε λειτουργία μάχης ή πτήσης, δεν μπορείτε πλέον να πείτε τίποτα, όχι - τώρα είστε ηλίθιος, μηχανικός μαστίγωσης, ανίκανος για μια αξιοπρεπή απάντηση ή ακόμα και για να σταματήσετε την επίθεση και ο εισβολέας είναι ελεύθερος να επιτίθεται ξανά και ξανά. Πρέπει πρώτα να ξαναγίνετε ο εαυτός σας, να ανακτήσετε τον έλεγχο, να βγείτε από τη λειτουργία "μάχη ή φυγή".

Και για αυτό χρειαζόμαστε λεκτικό χώρο. Απλώς ελεύθερος χώρος. Αν πείτε οτιδήποτε, τότε μπορείτε να το πείτε ακριβώς αυτό, και μετά πηγαίνετε και βρείτε πραγματικά «χώρο» για τον εαυτό σας: πηγαίνετε μια βόλτα στο πάρκο, κλειδωθείτε στο ντους - δεν πειράζει. Το κύριο πράγμα είναι να αποσυνδεθείτε προσωρινά από αυτήν την κατάσταση. Μόλις σβήσετε για τουλάχιστον μερικά δευτερόλεπτα, ο έλεγχος επιστρέφει, αρχίζετε να σκέφτεστε νηφάλια. «Εντάξει, δεν είμαι κάποιου είδους ηλίθιος, δεν κάνω ανόητα πράγματα, είμαι πολύ χρήσιμος άνθρωπος». Μόλις καταφέρετε να πείσετε τον εαυτό σας, είναι καιρός να προχωρήσετε στο επόμενο στάδιο: να κατανοήσετε τι συνέβη. Δέχτηκες επίθεση, η επίθεση ήρθε από εκεί που δεν την περίμενες, ήταν μια ανέντιμη, ποταπή ενέδρα. Αυτό είναι κακό. Το επόμενο βήμα είναι να καταλάβουμε γιατί ο εισβολέας το χρειαζόταν αυτό. Πραγματικά γιατί? Ίσως επειδή ο ίδιος είναι έξαλλος; Γιατί είναι τρελός; Για παράδειγμα, επειδή τσάκωσε τον εαυτό του και δεν μπορεί να δεχτεί την ευθύνη; Αυτός είναι ο τρόπος για να χειριστείτε προσεκτικά την όλη κατάσταση. Αλλά αυτό απαιτεί χώρο για ελιγμούς, λεκτικό χώρο. Το πρώτο βήμα είναι να διακόψετε τη λεκτική επαφή. Αποφύγετε τη συζήτηση με λόγια. Ακύρωσέ το, φύγε όσο πιο γρήγορα γίνεται. Εάν πρόκειται για τηλεφωνική συνομιλία, απλώς κλείστε το τηλέφωνο - αυτή είναι μια δεξιότητα που έμαθα από την επικοινωνία με την πρώην σύζυγό μου. Εάν η συζήτηση δεν πάει πουθενά καλά, απλά πείτε «αντίο» και κλείστε το τηλέφωνο. Από την άλλη πλευρά του τηλεφώνου: «μπλα μπλα μπλα», απαντάς: «ναι, αντίο!» και κλείσε το τηλέφωνο. Απλώς τελειώνεις τη συζήτηση. Πέντε λεπτά αργότερα, όταν η ικανότητα της λογικής σκέψης επιστρέφει σε εσάς, έχετε κρυώσει λίγο, γίνεται δυνατό να σκεφτείτε τα πάντα, τι συνέβη και τι θα συμβεί στη συνέχεια. Και αρχίστε να διατυπώνετε μια στοχαστική απάντηση, αντί να αντιδράτε απλώς από συναίσθημα. Για μένα, η ανακάλυψη στην αυτογνωσία ήταν ακριβώς το γεγονός ότι σε περίπτωση συναισθηματικού στρες δεν μπορώ να μιλήσω. Το να βγείτε από αυτή την κατάσταση, να σκεφτείτε και να σχεδιάσετε πώς να ανταποκριθείτε και να αντισταθμίσετε τα προβλήματα - αυτά είναι τα σωστά βήματα στην περίπτωση που δεν μπορείτε να μιλήσετε. Ο ευκολότερος τρόπος είναι να ξεφύγετε από την κατάσταση στην οποία εκδηλώνεται το συναισθηματικό στρες και απλά να σταματήσετε να συμμετέχετε σε αυτό το άγχος. Μετά από αυτό γίνεσαι ικανός να σκέφτεσαι, όταν μπορείς να σκέφτεσαι, γίνεσαι ικανός να μιλάς και ούτω καθεξής.

Παρεμπιπτόντως, στο δικαστήριο, ο αντίπαλος δικηγόρος προσπαθεί να σας το κάνει - τώρα είναι ξεκάθαρο γιατί. Γιατί έχει την ικανότητα να σε καταπιέζει σε τέτοια κατάσταση που δεν μπορείς να προφέρεις ούτε το όνομά σου, για παράδειγμα. Με μια πολύ πραγματική έννοια, δεν θα μπορείτε να μιλήσετε. Αν σας συμβεί αυτό και εάν ξέρετε ότι θα βρεθείτε σε ένα μέρος όπου μαίνονται λεκτικές μάχες, σε ένα μέρος όπως το δικαστήριο, τότε μπορείτε να έρθετε με τον δικηγόρο σας. Ο δικηγόρος θα υπερασπιστεί σας και θα σταματήσει τη λεκτική επίθεση και θα το κάνει με εντελώς νόμιμο τρόπο και ο χαμένος χώρος του Ζεν θα επιστρέψει σε εσάς. Για παράδειγμα, χρειάστηκε να τηλεφωνήσω στην οικογένειά μου μερικές φορές, ο δικαστής ήταν αρκετά φιλικός σχετικά με αυτό, αλλά ο αντίπαλος δικηγόρος ούρλιαξε και μου φώναξε, δεν μπορούσα να πάρω ούτε μια λέξη περίεργα. Σε αυτές τις περιπτώσεις, η χρήση ενός διαμεσολαβητή λειτουργεί καλύτερα για μένα. Ο διαμεσολαβητής σταματά όλη αυτή την πίεση που σου πέφτει σε συνεχή ροή, βρίσκεις τον απαραίτητο χώρο Ζεν, και μαζί του επιστρέφει και η ικανότητα να μιλάς. Αυτό είναι ένα ολόκληρο πεδίο γνώσης στο οποίο υπάρχουν πολλά να μελετήσετε, πολλά να ανακαλύψετε μέσα σας, και όλα αυτά μετατρέπονται σε στρατηγικές αποφάσεις υψηλού επιπέδου που είναι διαφορετικές για διαφορετικούς ανθρώπους. Μερικοί άνθρωποι δεν αντιμετωπίζουν τα προβλήματα που περιγράφονται παραπάνω· συνήθως, τα άτομα που είναι επαγγελματίες πωλητές δεν τα έχουν. Όλοι αυτοί οι άνθρωποι που βγάζουν το ψωμί τους με τα λόγια - διάσημοι τραγουδιστές, ποιητές, θρησκευτικοί ηγέτες και πολιτικοί, έχουν πάντα κάτι να πουν. Δεν έχουν τέτοια προβλήματα, αλλά εγώ.

Ανδρέας: Ήταν... αναπάντεχο. Μπράβο, έχουμε ήδη μιλήσει πολύ και ήρθε η ώρα να τελειώσουμε αυτή τη συνέντευξη. Σίγουρα θα συναντηθούμε στο συνέδριο και θα μπορέσουμε να συνεχίσουμε αυτόν τον διάλογο. Τα λέμε στην Ύδρα!

Μπορείτε να συνεχίσετε τη συνομιλία σας με τον Cliff στο συνέδριο Hydra 2019, που θα διεξαχθεί στις 11-12 Ιουλίου 2019 στην Αγία Πετρούπολη. Θα έρθει με αναφορά "Η εμπειρία της συναλλακτικής μνήμης υλικού Azul". Μπορείτε να αγοράσετε εισιτήρια στην επίσημη ιστοσελίδα.

Πηγή: www.habr.com

Προσθέστε ένα σχόλιο