Ταχύτητα Φωτός στην Αυτόματη Συμπλήρωση Domain: Έτσι Χτίζεις το Τέλειο Autocomplete
Πώς να Φτιάξεις Autocomplete που Νιώθεις Σαν Τηλεπάθεια
Έχεις ποτέ πληκτρολογήσει κάτι και η πρόταση να εμφανιστεί πριν καν τελειώσεις το πάτημα; Αυτό δεν είναι μαγεία—είναι καλοσχεδιασμένη μηχανική. Και γίνεται πραγματικά ενδιαφέρον όταν δουλεύεις με 240 εκατομμύρια domains.
Γιατί η Ταχύτητα Έχει Σημασία
Όταν ο χρήστης πληκτρολογεί σε ένα πεδίο αναζήτησης, περιμένει αποτελέσματα τώρα. Η Nielsen Norman Group έχει καθορίσει ότι τα 0.1 δευτερόλεπτα είναι το όριο—το σημείο όπου ο χρήστης νιώθει ότι η ενέργειά του είναι άμεση. Οτιδήποτε πιο αργό, και η διεπαφή αρχίζει να φαίνεται αργή—σπάει τον ρυθμό της εξερεύνησης.
Για ένα εργαλείο ελέγχου domains όπως το Wirewiki, το autocomplete είναι η κύρια πύλη εισόδου. Κάθε χιλιοστό του δευτερολέπτου μετράει. Ο χρήστης πρέπει να νιώθει ότι το εργαλείο διαβάζει το μυαλό του, όχι ότι περιμένει τον server.
Το Κόλπο του Prefetching
Εδώ είναι το ωραίο κομμάτι: το μυστικό δεν είναι να κάνεις το API πιο γρήγορο (αν και αυτό βοηθάει). Είναι να κλέβεις χρόνο από την ίδια τη διαδικασία πληκτρολόγησης.
Όταν ο χρήστης πατάει ένα πλήκτρο (keyDown), κάνεις prefetch τις προτάσεις για αυτό που πληκτρολογεί συν τον επόμενο πιθανό χαρακτήρα. Όταν αφήνει το πλήκτρο (keyUp), εμφανίζεις ό,τι είναι έτοιμο. Έτσι, ο χρονικός προϋπολογισμός σου δεν είναι η καθυστέρηση του API—είναι η διάρκεια δύο πατημάτων πλήκτρων συν το κενό μεταξύ τους.
Σε οθόνη 60Hz, έχεις 16.7ms ανά frame. Ο προϋπολογισμός βγαίνει περίπου 121ms για γρήγορους χρήστες στο p99. Αυτό είναι το παράθυρό σου. Προετοίμασε τα αποτελέσματα πριν τελειώσει το δεύτερο πάτημα, και για τον χρήστη θα φαίνεται στιγμιαίο.
Σχεδιασμός για Ταχύτητα σε Κλίμακα
Το API πρέπει να χειρίζεται 240 εκατομμύρια domains χωρίς να ιδρώνει. Το έξυπνο εδώ είναι να αντιμετωπίζεις τα δημοφιλή domains διαφορετικά από την "μακριά ουρά":
Η Κορυφή: Τα top domains ζουν σε ένα character trie αποθηκευμένο εξ ολοκλήρου στη μνήμη. Οι αναζητήσεις με βάση το prefix είναι απλές διαδρομές δεικτών—γρήγορες και προβλέψιμες. Οι 8 κορυφαίες προτάσεις για κάθε πιθανό prefix είναι προϋπολογισμένες. worst case; O(μήκος input). Αμελητέο.
Η Ουρά: Όλα τα υπόλοιπα ζουν σε SSD με ένα memory-mapped block index. Τα domains είναι ταξινομημένα, delta-compressed, και οργανωμένα σε blocks σταθερού μεγέθους με ένα μικρό in-memory directory για binary search. Τα 240M domains καταλαμβάνουν περίπου 2.5GB, και το λειτουργικό χειρίζεται αυτόματα το caching των hot pages.
Και οι δύο δομές έχουν bounded inputs—ο αριθμός των domains και το μήκος του query δεν μεγαλώνουν απεριόριστα. Αυτό κάνει την πραγματική πολυπλοκότητα ουσιαστικά O(1), διατηρώντας το p99 latency σταθερά χαμηλό.
Τα Νούμερα Δεν Λένε Ψέματα
Τα stress tests αποκάλυψαν κάτι ενδιαφέρον. Το API απαντάει τις περισσότερες requests σε λιγότερο από 2ms. Ακόμα και υπό φόρτο στις 1.600 requests ανά δευτερόλεπτο, το Nginx μαζί με το API αποκρίνεται σε 15ms στο p99. Αρκετά συμπαγές.
Αλλά εδώ μπαίνει η πραγματικότητα: το δίκτυο. Στην πράξη, το end-to-end latency ισούται με τον χρόνο μετάβασης-απόκρισης από τον browser μέσω Cloudflare στον server, συν περίπου 10ms overhead. Για χρήστες στην ίδια περιοχή με τον server, είσαι εντός προϋπολογισμού. Για όλους τους υπόλοιπους; Εκεί εμφανίζεται ο αστερίσκος.
Ο Αστερίσκος
p99 0ms* σημαίνει ότι το 99% των requests επιστρέφει αποτελέσματα πριν ο χρήστης τελειώσει το πάτημα του πλήκτρου, υποθέτοντας ότι είναι κοντά στον server. Πρόσθεσε 100-200ms transatlantic latency, και ξαφνικά ξεπερνάς τον προϋπολογισμό.
Η λύση θα ήταν geo-distributed servers με load balancing. Αλλά για ένα side project, είναι πολλή υποδομή να συντηρείς. Κάποιες φορές το "αρκετά καλό" πραγματικά είναι αρκετά καλό—ειδικά όταν το target audience σου είναι Ευρωπαίοι developers που ελέγχουν domains.
Τι Σημαίνει Αυτό για το Επόμενο Project Σου
Υπάρχει ένα μάθημα εδώ που ισχύει πολύ πέρα από τα domain lookups: κάνε prefetch έξυπνα. Αν ξέρεις τι θα ζητήσει ο χρήστης μετά, φέρε το πριν το ζητήσει. Άσε τη διεπαφή να αντιδρά σε ό,τι είναι έτοιμο αντί να περιμένει τη βεβαιότητα.
Το δεύτερο μάθημα αφορά την επιλογή δομών δεδομένων. Ένα trie για hot data, μια well-indexed sorted structure για τα πάντα άλλα. Δεν χρειάζεται να κρατάς 240 εκατομμύρια items στη RAM αν σχεδιάσεις τα access patterns σου γύρω από το τι είναι πραγματικά πιθανό να ζητηθεί.
Τέλος, μέτρησε τον πραγματικό σου προϋπολογισμό. Σε αυτή την περίπτωση, δύο πατήματα πλήκτρων συν ένα κενό. Ποιος είναι ο δικός σου; Βρες τον, βελτιστοποίησε προς αυτόν, και σταμάτα να βελτιστοποιείς πέρα από αυτόν.
Το αποτέλεσμα μοιάζει με μαγεία. Αλλά ξεκινάει με το να κατανοήσεις ακριβώς πόσο χρόνο έχεις στην πραγματικότητα.