Κυριακή 24 Ιανουαρίου 2016

Αναθεώρηση 142 - Αλλαγή μεγέθους Stack

Στην αναθεώρηση 142 έκανα κάποιες εργασίες για να βελτιωθεί η ταχύτητα και επιπλέον βρήκα και τον τρόπο να αλλάξω το μέγεθος του stack, της στοίβας που γράφει τις παραμέτρους των συναρτήσεων, ώστε να αυξήσω το βάθος κλήσεων από 128 κλήσεις σε 14500 κλήσεις.

Όταν η γλώσσα ανοίγει στο IDE της Vb6 και τρέχει εκεί τότε αυτόματα οι κλήσεις περιορίζονται σε 128. Οι ρουτίνες (Subs) έχουν αρχικό όριο 10000 αλλά μπορούμε να το αλλάξουμε, π.χ. 50000 γιατί δεν χρησιμοποιείται stack όπως στις ρουτίνες, αλλά μνήμη γενικότερα. Ως προς τις ρουτίνες δηλαδή δεν άλλαξε κάτι. Υπενθυμίζω ότι μπορούμε να καλέσουμε μια ρουτίνα χωρίς την εντολή ΔΙΑΜΕΣΟΥ αν δεν έχουμε πίνακα με το ίδιο αναγνωριστικό. Οι ρουτίνες και οι συναρτήσεις έχουν αναδρομή, δηλαδή μπορούν να καλέσουν τον εαυτό τους. Οι ρουτίνες δεν έχουν αντικείμενο εκτέλεσης, αλλά τρέχουν στο αντικείμενο που της καλεί, σε τμήμα ή συνάρτηση..Είναι πιο ελαφριές αλλά δεν μπαίνουν όπως οι συναρτήσεις μέσα σε παραστάσεις, αριθμητικές ή αλφαριθμητικές. Όμως χρησιμοποιούν των σωρό τιμών και μπορούν να αφήσουν εκεί ότι θέλουμε, ή να χρησιμοποιήσουμε μεταβλητή με αναφορά, ή να χρησιμοποιήσουμε μια μεταβλητή του τμήματος ή συνάρτησης που το κάλεσε, αφού μια ρουτίνα έχει πρόσβαση σε ότι βλέπει το τμήμα/συνάρτηση που την καλεί.


Αν αλλάξουμε το κώδικα της Μ2000 (π.χ. θέλουμε να προσθέσουμε κάποιες εντολές), και φτιάξουμε το exe αρχείο (με την Vb 6) , τότε πρέπει να εκτελέσουμε το παρακάτω πρόγραμμα, το οποίο το γράφουμε σε ένα αρχείο stack.gsb  (υπάρχει ένα παρόμοιο στο φάκελο με τα αρχεία του προγράμματος, αλλά αυτό εδώ είναι πιο γενικό)
Χρειαζόμαστε το Editbin το οποίο το βρίσκουμε ή στο φάκελο της VC98, ή κατεβάζουμε το masm32, από το Masm32 SDK

Στο Module A έχουμε το τεστ με τη μεγάλη αναδρομική κλήση. Στο Module B έχουμε το πρόγραμμα που φτιάχνουμε δυο bat αρχεία (batch τα λέμε), όπου ένα καλούμε για να να δώσει πληροφορίες και το άλλο για να κάνει τη δουλειά, να αλλάξει το stack. Ο λόγος που το έσπασα στα δύο είναι γιατί πρέπει να κλείσει η Μ2000 και μετά να κάνουμε την αλλαγή.  Το Set End στέλνει στον μεταφραστή γραμμής την εντολή End, ενώ χωρίς το Set το End κάνει ότι και η Exit - έξοδος από το μπλοκ (μπλοκ θεωρείται και το τμήμα, αλλά δείτε στο πρόγραμμα, έχω χρησιμοποιήσει την Break για να βγω από το τμήμα, μέσα από άλλο μπλοκ μέσα στο τμήμα). Η Rem ή Σημ κάνει ότι και η \ ή ' δηλαδή αφήνει τη γραμμή ως σημειώσεις (remarks) αλλά επιτρέπει στον διορθωτή να χρωματίσει σαν να ήταν οι σημειώσει εντολές.  Δείτε εδώ ότι γράφουμε στο cmd παράθυρο το Stack (το ίδιο όνομα με το gsb, αλλά εδώ καλούμε το Stack.bat)

Δείτε με τη βοήθεια τις εντολές Dos και Win
π.χ. Win dir$ ανοίγει τον τρέχον φάκελο στον explorer. H Win είναι σαν Start, π.χ. Win Calc ανοίγει την αριθμομηχανή. Μπορεί όμως να ανοίξει έγγραφα (δηλαδή τύπους αρχείων που γνωρίζει το σύστημα με τι ανοίγουν). Η εντολή Dos στέλνει στο cmd ότι θέλουμε (σε μια γραμμή).
Αυτές οι εντολές ΔΕΝ λειτουργούν αν επιλέξουμε χρήστη (δηλαδή όχι τον αρχικό αλλά κάποιο όνομα με την εντολή User ή Χρήστης). Τότε η Μ2000 περιορίζει την πρόσβαση για ασφάλεια, στο φάκελο του χρήστη. 
Ακόμα και αν αλλάξουμε τον τρέχοντα φάκελο..μπορούμε να επιστρέψουμε στο φάκελο χρήση με την εντολή Dir User  ή Κατάλογος Χρήστη. Η εντολή Dir ή Κατάλογος χωρίς παράμετρο μας δίνει τα περιεχόμενα του καταλόγου. 



Module A {
      Function rec {
                  Read bb
                  If bb<=0 Then =0 : Exit
                  Print bb
                  =rec(bb-1)
      }
      a= rec(14500)
}
Module B {\\ script For making needed batch files For setting stack For m2000.exe
      \\ when we make the final exe
      curdir$=Dir$
      \\ use editbin from masm32
      rem defaultpath$="C:\masm32\bin\"
      \\ or use the one from VC98
      defaultpath$="C:\Program Files\Microsoft Visual Studio\VC98\Bin\"
      If Not Exist(defaultpath$+"editbin.exe") Then {
            Dir ? "c:", "Need Editbin.exe Folder"
            defaultpath$=Dir$
            Dir curdir$
            If Not Exist(defaultpath$+"editbin.exe") Then Break
      }
      document dd$= {Echo off
            Cls
            Echo Set Stack Size For M2000 - press enter
            }
      \\ = is append For document  - use clear dd$ to clear it.
      dd$ = Shortdir$(defaultpath$) + {editbin /stack:102402048 m2000.exe}
      Dir Appdir$
      \\ without "For Wide Output" we output ascii text
      Open "stack.bat" For Output As i
      Print #i, dd$
      Close #i
      Clear dd$
      dd$ ={Cls
            Echo Execute stack.bat to set stack size For m2000, ver 8, rev 142+
            }
      Open "Info.bat" For Output As i
      Print #i,"Echo off"
      Print #i, "cd "+Quote$(Appdir$)
      Print #i, dd$
      Close #i
      Dos "cd "+Quote$(Appdir$) + " &&  Info.bat"
      Set End
}

Υλοποιώ την 8.1 έκδοση. Θέλει δουλειά, αλλά είναι σε ένα 70%. Το ζήτημα εδώ είναι να γίνει η αναζήτηση μεταβλητών στον ίδιο χρόνο ανεξάρτητα από το πόσες φτιάχνει κανείς. Στην υπάρχουσα υλοποίηση (έκδοση 8, αναθεώρηση 142), οι μεταβλητές αναζητούνται σειριακά από την τελευταία. Η τελευταία είναι και η τελευταία που δημιουργήθηκε. Επιπλέον στη Μ2000 δεν υπάρχει αναζήτηση πέρα του τμήματος, παρά μόνο για γενικές. Οπότε στις γενικές υπάρχει ένα πέναλτι χρόνου, αν όμως βρίσκονται στο βάθος, δηλαδή αν έχουμε μεγάλη διαφορά "απόστασης". Πραγματικά η απόσταση εδώ έχει νόημα αφού τα ονόματα γράφονται σε ένα αλφαριθμητικό. 
Η έκδοση 8.1 χρησιμοποιεί πίνακα κατακερματισμού που δύναται να επεκταθεί. Στην επέκταση χρησιμοποιούνται μερικά αποτελέσματα για να υπολογιστούν οι νέες θέσεις (δηλαδή αν έχουμε 1000 μεταβλητές θα γίνουν χίλιοι υπολογισμοί και θα περαστούν σε θέσεις στον πίνακα κατακερματισμού και όπου υπάρχουν συγκρούσεις θα ενημερωθεί ένας δείκτης "επόμενο"). Η λογική του πίνακα κατακερματισμού έχει εμφανιστεί εδώ στο blog σαν πρόγραμμα της Μ2000.

Κερδίζουμε από τη χρήση του πίνακα γιατί για κάθε φορά που αναζητούμε κάτι εκτελούμε την συνάρτηση κατακερματισμού και μας λέει σε ποια θέση στο πίνακα πέφτει αυτό που ζητάμε. Κοιτάμε αν υπάρχει εκεί και αν όχι τότε κοιτάμε τι δείχνει αυτό..ως επόμενο...μέχρι να το βρούμε ή να μην υπάρχει επόμενο. Ουσιαστικά πάμε σε σειριακή αναζήτηση μόνο σε εκείνα τα στοιχεία που δίνουν ίδιο αποτέλεσμα στην συνάρτηση κατακερματισμού. Πετυχαίνουμε εν τέλει σχεδόν σταθερό χρόνο αναζήτησης για οποιοδήποτε αριθμό στοιχείων! Πιο γρήγορος τρόπος υπάρχει με collection (την παρέχει η vb) αλλά δεν ταιριάζει με την περίπτωση εδώ, επειδή στη Μ2000 μπορούμε να ορίσουμε τοπική μεταβλητή με ακριβώς ίδια στοιχεία, για το ίδιο αντικείμενο εκτέλεσης, άρα ο πίνακας κατακερματισμού θα έχει ίδια κλειδιά και το collection της Vb6..δεν το δέχεται. Εδώ στα ίδια κλειδιά διαβάζουμε πάντα από το τελευταίο.

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

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







Δεν υπάρχουν σχόλια:

Δημοσίευση σχολίου

You can feel free to write any suggestion, or idea on the subject.