Προγραμματισμός

Συμβουλές JMeter

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

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

Παρακαλώ σημειώστε ότι υποθέτω ότι οι αναγνώστες γνωρίζουν τα βασικά του JMeter. Τα παραδείγματα αυτού του άρθρου βασίζονται στο JMeter 2.0.3.

Προσδιορίστε την περίοδο βελτίωσης μιας ομάδας νήματος

Το πρώτο συστατικό στο σενάριο JMeter είναι μια ομάδα νήματος, οπότε ας το αναθεωρήσουμε πρώτα. Όπως φαίνεται στο σχήμα 1, ένα στοιχείο ομάδας νημάτων περιέχει τις ακόλουθες παραμέτρους:

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

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

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

Οι περισσότερες από τις παραμέτρους μιας ομάδας νήματος είναι αυτονόητες, αλλά η περίοδος αύξησης είναι λίγο περίεργη, καθώς ο κατάλληλος αριθμός δεν είναι πάντα προφανής. Για ένα πράγμα, η περίοδος αύξησης δεν πρέπει να είναι μηδενική εάν έχετε μεγάλο αριθμό νημάτων. Στην αρχή μιας δοκιμής φόρτωσης, εάν η περίοδος αύξησης είναι μηδέν, το JMeter θα δημιουργήσει όλα τα νήματα ταυτόχρονα και θα στείλει αιτήματα αμέσως, με αποτέλεσμα να κορεστεί ο διακομιστής και, το πιο σημαντικό, αυξάνοντας παραπλανητικά το φορτίο. Δηλαδή, ο διακομιστής θα μπορούσε να υπερφορτωθεί, όχι επειδή ο μέσος ρυθμός επίσκεψης είναι υψηλός, αλλά επειδή στέλνετε ταυτόχρονα τα πρώτα αιτήματα όλων των νημάτων, προκαλώντας ασυνήθιστο αρχικό ρυθμό επιτυχίας. Μπορείτε να δείτε αυτό το εφέ με έναν ακροατή αναφοράς JMeter Aggregate.

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

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

Πώς λοιπόν επαληθεύετε ότι η περίοδος αύξησης δεν είναι ούτε πολύ μικρή ούτε πολύ μεγάλη; Κατ 'αρχάς, μαντέψτε το μέσο ποσοστό επίσκεψης και, στη συνέχεια, υπολογίστε την αρχική περίοδο αύξησης διαιρώντας τον αριθμό των νημάτων με το υποτιθέμενο ποσοστό επιτυχίας. Για παράδειγμα, εάν ο αριθμός των νημάτων είναι 100 και ο εκτιμώμενος ρυθμός επιτυχίας είναι 10 επισκέψεις ανά δευτερόλεπτο, η εκτιμώμενη ιδανική περίοδος αύξησης είναι 100/10 = 10 δευτερόλεπτα. Πώς καταλήγετε με εκτιμώμενο ποσοστό επίσκεψης; Δεν υπάρχει εύκολος τρόπος. Πρέπει απλώς να εκτελέσετε το δοκιμαστικό σενάριο μία φορά πρώτα.

Δεύτερον, προσθέστε ένα πρόγραμμα ακρόασης Αναφορών Συγκεντρωτικού, που φαίνεται στο Σχήμα 2, στο σχέδιο δοκιμής. Περιέχει το μέσο ποσοστό επίσκεψης κάθε μεμονωμένου αιτήματος (JMeter samplers). Ο ρυθμός επίσκεψης του πρώτου δειγματοληπτικού προγράμματος (π.χ. αίτημα HTTP) σχετίζεται στενά με την περίοδο αύξησης και τον αριθμό των νημάτων. Προσαρμόστε την περίοδο αύξησης, έτσι ώστε ο ρυθμός επιτυχίας του πρώτου δειγματοληπτικού σχεδίου δοκιμής να πλησιάζει το μέσο ρυθμό επιτυχίας όλων των άλλων δειγματοληπτών.

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

Συνοπτικά, ο καθορισμός ενός καλού χρόνου αύξησης διέπεται από τους ακόλουθους δύο κανόνες:

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

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

Χρόνος σκέψης χρήστη, χρονόμετρο και διακομιστής μεσολάβησης

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

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

Ο διακομιστής μεσολάβησης καταγράφει τις ενέργειές σας ενώ περιηγείστε σε μια εφαρμογή Web με ένα κανονικό πρόγραμμα περιήγησης (όπως FireFox ή Internet Explorer). Επιπλέον, το JMeter δημιουργεί ένα σχέδιο δοκιμής κατά την καταγραφή των ενεργειών σας. Αυτή η δυνατότητα είναι εξαιρετικά βολική για διάφορους σκοπούς:

  • Δεν χρειάζεται να δημιουργήσετε ένα αίτημα HTTP χειροκίνητα, ειδικά αυτές οι κουραστικές παράμετροι φόρμας. (Ωστόσο, οι μη αγγλικές παράμετροι ενδέχεται να μην λειτουργούν σωστά.) Το JMeter θα καταγράψει τα πάντα στα αιτήματα που δημιουργούνται αυτόματα, συμπεριλαμβανομένων των κρυφών πεδίων.
  • Στο δημιουργημένο σχέδιο δοκιμών, το JMeter περιλαμβάνει όλες τις κεφαλίδες HTTP που δημιουργούνται από το πρόγραμμα περιήγησης για εσάς, όπως User-Agent (π.χ. Mozilla / 4.0) ή AcceptLanguage (π.χ. zh-tw, en-us; q = 0.7, zh- cn; q = 0,3).
  • Το JMeter μπορεί να δημιουργήσει χρονόμετρα της επιλογής σας, όπου ο χρόνος καθυστέρησης ορίζεται σύμφωνα με την πραγματική καθυστέρηση κατά τη διάρκεια της περιόδου εγγραφής.

Ας δούμε πώς να ρυθμίσετε το JMeter με τη δυνατότητα εγγραφής. Στην κονσόλα JMeter, κάντε δεξί κλικ στο στοιχείο WorkBench και προσθέστε το στοιχείο διακομιστή μεσολάβησης HTTP. Σημειώστε ότι κάνετε δεξί κλικ στο στοιχείο WorkBench, όχι στο στοιχείο Test Plan, επειδή η διαμόρφωση εδώ είναι για εγγραφή και όχι για ένα εκτελέσιμο πρόγραμμα δοκιμών. Ο σκοπός του στοιχείου διακομιστή μεσολάβησης HTTP είναι να διαμορφώσετε τον διακομιστή μεσολάβησης του προγράμματος περιήγησης έτσι ώστε όλα τα αιτήματα να περάσουν από το JMeter.

Όπως φαίνεται στο σχήμα 3, πρέπει να διαμορφωθούν διάφορα πεδία για το στοιχείο διακομιστή μεσολάβησης HTTP:

  • Λιμάνι: Η θύρα ακρόασης που χρησιμοποιείται από τον διακομιστή μεσολάβησης.
  • Ελεγκτής στόχου: Ο ελεγκτής όπου ο διακομιστής μεσολάβησης αποθηκεύει τα παραγόμενα δείγματα. Από προεπιλογή, το JMeter θα αναζητήσει έναν ελεγκτή εγγραφής στο τρέχον σχέδιο δοκιμών και θα αποθηκεύσει τα δείγματα εκεί. Εναλλακτικά, μπορείτε να επιλέξετε οποιοδήποτε στοιχείο ελεγκτή που αναφέρεται στο μενού. Συνήθως, η προεπιλογή είναι εντάξει.
  • Ομαδοποίηση: Πώς θα θέλατε να ομαδοποιήσετε τα παραγόμενα στοιχεία στο σχέδιο δοκιμών. Διατίθενται πολλές επιλογές και η πιο λογική είναι πιθανώς "Αποθήκευση 1ου δείγματος μόνο για κάθε ομάδα", διαφορετικά, θα καταγράφονται επίσης οι διευθύνσεις URL που είναι ενσωματωμένες σε μια σελίδα, όπως αυτές για εικόνες και JavaScript. Ωστόσο, μπορεί να θέλετε να δοκιμάσετε την προεπιλεγμένη επιλογή "Να μην ομαδοποιήσετε δείγματα" για να μάθετε τι ακριβώς δημιουργεί το JMeter για εσάς στο σχέδιο δοκιμών.
  • Μοτίβα προς συμπερίληψη και Μοτίβα προς εξαίρεση: Σας βοηθά να φιλτράρετε ορισμένα ανεπιθύμητα αιτήματα.

Όταν κάνετε κλικ στο κουμπί Έναρξη, ο διακομιστής μεσολάβησης ξεκινά και αρχίζει την καταγραφή των αιτημάτων HTTP που λαμβάνει. Φυσικά, πριν κάνετε κλικ στο Έναρξη, πρέπει να διαμορφώσετε τη ρύθμιση διακομιστή μεσολάβησης του προγράμματος περιήγησής σας.

Μπορείτε να προσθέσετε ένα χρονόμετρο ως θυγατρικό του στοιχείου διακομιστή μεσολάβησης HTTP, το οποίο θα δώσει εντολή στο JMeter να προσθέσει αυτόματα ένα χρονόμετρο ως θυγατρικό του αιτήματος HTTP που δημιουργεί. Το JMeter αποθηκεύει αυτόματα την πραγματική καθυστέρηση χρόνου σε μια μεταβλητή JMeter που ονομάζεται Τ, οπότε αν προσθέσετε ένα τυχαίο χρονόμετρο Gauss στο στοιχείο διακομιστή μεσολάβησης HTTP, θα πρέπει να πληκτρολογήσετε $ {Τ} στο πεδίο Constant Delay, όπως φαίνεται στο σχήμα 4. Αυτό είναι ένα άλλο βολικό χαρακτηριστικό που σας εξοικονομεί πολύ χρόνο.

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

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

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

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

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

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

Υπάρχει ένα σύνολο γνωστών κανόνων για τον προσδιορισμό των κριτηρίων χρόνου απόκρισης:

  • Οι χρήστες δεν παρατηρούν καθυστέρηση μικρότερη από 0,1 δευτερόλεπτο
  • Μια καθυστέρηση μικρότερη από 1 δευτερόλεπτο δεν διακόπτει τη ροή σκέψης ενός χρήστη, αλλά παρατηρείται κάποια καθυστέρηση
  • Οι χρήστες θα περιμένουν ακόμη την απάντηση εάν καθυστερήσει λιγότερο από 10 δευτερόλεπτα
  • Μετά από 10 δευτερόλεπτα, οι χρήστες χάνουν την εστίαση και αρχίζουν να κάνουν κάτι άλλο

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

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

  • Μέσος χρόνος απόκρισης
  • Απόλυτος χρόνος απόκρισης. Δηλαδή, οι χρόνοι απόκρισης όλων των απαντήσεων πρέπει να είναι κάτω από το κατώφλι

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

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

Ας εξετάσουμε τα βασικά στατιστικά στοιχεία προτού προχωρήσουμε περαιτέρω.

Το κεντρικό θεώρημα ορίου

Το κεντρικό θεώρημα ορίου δηλώνει ότι εάν η κατανομή του πληθυσμού έχει μέση μ και τυπική απόκλιση σ, τότε, για αρκετά μεγάλο n (> 30), η κατανομή δειγματοληψίας του μέσου δειγματοληψίας είναι περίπου φυσιολογική, με μέση μσημαίνω = μ και τυπική απόκλιση σσημαίνω = σ / √n.

Σημειώστε ότι η κατανομή του μέσου δειγματοληψίας ειναι ΦΥΣΙΟΛΟΓΙΚΟ. Η κατανομή της ίδιας της δειγματοληψίας δεν είναι απαραίτητα φυσιολογική. Δηλαδή, αν εκτελέσετε το δοκιμαστικό σενάριο πολλές φορές, η κατανομή των προκύπτοντων μέσων χρόνων απόκρισης θα είναι φυσιολογική.

Τα σχήματα 5 και 6 παρακάτω δείχνουν δύο κανονικές κατανομές. Στο πλαίσιο μας, ο οριζόντιος άξονας είναι ο μέσος όρος δειγματοληψίας του χρόνου απόκρισης, μετατοπισμένος έτσι ο μέσος πληθυσμός είναι στην αρχή. Το Σχήμα 5 δείχνει ότι το 90 τοις εκατό του χρόνου, τα μέσα δειγματοληψίας βρίσκονται εντός του διαστήματος ± Zσ, όπου Z = 1.645 και σ είναι η τυπική απόκλιση. Το Σχήμα 6 δείχνει την περίπτωση 99 τοις εκατό, όπου Ζ = 2.576. Για μια δεδομένη πιθανότητα, ας πούμε 90 τοις εκατό, μπορούμε να αναζητήσουμε την αντίστοιχη τιμή Ζ με μια κανονική καμπύλη και το αντίστροφο.