Πώς να βελτιστοποιήσετε την εφαρμογή Web Laravel της PHP για υψηλή απόδοση;

Η Laravel είναι πολλά πράγματα. Αλλά το γρήγορο δεν είναι ένα από αυτά. Ας μάθουμε μερικά κόλπα του εμπορίου για να το κάνουμε πιο γρήγορο!

Κανένας προγραμματιστής PHP δεν είναι άθικτος Laravel αυτές τις μέρες. Είναι είτε κατώτεροι είτε μεσαίου επιπέδου προγραμματιστές που αγαπούν την ταχεία ανάπτυξη που προσφέρει η Laravel, είτε είναι ανώτερος προγραμματιστής που αναγκάζεται να μάθει Laravel λόγω των πιέσεων της αγοράς.

Είτε έτσι είτε αλλιώς, δεν υπάρχει αμφιβολία ότι η Laravel έχει αναζωογονήσει το οικοσύστημα της PHP (σίγουρα, θα είχα εγκαταλείψει τον κόσμο της PHP εδώ και πολύ καιρό αν δεν ήταν η Laravel).

Ένα απόσπασμα (κάπως δικαιολογημένο) αυτοεπαίνου από τη Laravel

Ωστόσο, δεδομένου ότι η Laravel σκύβει προς τα πίσω για να σας διευκολύνει, σημαίνει ότι από κάτω κάνει πάρα πολλές δουλειές για να διασφαλίσει ότι έχετε μια άνετη ζωή ως προγραμματιστής. Όλα τα «μαγικά» χαρακτηριστικά του Laravel που απλώς φαίνεται να λειτουργούν έχουν στρώματα κώδικα που πρέπει να ανανεώνονται κάθε φορά που εκτελείται ένα χαρακτηριστικό. Ακόμη και μια απλή Εξαίρεση ανιχνεύει πόσο βαθιά είναι η τρύπα του κουνελιού (προσέξτε από πού ξεκινά το σφάλμα, μέχρι τον κύριο πυρήνα):

Για αυτό που φαίνεται να είναι σφάλμα μεταγλώττισης σε μία από τις προβολές, υπάρχουν 18 κλήσεις συναρτήσεων για ανίχνευση. Προσωπικά έχω συναντήσει 40, και θα μπορούσαν εύκολα να υπάρχουν περισσότερα αν χρησιμοποιείτε άλλες βιβλιοθήκες και πρόσθετα.

Το γεγονός ότι, από προεπιλογή, αυτό το στρώμα πάνω σε στρώματα κώδικα, κάνει το Laravel αργό.

Πόσο αργή είναι η Laravel;

Ειλικρινά, είναι αδύνατο να απαντηθεί αυτή η ερώτηση για διάφορους λόγους.

Πρώτον, δεν υπάρχει κανένα αποδεκτό, αντικειμενικό, λογικό πρότυπο για τη μέτρηση της ταχύτητας των εφαρμογών Ιστού. Πιο γρήγορα ή πιο αργά σε σύγκριση με τι; Υπό ποιες προϋποθέσεις;

Δεύτερον, μια εφαρμογή Ιστού εξαρτάται από τόσα πολλά πράγματα (βάση δεδομένων, σύστημα αρχείων, δίκτυο, κρυφή μνήμη κ.λπ.) που είναι εντελώς ανόητο να μιλάμε για ταχύτητα. Μια πολύ γρήγορη εφαρμογή Ιστού με πολύ αργή βάση δεδομένων είναι μια πολύ αργή εφαρμογή Ιστού. 🙂

Αλλά αυτή η αβεβαιότητα είναι ακριβώς ο λόγος που τα σημεία αναφοράς είναι δημοφιλή. Παρόλο που δεν σημαίνουν τίποτα (βλ Αυτό και Αυτό), παρέχουν κάποιο πλαίσιο αναφοράς και μας βοηθούν να τρελαθούμε. Επομένως, με αρκετές πρέζες αλάτι έτοιμες, ας έχουμε μια λανθασμένη, χονδρική ιδέα της ταχύτητας μεταξύ των πλαισίων PHP.

Πηγαίνοντας από αυτό το αρκετά αξιοσέβαστο GitHub πηγήδείτε πώς ευθυγραμμίζονται τα πλαίσια PHP σε σύγκριση:

Μπορεί να μην παρατηρήσετε καν το Laravel εδώ (ακόμα κι αν στραβοπατήσετε πολύ δυνατά) εκτός και αν ρίξετε την θήκη σας μέχρι την άκρη της ουράς. Ναι, αγαπητοί φίλοι, η Laravel έρχεται τελευταία! Τώρα, φυσικά, τα περισσότερα από αυτά τα «πλαίσια» δεν είναι πολύ πρακτικά ή ακόμη και χρήσιμα, αλλά μας λέει πόσο υποτονική είναι η Laravel σε σύγκριση με άλλα πιο δημοφιλή.

Κανονικά, αυτή η «επιβράδυνση» δεν εμφανίζεται στις εφαρμογές, επειδή οι καθημερινές μας εφαρμογές ιστού σπάνια σημειώνουν υψηλά νούμερα. Αλλά μόλις το κάνουν (ας πούμε, πάνω από 200-500 ταυτόχρονα), οι διακομιστές αρχίζουν να πνίγονται και να πεθαίνουν. Είναι η στιγμή που ακόμη και το να ρίχνεις περισσότερο υλικό στο πρόβλημα δεν το μειώνει και οι λογαριασμοί υποδομής ανεβαίνουν τόσο γρήγορα που τα υψηλά ιδανικά σου για το cloud computing καταρρέουν.

Αλλά ρε, κέφι! Αυτό το άρθρο δεν είναι για το τι δεν μπορεί να γίνει, αλλά για το τι μπορεί να γίνει. 🙂

Τα καλά νέα είναι ότι μπορείτε να κάνετε πολλά για να κάνετε την εφαρμογή Laravel να λειτουργεί πιο γρήγορα. Αρκετές φορές γρήγορα. Ναι, χωρίς πλάκα. Μπορείτε να κάνετε την ίδια βάση κωδικών να γίνει βαλλιστική και να εξοικονομήσετε αρκετές εκατοντάδες δολάρια σε λογαριασμούς υποδομής/φιλοξενίας κάθε μήνα. Πως? Ας φτάσουμε σε αυτό.

Τέσσερις τύποι βελτιστοποιήσεων

Κατά τη γνώμη μου, η βελτιστοποίηση μπορεί να γίνει σε τέσσερα διαφορετικά επίπεδα (όσον αφορά τις εφαρμογές PHP, δηλαδή):

  • Επίπεδο γλώσσας: Αυτό σημαίνει ότι χρησιμοποιείτε μια πιο γρήγορη έκδοση της γλώσσας και αποφεύγετε συγκεκριμένες λειτουργίες/στυλ κωδικοποίησης στη γλώσσα που κάνει τον κώδικά σας αργό.
  • Επίπεδο πλαισίου: Αυτά είναι τα πράγματα που θα καλύψουμε σε αυτό το άρθρο.
  • Επίπεδο υποδομής: Συντονισμός του διαχειριστή διεργασιών PHP, του διακομιστή web, της βάσης δεδομένων κ.λπ.
  • Επίπεδο υλικού: Μετάβαση σε έναν καλύτερο, ταχύτερο, πιο ισχυρό πάροχο φιλοξενίας υλικού.

Όλοι αυτοί οι τύποι βελτιστοποιήσεων έχουν τη θέση τους (για παράδειγμα, η βελτιστοποίηση PHP-fpm είναι αρκετά κρίσιμη και ισχυρή). Αλλά το επίκεντρο αυτού του άρθρου θα είναι οι βελτιστοποιήσεις καθαρά τύπου 2: αυτές που σχετίζονται με το πλαίσιο.

Παρεμπιπτόντως, δεν υπάρχει καμία λογική πίσω από την αρίθμηση και δεν είναι ένα αποδεκτό πρότυπο. Μόλις τα έφτιαξα αυτά. Παρακαλώ μην μου αναφέρετε ποτέ και μην πείτε, “Χρειαζόμαστε βελτιστοποίηση τύπου 3 στον διακομιστή μας”, διαφορετικά ο επικεφαλής της ομάδας σας θα σας σκοτώσει, θα με βρει και στη συνέχεια θα με σκοτώσει επίσης. 😀

Και τώρα, επιτέλους, φτάνουμε στη γη της επαγγελίας.

Να είστε ενήμεροι για ερωτήματα βάσης δεδομένων n+1

Το πρόβλημα ερωτήματος n+1 είναι συνηθισμένο όταν χρησιμοποιούνται ORM. Η Laravel έχει το ισχυρό της ORM που ονομάζεται Eloquent, το οποίο είναι τόσο όμορφο, τόσο βολικό, που συχνά ξεχνάμε να δούμε τι συμβαίνει.

  Τι συμβαίνει εάν καταργήσετε την εγγραφή του Firestick σας;

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

Στο Laravel, μπορούμε να φανταστούμε μια λειτουργία ελεγκτή που κάνει τη δουλειά ως εξής:

class OrdersController extends Controller 
{
    // ... 

    public function getAllByCustomers(Request $request, array $ids) {
        $customers = Customer::findMany($ids);        
        $orders = collect(); // new collection
        
        foreach ($customers as $customer) {
            $orders = $orders->merge($customer->orders);
        }
        
        return view('admin.reports.orders', ['orders' => $orders]);
    }
}

Γλυκός! Και το πιο σημαντικό, κομψό, όμορφο. 🤩🤩

Δυστυχώς, είναι ένας καταστροφικός τρόπος για να γράψετε κώδικα στο Laravel.

Να γιατί.

Όταν ζητάμε από το ORM να αναζητήσει τους συγκεκριμένους πελάτες, δημιουργείται ένα ερώτημα SQL όπως αυτό:

SELECT * FROM customers WHERE id IN (22, 45, 34, . . .);

Το οποίο είναι ακριβώς όπως αναμενόταν. Ως αποτέλεσμα, όλες οι επιστρεφόμενες σειρές αποθηκεύονται στη συλλογή $customers μέσα στη λειτουργία ελεγκτή.

Τώρα παρακολουθούμε κάθε πελάτη έναν προς έναν και λαμβάνουμε τις παραγγελίες του. Αυτό εκτελεί το ακόλουθο ερώτημα. . .

SELECT * FROM orders WHERE customer_id = 22;

. . . όσες φορές υπάρχουν πελάτες.

Με άλλα λόγια, εάν χρειαστεί να λάβουμε τα δεδομένα παραγγελίας για 1000 πελάτες, ο συνολικός αριθμός των ερωτημάτων της βάσης δεδομένων που θα εκτελεστούν θα είναι 1 (για την ανάκτηση όλων των δεδομένων των πελατών) + 1000 (για την ανάκτηση δεδομένων παραγγελίας για κάθε πελάτη) = 1001. Αυτό είναι από όπου προέρχεται το όνομα n+1.

Μπορούμε να τα πάμε καλύτερα; Σίγουρα! Χρησιμοποιώντας αυτό που είναι γνωστό ως ανυπόμονη φόρτωση, μπορούμε να αναγκάσουμε το ORM να εκτελέσει ένα JOIN και να επιστρέψει όλα τα απαραίτητα δεδομένα σε ένα μόνο ερώτημα! Σαν αυτό:

$orders = Customer::findMany($ids)->with('orders')->get();

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

SELECT * FROM customers INNER JOIN orders ON customers.id = orders.customer_id WHERE customers.id IN (22, 45, . . .);

Ένα μόνο ερώτημα είναι, φυσικά, καλύτερο από χίλια επιπλέον ερωτήματα. Φανταστείτε τι θα γινόταν αν υπήρχαν 10.000 πελάτες για επεξεργασία! Ή θεός να το κάνει αν θέλαμε να εμφανίσουμε και τα είδη που περιέχονται σε κάθε παραγγελία! Θυμηθείτε, το όνομα της τεχνικής είναι ανυπόμονη φόρτωση και είναι σχεδόν πάντα μια καλή ιδέα.

Αποθηκεύστε προσωρινά τη διαμόρφωση!

Ένας από τους λόγους για την ευελιξία της Laravel είναι οι τόνοι των αρχείων διαμόρφωσης που αποτελούν μέρος του πλαισίου. Θέλετε να αλλάξετε τον τρόπο/πού αποθηκεύονται οι εικόνες;

Λοιπόν, απλώς αλλάξτε το αρχείο config/filesystems.php (τουλάχιστον από τη στιγμή που γράφτηκε). Θέλετε να εργαστείτε με προγράμματα οδήγησης πολλαπλών ουρών; Μη διστάσετε να τα περιγράψετε στο config/queue.php. Μόλις μέτρησα και διαπίστωσα ότι υπάρχουν 13 αρχεία διαμόρφωσης για διαφορετικές πτυχές του πλαισίου, διασφαλίζοντας ότι δεν θα απογοητευτείτε ανεξάρτητα από το τι θέλετε να αλλάξετε.

Δεδομένης της φύσης της PHP, κάθε φορά που έρχεται ένα νέο αίτημα Web, η Laravel ξυπνά, εκκινεί τα πάντα και αναλύει όλα αυτά τα αρχεία διαμόρφωσης για να καταλάβει πώς να κάνει τα πράγματα διαφορετικά αυτή τη φορά. Μόνο που είναι χαζό αν δεν έχει αλλάξει τίποτα τις τελευταίες μέρες! Η επαναδημιουργία της διαμόρφωσης σε κάθε αίτημα είναι μια σπατάλη που μπορεί (στην πραγματικότητα, πρέπει να αποφευχθεί) και η διέξοδος είναι μια απλή εντολή που προσφέρει η Laravel:

php artisan config:cache

Αυτό που κάνει είναι να συνδυάζει όλα τα διαθέσιμα αρχεία διαμόρφωσης σε ένα και η προσωρινή μνήμη είναι κάπου για γρήγορη ανάκτηση. Την επόμενη φορά που θα υπάρξει αίτημα Ιστού, η Laravel απλώς θα διαβάσει αυτό το μεμονωμένο αρχείο και θα ξεκινήσει.

Τούτου λεχθέντος, η προσωρινή αποθήκευση διαμόρφωσης είναι μια εξαιρετικά λεπτή λειτουργία που μπορεί να εκραγεί στο πρόσωπό σας. Το μεγαλύτερο πρόβλημα είναι ότι μόλις εκδώσετε αυτήν την εντολή, η συνάρτηση env() καλεί από παντού εκτός από τα αρχεία διαμόρφωσης θα επιστρέψει null!

Έχει νόημα όταν το σκέφτεσαι. Εάν χρησιμοποιείτε προσωρινή αποθήκευση διαμόρφωσης, λέτε στο πλαίσιο: “Ξέρεις τι, νομίζω ότι έχω ρυθμίσει τα πράγματα καλά και είμαι 100% σίγουρος ότι δεν θέλω να αλλάξουν.” Με άλλα λόγια, περιμένεις το περιβάλλον να παραμείνει στατικό, κάτι που εξυπηρετούν τα αρχεία .env.

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

  • Κάντε το μόνο σε ένα σύστημα παραγωγής.
  • Κάντε το μόνο εάν είστε πραγματικά, πραγματικά βέβαιοι ότι θέλετε να παγώσετε τη διαμόρφωση.
  • Σε περίπτωση που κάτι πάει στραβά, αναιρέστε τη ρύθμιση με το php artisan cache:clear
  • Προσευχηθείτε να μην ήταν σημαντική η ζημιά που έγινε στην επιχείρηση!
  • Μειώστε τις υπηρεσίες που φορτώνονται αυτόματα

    Για να είναι χρήσιμο, το Laravel φορτώνει έναν τόνο υπηρεσιών όταν ξυπνήσει. Αυτά είναι διαθέσιμα στο αρχείο config/app.php ως μέρος του κλειδιού πίνακα «πάροχοι». Ας ρίξουμε μια ματιά σε αυτό που έχω στην περίπτωσή μου:

    /*
        |--------------------------------------------------------------------------
        | Autoloaded Service Providers
        |--------------------------------------------------------------------------
        |
        | The service providers listed here will be automatically loaded on the
        | request to your application. Feel free to add your own services to
        | this array to grant expanded functionality to your applications.
        |
        */
    
        'providers' => [
    
            /*
             * Laravel Framework Service Providers...
             */
            IlluminateAuthAuthServiceProvider::class,
            IlluminateBroadcastingBroadcastServiceProvider::class,
            IlluminateBusBusServiceProvider::class,
            IlluminateCacheCacheServiceProvider::class,
            IlluminateFoundationProvidersConsoleSupportServiceProvider::class,
            IlluminateCookieCookieServiceProvider::class,
            IlluminateDatabaseDatabaseServiceProvider::class,
            IlluminateEncryptionEncryptionServiceProvider::class,
            IlluminateFilesystemFilesystemServiceProvider::class,
            IlluminateFoundationProvidersFoundationServiceProvider::class,
            IlluminateHashingHashServiceProvider::class,
            IlluminateMailMailServiceProvider::class,
            IlluminateNotificationsNotificationServiceProvider::class,
            IlluminatePaginationPaginationServiceProvider::class,
            IlluminatePipelinePipelineServiceProvider::class,
            IlluminateQueueQueueServiceProvider::class,
            IlluminateRedisRedisServiceProvider::class,
            IlluminateAuthPasswordsPasswordResetServiceProvider::class,
            IlluminateSessionSessionServiceProvider::class,
            IlluminateTranslationTranslationServiceProvider::class,
            IlluminateValidationValidationServiceProvider::class,
            IlluminateViewViewServiceProvider::class,
    
            /*
             * Package Service Providers...
             */
    
            /*
             * Application Service Providers...
             */
            AppProvidersAppServiceProvider::class,
            AppProvidersAuthServiceProvider::class,
            // AppProvidersBroadcastServiceProvider::class,
            AppProvidersEventServiceProvider::class,
            AppProvidersRouteServiceProvider::class,
    
        ],

    Για άλλη μια φορά, μέτρησα, και υπάρχουν 27 υπηρεσίες που αναφέρονται! Τώρα, μπορεί να τα χρειαστείτε όλα, αλλά είναι απίθανο.

      7 Εργαλεία (δωρεάν + επί πληρωμή) για την παρακολούθηση της υγείας του Active Directory

    Για παράδειγμα, τυχαίνει να δημιουργώ ένα REST API αυτή τη στιγμή, πράγμα που σημαίνει ότι δεν χρειάζομαι το Session Service Provider, View Service Provider κ.λπ. Και επειδή κάνω μερικά πράγματα με τον δικό μου τρόπο και δεν ακολουθώ τις προεπιλογές του πλαισίου , μπορώ επίσης να απενεργοποιήσω τον πάροχο υπηρεσιών ελέγχου ταυτότητας, τον πάροχο υπηρεσιών σελιδοποίησης, τον πάροχο υπηρεσιών μετάφρασης και ούτω καθεξής. Συνολικά, σχεδόν τα μισά από αυτά είναι περιττά για την περίπτωση χρήσης μου.

    Ρίξτε μια μακρά, προσεκτική ματιά στην αίτησή σας. Χρειάζεται όλους αυτούς τους παρόχους υπηρεσιών; Αλλά για όνομα του Θεού, μην σχολιάζετε τυφλά αυτές τις υπηρεσίες και σπρώχνετε στην παραγωγή! Εκτελέστε όλες τις δοκιμές, ελέγξτε τα πράγματα με μη αυτόματο τρόπο σε προγραμματιστές και μηχανές σταδιοποίησης και να είστε πολύ παρανοϊκοί προτού πατήσετε τη σκανδάλη. 🙂

    Να είστε σοφοί με τις στοίβες ενδιάμεσων λογισμικών

    Όταν χρειάζεστε κάποια προσαρμοσμένη επεξεργασία του εισερχόμενου αιτήματος Ιστού, η δημιουργία ενός νέου ενδιάμεσου λογισμικού είναι η απάντηση. Τώρα, είναι δελεαστικό να ανοίξετε το app/Http/Kernel.php και να κολλήσετε το ενδιάμεσο λογισμικό στον ιστό ή στη στοίβα api. Με αυτόν τον τρόπο, γίνεται διαθέσιμο σε όλη την εφαρμογή και αν δεν κάνει κάτι ενοχλητικό (όπως η καταγραφή ή η ειδοποίηση, για παράδειγμα).

    Ωστόσο, καθώς η εφαρμογή μεγαλώνει, αυτή η συλλογή παγκόσμιων ενδιάμεσων λογισμικών μπορεί να γίνει σιωπηλή επιβάρυνση για την εφαρμογή εάν όλα (ή τα περισσότερα) από αυτά υπάρχουν σε κάθε αίτημα, ακόμα κι αν δεν υπάρχει επαγγελματικός λόγος για αυτό.

    Με άλλα λόγια, να προσέχετε πού προσθέτετε/εφαρμόζετε ένα νέο ενδιάμεσο λογισμικό. Μπορεί να είναι πιο βολικό να προσθέσετε κάτι παγκοσμίως, αλλά η ποινή απόδοσης είναι πολύ υψηλή μακροπρόθεσμα. Ξέρω τον πόνο που θα έπρεπε να υποστείτε αν εφαρμόσατε επιλεκτικά ενδιάμεσο λογισμικό κάθε φορά που υπάρχει μια νέα αλλαγή, αλλά είναι ένας πόνος που θα δεχόμουν πρόθυμα και θα το συνιστούσα!

    Αποφύγετε το ORM (κατά καιρούς)

    Ενώ το Eloquent κάνει πολλές πτυχές της αλληλεπίδρασης DB ευχάριστες, έρχεται σε βάρος της ταχύτητας. Όντας χαρτογράφος, το ORM όχι μόνο πρέπει να ανακτήσει εγγραφές από τη βάση δεδομένων, αλλά και να δημιουργήσει στιγμιότυπα τα αντικείμενα του μοντέλου και να τα ενυδατώσει (να τα συμπληρώσει) με δεδομένα στηλών.

    Έτσι, εάν κάνετε έναν απλό $users = User::all() και υπάρχουν, ας πούμε, 10.000 χρήστες, το πλαίσιο θα πάρει 10.000 σειρές από τη βάση δεδομένων και θα κάνει εσωτερικά 10.000 νέους User() και θα γεμίσει τις ιδιότητές τους με τα σχετικά δεδομένα . Αυτό είναι τεράστιος όγκος εργασίας που γίνεται στα παρασκήνια, και αν η βάση δεδομένων είναι το σημείο όπου βρίσκεστε η εφαρμογή σας γίνεται εμπόδιο, η παράκαμψη του ORM είναι μια καλή ιδέα μερικές φορές.

    Αυτό ισχύει ιδιαίτερα για πολύπλοκα ερωτήματα SQL, όπου θα έπρεπε να κάνετε πολλά πλήκτρα και να γράψετε closures on closures και να καταλήξετε με ένα αποτελεσματικό ερώτημα. Σε τέτοιες περιπτώσεις, προτιμάται να κάνετε μια DB::raw() και να γράψετε το ερώτημα με το χέρι.

    Πηγαίνει από Αυτό μελέτη απόδοσης, ακόμη και για απλά ένθετα Το Eloquent είναι πολύ πιο αργό καθώς αυξάνεται ο αριθμός των εγγραφών:

    Χρησιμοποιήστε την προσωρινή αποθήκευση όσο το δυνατόν περισσότερο

    Ένα από τα καλύτερα κρυμμένα μυστικά της βελτιστοποίησης εφαρμογών Ιστού είναι η προσωρινή αποθήκευση.

    Για τους μη μυημένους, η προσωρινή αποθήκευση σημαίνει προυπολογισμό και αποθήκευση ακριβών αποτελεσμάτων (ακριβή όσον αφορά τη χρήση της CPU και της μνήμης) και απλώς την επιστροφή τους όταν επαναλαμβάνεται το ίδιο ερώτημα.

    Για παράδειγμα, σε ένα κατάστημα ηλεκτρονικού εμπορίου, μπορεί να συναντήσει ότι από τα 2 εκατομμύρια προϊόντα, τις περισσότερες φορές οι άνθρωποι ενδιαφέρονται για αυτά που είναι πρόσφατα εφοδιασμένα, εντός ενός συγκεκριμένου εύρους τιμών και για μια συγκεκριμένη ηλικιακή ομάδα. Η αναζήτηση στη βάση δεδομένων για αυτές τις πληροφορίες είναι σπάταλη — καθώς το ερώτημα δεν αλλάζει συχνά, είναι καλύτερα να αποθηκεύουμε αυτά τα αποτελέσματα κάπου όπου μπορούμε να έχουμε γρήγορη πρόσβαση.

    Η Laravel έχει ενσωματωμένη υποστήριξη για διάφορους τύπους προσωρινή αποθήκευση. Εκτός από τη χρήση ενός προγράμματος οδήγησης προσωρινής αποθήκευσης και τη δημιουργία του συστήματος προσωρινής αποθήκευσης από την αρχή, ίσως θελήσετε να χρησιμοποιήσετε ορισμένα πακέτα Laravel που διευκολύνουν προσωρινή αποθήκευση μοντέλου, προσωρινή αποθήκευση ερωτημάτωνκαι τα λοιπά.

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

    Προτιμήστε την προσωρινή αποθήκευση στη μνήμη

    Όταν αποθηκεύετε στην προσωρινή μνήμη κάτι στο Laravel, έχετε πολλές επιλογές για το πού να αποθηκεύσετε τον υπολογισμό που προκύπτει που πρέπει να αποθηκευτεί προσωρινά. Αυτές οι επιλογές είναι επίσης γνωστές ως προγράμματα οδήγησης κρυφής μνήμης. Έτσι, ενώ είναι δυνατό και απολύτως λογικό να χρησιμοποιείτε το σύστημα αρχείων για την αποθήκευση των αποτελεσμάτων της κρυφής μνήμης, δεν είναι στην πραγματικότητα αυτό που πρέπει να είναι η προσωρινή αποθήκευση.

    Στην ιδανική περίπτωση, θέλετε να χρησιμοποιήσετε μια μνήμη cache (που μένει εξ ολοκλήρου στη μνήμη RAM) όπως το Redis, το Memcached, το MongoDB κ.λπ., έτσι ώστε κάτω από υψηλότερα φορτία, η προσωρινή αποθήκευση να εξυπηρετεί μια ζωτική χρήση αντί να γίνεται η ίδια μια συμφόρηση.

    Τώρα, μπορεί να πιστεύετε ότι η ύπαρξη ενός δίσκου SSD είναι σχεδόν το ίδιο με τη χρήση ενός στικ RAM, αλλά δεν είναι καν κοντά. Ακόμα και άτυπη σημεία αναφοράς δείχνουν ότι η RAM υπερτερεί του SSD κατά 10-20 φορές όσον αφορά την ταχύτητα.

    Το αγαπημένο μου σύστημα όσον αφορά την προσωρινή αποθήκευση είναι το Redis. Του γελοία γρήγορα (100.000 λειτουργίες ανάγνωσης ανά δευτερόλεπτο είναι κοινές) και για πολύ μεγάλα συστήματα κρυφής μνήμης, μπορούν να εξελιχθούν σε σύμπλεγμα εύκολα.

      Πώς να διαχειριστείτε την απεριόριστη συνδρομή στο Kindle

    Αποθηκεύστε προσωρινά τις διαδρομές

    Ακριβώς όπως η διαμόρφωση της εφαρμογής, οι διαδρομές δεν αλλάζουν πολύ με την πάροδο του χρόνου και είναι ιδανικός υποψήφιος για προσωρινή αποθήκευση. Αυτό ισχύει ιδιαίτερα αν δεν αντέχετε μεγάλα αρχεία όπως εγώ και καταλήγετε να χωρίζετε το web.php και το api.php σας σε πολλά αρχεία. Μία μόνο εντολή Laravel συσκευάζει όλες τις διαθέσιμες διαδρομές και τις κρατά εύχρηστες για μελλοντική πρόσβαση:

    php artisan route:cache

    Και όταν καταλήξετε να προσθέσετε ή να αλλάξετε διαδρομές, απλώς κάντε:

    php artisan route:clear

    Βελτιστοποίηση εικόνας και CDN

    Οι εικόνες είναι η καρδιά και η ψυχή των περισσότερων εφαρμογών Ιστού. Συμπτωματικά, είναι επίσης οι μεγαλύτεροι καταναλωτές εύρους ζώνης και ένας από τους μεγαλύτερους λόγους για αργές εφαρμογές/ιστοτόπους. Εάν απλώς αποθηκεύετε τις μεταφορτωμένες εικόνες αφελώς στον διακομιστή και τις στέλνετε πίσω σε απαντήσεις HTTP, αφήνετε μια τεράστια ευκαιρία βελτιστοποίησης να χαθεί.

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

    Αντ ‘αυτού, αναζητήστε μια λύση όπως Συννεφιασμένος που αλλάζει αυτόματα το μέγεθος και βελτιστοποιεί τις εικόνες εν κινήσει.

    Εάν αυτό δεν είναι δυνατό, χρησιμοποιήστε κάτι όπως το Cloudflare για την προσωρινή αποθήκευση και την προβολή εικόνων ενώ είναι αποθηκευμένες στον διακομιστή σας.

    Και αν ακόμη και αυτό δεν είναι δυνατό, το να τροποποιήσετε λίγο το λογισμικό του διακομιστή ιστού σας για να συμπιέσετε τα στοιχεία και να κατευθύνετε το πρόγραμμα περιήγησης του επισκέπτη στην προσωρινή αποθήκευση των πραγμάτων, έχει μεγάλη διαφορά. Δείτε πώς θα μοιάζει ένα απόσπασμα της διαμόρφωσης Nginx:

    server {
    
       # file truncated
        
        # gzip compression settings
        gzip on;
        gzip_comp_level 5;
        gzip_min_length 256;
        gzip_proxied any;
        gzip_vary on;
    
       # browser cache control
       location ~* .(ico|css|js|gif|jpeg|jpg|png|woff|ttf|otf|svg|woff2|eot)$ {
             expires 1d;
             access_log off;
             add_header Pragma public;
             add_header Cache-Control "public, max-age=86400";
        }
    }

    Γνωρίζω ότι η βελτιστοποίηση εικόνας δεν έχει καμία σχέση με τη Laravel, αλλά είναι ένα τόσο απλό και ισχυρό κόλπο (και τόσο συχνά παραμελείται) που δεν θα μπορούσα να βοηθήσω τον εαυτό μου.

    Βελτιστοποίηση Autoloader

    Η αυτόματη φόρτωση είναι μια τακτοποιημένη, όχι και τόσο παλιά δυνατότητα στην PHP που αναμφισβήτητα έσωσε τη γλώσσα από την καταστροφή. Τούτου λεχθέντος, η διαδικασία εύρεσης και φόρτωσης της σχετικής κλάσης με την αποκρυπτογράφηση μιας δεδομένης συμβολοσειράς χώρου ονομάτων απαιτεί χρόνο και μπορεί να αποφευχθεί σε αναπτύξεις παραγωγής όπου είναι επιθυμητή η υψηλή απόδοση. Για άλλη μια φορά, η Laravel έχει μια λύση μίας εντολής σε αυτό:

    composer install --optimize-autoloader --no-dev

    Κάντε φίλους με ουρές

    Ουρές είναι ο τρόπος με τον οποίο επεξεργάζεστε τα πράγματα όταν υπάρχουν πολλά από αυτά και καθένα από αυτά χρειάζεται μερικά χιλιοστά του δευτερολέπτου για να ολοκληρωθεί. Ένα καλό παράδειγμα είναι η αποστολή μηνυμάτων ηλεκτρονικού ταχυδρομείου – μια ευρέως διαδεδομένη περίπτωση χρήσης στις εφαρμογές Ιστού είναι η λήψη μερικών μηνυμάτων ηλεκτρονικού ταχυδρομείου ειδοποίησης όταν ένας χρήστης εκτελεί ορισμένες ενέργειες.

    Για παράδειγμα, σε ένα προϊόν που κυκλοφόρησε πρόσφατα, μπορεί να θέλετε η ηγεσία της εταιρείας (περίπου 6-7 διευθύνσεις email) να ειδοποιείται κάθε φορά που κάποιος κάνει μια παραγγελία πάνω από μια συγκεκριμένη τιμή. Υποθέτοντας ότι η πύλη email σας μπορεί να ανταποκριθεί στο αίτημά σας SMTP σε 500 ms, μιλάμε για μια καλή αναμονή 3-4 δευτερολέπτων για τον χρήστη πριν ξεκινήσει η επιβεβαίωση της παραγγελίας. Ένα πολύ κακό κομμάτι UX, είμαι σίγουρος ότι θα το κάνετε συμφωνώ.

    Η λύση είναι να αποθηκεύσετε τις εργασίες καθώς έρχονται, να πείτε στον χρήστη ότι όλα πήγαν καλά και να τις επεξεργαστείτε (λίγα δευτερόλεπτα) αργότερα. Εάν υπάρχει κάποιο σφάλμα, οι εργασίες στην ουρά μπορούν να επαναληφθούν μερικές φορές προτού δηλωθούν ότι απέτυχαν.

    Πιστώσεις: Microsoft.com

    Ενώ ένα σύστημα ουράς περιπλέκει λίγο τη ρύθμιση (και προσθέτει κάποια επιβάρυνση παρακολούθησης), είναι απαραίτητο σε μια σύγχρονη εφαρμογή Ιστού.

    Βελτιστοποίηση περιουσιακών στοιχείων (Mix Laravel)

    Για τυχόν στοιχεία διεπαφής στην εφαρμογή Laravel, βεβαιωθείτε ότι υπάρχει μια διοχέτευση που συγκεντρώνει και ελαχιστοποιεί όλα τα αρχεία στοιχείων. Όσοι αισθάνονται άνετα με ένα σύστημα bundler όπως το Webpack, το Gulp, το Parcel κ.λπ., δεν χρειάζεται να ασχοληθούν, αλλά αν δεν το κάνετε ήδη, Μείγμα Laravel είναι μια σταθερή σύσταση.

    Το Mix είναι ένα ελαφρύ (και απολαυστικό, με κάθε ειλικρίνεια!) περιτύλιγμα γύρω από το Webpack που φροντίζει όλα τα αρχεία σας CSS, SASS, JS κ.λπ. για παραγωγή. Ένα τυπικό αρχείο .mix.js μπορεί να είναι τόσο μικρό όσο αυτό και εξακολουθεί να κάνει θαύματα:

    const mix = require('laravel-mix');
    
    mix.js('resources/js/app.js', 'public/js')
        .sass('resources/sass/app.scss', 'public/css');

    Αυτό φροντίζει αυτόματα τις εισαγωγές, την ελαχιστοποίηση, τη βελτιστοποίηση και ολόκληρο το shebang όταν είστε έτοιμοι για παραγωγή και εκτελέσετε παραγωγή npm run. Το Mix φροντίζει όχι μόνο τα παραδοσιακά αρχεία JS και CSS, αλλά και τα στοιχεία Vue και React που μπορεί να έχετε στη ροή εργασίας της εφαρμογής σας.

    Περισσότερες πληροφορίες εδώ!

    συμπέρασμα

    Η βελτιστοποίηση απόδοσης είναι περισσότερο τέχνη παρά επιστήμη — το να ξέρεις πώς και πόσα πρέπει να κάνεις είναι σημαντικό από το τι να κάνεις. Τούτου λεχθέντος, δεν υπάρχει τέλος στο πόσα και τι μπορείτε να βελτιστοποιήσετε σε μια εφαρμογή Laravel.

    Αλλά ό,τι κι αν κάνετε, θα ήθελα να σας αφήσω μερικές συμβουλές αποχωρισμού — η βελτιστοποίηση πρέπει να γίνεται όταν υπάρχει σοβαρός λόγος και όχι επειδή ακούγεται καλό ή επειδή είστε παρανοϊκοί σχετικά με την απόδοση της εφαρμογής για 100.000+ χρήστες ενώ στην πραγματικότητα υπάρχουν μόνο 10.

    Εάν δεν είστε σίγουροι αν πρέπει να βελτιστοποιήσετε την εφαρμογή σας ή όχι, δεν χρειάζεται να κλωτσήσετε την παροιμιώδη φωλιά των κηφήνων. Μια λειτουργική εφαρμογή που αισθάνεται βαρετή, αλλά κάνει ακριβώς αυτό που πρέπει, είναι δέκα φορές πιο επιθυμητή από μια εφαρμογή που έχει βελτιστοποιηθεί σε μεταλλαγμένο υβριδικό υπερμηχανή, αλλά καταρρέει κάθε τόσο.

    Και, για να γίνει ο αρχάριος κύριος της Laravel, ρίξτε μια ματιά σε αυτό διαδικτυακό μάθημα.

    Μακάρι οι εφαρμογές σας να τρέχουν πολύ, πολύ πιο γρήγορα! 🙂