Πιο γρήγορα στρινγκς!

Σε αυτή την περιοχή μπορείτε να βρείτε ή να αναζητήσετε πληροφορίες σχετικές με την PHP

Συντονιστές: WebDev Moderators, Super-Moderators

gvre
Δημοσιεύσεις: 992
Εγγραφή: 14 Οκτ 2010 11:34
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από gvre » 10 Ιούλ 2011 02:07

pimpogio έγραψε:40'' στο 1 μυριο ειναι η καθυστερηση στα strings
η καθυστερηση στα 1 μυριο inserts ειναι παρα πολυ παραπανω που κανει τα 40'' ασημαντα αυτο λεω.
Δε διαφωνώ σχετικά με το ότι η καθυστέρηση από τα inserts είναι πολύ μεγαλύτερη. Γι' αυτό το λόγο έγραψα παραπάνω ότι οι αλλαγές στη συνάρτηση πρέπει να συνδυαστούν με transactions κλπ.

pimpogio
Δημοσιεύσεις: 1080
Εγγραφή: 28 Δεκ 2010 14:08

Πιο γρήγορα στρινγκς!

Δημοσίευση από pimpogio » 10 Ιούλ 2011 04:49

τα inserts θα τα βαλεις σε prepared statment
και θα ειναι ετσι

Κώδικας: Επιλογή όλων

$sql="INSERT INTO yourtable
( ID ) VALUES
(?),
(?),
(?),
(?),
(?),
(?),
(?),
......
......
(?)";
πολλα rows δηλαδη ανα insert..
τοσα rows ωστε να γεμιζει ακριβως 1 block
και επειδη αυτο ειναι πρακτικα δυσκολο να το πετυχεις
βαλε πολλα ωστε να γεμιζουνε πολλα blocks και να μενει μονο το τελευταίο μισογεματο
ωστε να ελλατωσεις το overhead των πολλων προσβασεων στο δισκο απο πολλα "μισογεματα" blocks

σε prepared statment οχι σε απλο query
πχ

Κώδικας: Επιλογή όλων

$db = new PDO('mysql:host=your_hostname;dbname=your_db;charset=UTF-8', 'user', 'pass');
$db->exec("SET NAMES utf8");
$stmt = $db->prepare($sql);
while(....){
$stmt->bindParam(1, $string1, PDO::PARAM_STR);
$stmt->bindParam(2, $string2, PDO::PARAM_STR);
$stmt->bindParam(3, $string3, PDO::PARAM_STR);
$stmt->bindParam(4, $string4, PDO::PARAM_STR);
.....
.....
$stmt->bindParam(N, $stringN, PDO::PARAM_STR);
$stmt->execute();
}
πολλα αλλα μπορεις να κανεις αλλα κανε αυτα για αρχη

gvre
Δημοσιεύσεις: 992
Εγγραφή: 14 Οκτ 2010 11:34
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από gvre » 10 Ιούλ 2011 17:30

Κώδικας: Επιλογή όλων

<?php
function random_gen&#40;&#41;
&#123;
        static $characters = "0123456789abcdefghijklmnopqrstuvwxyz";

        return  $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;;
&#125;

$cn = mysqli_connect&#40;"localhost", "user", "pass"&#41;;
mysqli_autocommit&#40;$cn, FALSE&#41;;
for &#40;$i = 0; $i < 1000; ++$i&#41;
&#123;
        $query = "";
        for &#40;$j = 0; $j < 1000; ++$j&#41;
                $query .= "&#40;'" . random_gen&#40;&#41; . "'&#41;,";
        mysqli_query&#40;$cn, "INSERT into test.words &#40;id&#41; VALUES " . substr&#40;$query, 0, -1&#41;&#41;;
&#125;
mysqli_commit&#40;$cn&#41;;
Χρόνος: 10.268517971039"



Κώδικας: Επιλογή όλων

<?php
function random_gen&#40;&#41;
&#123;
        static $characters = "0123456789abcdefghijklmnopqrstuvwxyz";

        return  $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;
                . $characters&#91;mt_rand&#40;0, 35&#41;&#93;;
&#125;

$cn = new PDO&#40;"mysql&#58;host=localhost;dbname=test;charset=UTF-8", "user", "pass"&#41;;
$cn->beginTransaction&#40;&#41;;
$query = "INSERT into test.words &#40;id&#41; VALUES " . str_repeat&#40;"&#40;?&#41;,", 1000&#41;;
$query = substr&#40;$query, 0, -1&#41;;
$stmt  = $cn->prepare&#40;$query&#41;;
for &#40;$i = 0; $i < 1000; ++$i&#41;
&#123;
        for &#40;$j = 1; $j <= 1000; ++$j&#41;
                $stmt->bindParam&#40;$j, random_gen&#40;&#41;, PDO&#58;&#58;PARAM_STR&#41;;
        $stmt->execute&#40;&#41;;
&#125;
$cn->commit&#40;&#41;; 
Χρόνος: 10.208563089371

Με την αρχική συνάρτηση random_gen() ο χρόνος αυξάνεται περίπου 6" (από 10.2" στα 16.2").
Ο πίνακας είναι σε InnoDB χωρίς indexes και primary key.

Άβαταρ μέλους
Pavel
Honorary Member
Δημοσιεύσεις: 1046
Εγγραφή: 08 Αύγ 2003 00:05
Τοποθεσία: UK

Πιο γρήγορα στρινγκς!

Δημοσίευση από Pavel » 11 Ιούλ 2011 02:45

Το κομμάτι της php για 100.000 εγγραφές χρειάζεται 3 δευτερόλεπτα.
Με το αρχικό σου script για 100.000 εγγραφές χρειάστηκαν 17,093940019608 δευτερόλεπτα (όλα μαζί)

Δεν έκανα κανένα optimisation ως προς την function που παράγεις την λέξη επειδή τα 3 δευτερόλεπτα είναι λίγα ως προς τα τελικά 17.

Αλλάζοντας μόνο τον αριθμό των inserts ανά request (έβαλα 10) ο χρόνος έπεσε στα 3,8522708415985.

Κώδικας: Επιλογή όλων

$sql = 'INSERT INTO words &#40;id&#41; VALUES';
	for &#40;$i = 0; $i < 10000; $i++&#41; &#123;
		$q = '';
		$q .= '&#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;, &#40;"'. random_gen&#40;&#41; .'"&#41;';
		mysql_query&#40;$sql . $q, $link&#41;;
	&#125;
Εσύ είσαι τρελός.

gvre
Δημοσιεύσεις: 992
Εγγραφή: 14 Οκτ 2010 11:34
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από gvre » 11 Ιούλ 2011 10:35

Έκανα δοκιμές και με την αλλαγή που πρότεινες (με μόνη αλλαγή το $i < 10000 προκειμένου να έχω 1.000.000 εγγραφές) αλλά ο χρόνος κυμάνθηκε στα ίδια επίπεδα ( 10.713s ).
Το καλύτερο που έχει να κάνει ο OP είναι να παίξει λίγο με αυτό το loop στο δικό του μηχάνημα και να βρει την αποδοτικότερη λύση.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από cherouvim » 13 Ιούλ 2011 11:59

Το αν θα βάλεις index ή όχι στο πεδίο έχει να κάνει με το τι θα κάνεις αυτές τις τιμές αργότερα.

Δεν μας είπες, γιατί το κάνεις αυτό γενικότερα; Τι πρόβλημα λύνεις;

Άβαταρ μέλους
Christianago
Δημοσιεύσεις: 332
Εγγραφή: 12 Νοέμ 2009 13:36

Πιο γρήγορα στρινγκς!

Δημοσίευση από Christianago » 13 Ιούλ 2011 13:20

Αυτα τα δεδομενα που παραγω οταν καταφερω να τελειοποιησω το προγραμμα συμφωνα με τις ιδεες που προταθηκαν
θα αποθηκευτουν στον πινακα της ΒΔ και υστερα θα αποθηκευτουν σε ενα αρχειο txt για αναγνωση απο αυτο το αρχειο.
Θεωρησα η εισαγωγη στη βαση πρωτα και η τελικη εγγραφη των εγγραφων στο αρχειο μειωνει σημαντικα το χρονο.
Επομενως αν το κανω με αυτον τον τροπο οντως δε χρειαζομαι ευρετηριο.
Προς το παρον εχω προβλημα με τα transactions και με τις ετοιμες προτασεις.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από cherouvim » 13 Ιούλ 2011 13:39

Σύμφωνα με αυτά που λες δεν βλέπω κανένα λόγο να συμπεριλάβεις βάση μέσα στο όλο σύστημα.

pimpogio
Δημοσιεύσεις: 1080
Εγγραφή: 28 Δεκ 2010 14:08

Πιο γρήγορα στρινγκς!

Δημοσίευση από pimpogio » 13 Ιούλ 2011 13:40

οχι να το κανεις επιτοπου στο αρχειο και θα γραφεις
σε blocks πολλαπλασια με το μεγεθος του block του δισκου.
Με 1 MB block θα πηγαινει σφαιρα.

Φτιαξε 2 threads αν θες παραπανω ταχυτητα 1 να γραφει τα data και 1 να σου φτιαχει τα strings στο buffer

Άβαταρ μέλους
Christianago
Δημοσιεύσεις: 332
Εγγραφή: 12 Νοέμ 2009 13:36

Πιο γρήγορα στρινγκς!

Δημοσίευση από Christianago » 13 Ιούλ 2011 14:08

Ευχαριστω pimpogio μπορεις να μου δωσεις ενα παραδειγμα για να καταλαβω πως θα το κανω;

gvre
Δημοσιεύσεις: 992
Εγγραφή: 14 Οκτ 2010 11:34
Τοποθεσία: Ηράκλειο Κρήτης
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από gvre » 13 Ιούλ 2011 14:39

Κώδικας: Επιλογή όλων

$fp = @fopen&#40;"data.txt", "w"&#41;;
if &#40;$fp !== false&#41;
&#123;
        for &#40;$i = 0; $i < 1000; $i++&#41;
        &#123;
                $data = "";
                for &#40;$j = 0; $j < 1000; $j++&#41;
                        $data .= random_gen&#40;&#41; . "\n";
                fwrite&#40;$fp, $data&#41;;
        &#125;
        fclose&#40;$fp&#41;;
&#125;
Χρόνος εκτέλεσης: 2.7"
Αν θέλεις να γίνει πιο γρήγορο κάνε το σε C. Δε σου προτείνω να μπλέξεις με threads κλπ (η php δεν υποστηρίζει threads έτσι κι αλλιώς).
Αν θέλεις, κάνε μια μικρή περιγραφή σχετικά με αυτό που θέλεις να κάνεις. Ίσως έτσι προκύψουν κάποιες καλύτερες ιδέες.

pimpogio
Δημοσιεύσεις: 1080
Εγγραφή: 28 Δεκ 2010 14:08

Πιο γρήγορα στρινγκς!

Δημοσίευση από pimpogio » 13 Ιούλ 2011 15:52

Christianago έγραψε:Ευχαριστω pimpogio μπορεις να μου δωσεις ενα παραδειγμα για να καταλαβω πως θα το κανω;
ελα παρε με threads k συγχρονισμο

Κώδικας: Επιλογή όλων

// Filename&#58; FileWrite.java
// compile&#58; javac FileWrite.java
// run&#58; java FileWrite
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Random;

public class FileWrite &#123;

    private static final int BLOCKS = 10; // posa blocks tha grapseis

    public static void main&#40;String&#91;&#93; args&#41; throws IOException &#123;
        Buffer buf = new Buffer&#40;&#41;;

        Thread prod = new Thread&#40;new Producer&#40;BLOCKS, buf&#41;&#41;;
        Thread cons = new Thread&#40;new Consumer&#40;BLOCKS, buf, "Output.txt"&#41;&#41;;

        prod.start&#40;&#41;;
        cons.start&#40;&#41;;

        try &#123;
            prod.join&#40;&#41;;
            cons.join&#40;&#41;;
        &#125; catch &#40;InterruptedException e&#41; &#123;
            return;
        &#125;
    &#125;
&#125;

class Buffer &#123;

    private char&#91;&#93; contents;
    private boolean empty = true;

    public synchronized void put&#40;char&#91;&#93; buf&#41; throws InterruptedException &#123;
        while &#40;empty == false&#41; &#123;
            try &#123;
                wait&#40;&#41;;
            &#125; catch &#40;InterruptedException e&#41; &#123;
                throw e;
            &#125;
        &#125;
        contents = buf;
        empty = false;
        notify&#40;&#41;;
    &#125;

    public synchronized char&#91;&#93; get&#40;&#41; throws InterruptedException &#123;
        while &#40;empty == true&#41; &#123;
            try &#123;
                wait&#40;&#41;;
            &#125; catch &#40;InterruptedException e&#41; &#123;
                throw e;
            &#125;
        &#125;
        empty = true;
        notify&#40;&#41;;
        return contents;
    &#125;
&#125;

class Producer implements Runnable &#123;

    private final static char&#91;&#93; CHARS = &#123;'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
        'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'z', 'l',
        'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'm'&#125;;
    private final static int BSIZE = 1000 * 4096; // megethos block
    private final static int CHARS_PER_LINE = 64; // xaraktires ana grami
    private Random r;
    private int n;
    private Buffer prodBuf;
    private char&#91;&#93; block;

    public Producer&#40;int m, Buffer buf&#41; &#123;
        n = m;
        prodBuf = buf;
        r = new Random&#40;System.currentTimeMillis&#40;&#41;&#41;;
        block = new char&#91;BSIZE&#93;;
    &#125;

    @Override
    public void run&#40;&#41; &#123;
        for &#40;int i = 1; i <= n; i++&#41; &#123;
            for &#40;int j = 0; j < BSIZE; j++&#41; &#123;
                block&#91;j&#93; = CHARS&#91;r.nextInt&#40;CHARS.length&#41;&#93;;
                if &#40;j % CHARS_PER_LINE == 0 && j != 0&#41; &#123;
                    block&#91;j - 1&#93; = '\r';
                    block&#91;j&#93; = '\n';
                &#125;
            &#125;
            block&#91;BSIZE - 2&#93; = '\r';
            block&#91;BSIZE - 1&#93; = '\n';

            try &#123;

                prodBuf.put&#40;block&#41;;
            &#125; catch &#40;InterruptedException e&#41; &#123;
                return;
            &#125;

        &#125;
    &#125;
&#125;

class Consumer implements Runnable &#123;

    FileWriter fstream;
    BufferedWriter out;
    private int n;
    private Buffer consBuf;

    public Consumer&#40;int m, Buffer buf, String fname&#41; throws IOException &#123;
        n = m;
        consBuf = buf;
        fstream = new FileWriter&#40;fname&#41;;
        out = new BufferedWriter&#40;fstream&#41;;
    &#125;

    @Override
    public void run&#40;&#41; &#123;
        try &#123;
            for &#40;int i = 1; i <= n; i++&#41; &#123;
                out.write&#40;consBuf.get&#40;&#41;&#41;;
                System.out.println&#40;"Block&#58;" + i + " written.."&#41;;
            &#125;
            out.close&#40;&#41;;
        &#125; catch &#40;InterruptedException e&#41; &#123;
            return;
        &#125; catch &#40;IOException e&#41; &#123;
            return;
        &#125;

    &#125;
&#125;



Άβαταρ μέλους
cpulse
Script Master
Δημοσιεύσεις: 1527
Εγγραφή: 21 Μαρ 2006 19:30
Τοποθεσία: Αθήνα village
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από cpulse » 13 Ιούλ 2011 16:01

Είσαι Θεός!

Άβαταρ μέλους
cpulse
Script Master
Δημοσιεύσεις: 1527
Εγγραφή: 21 Μαρ 2006 19:30
Τοποθεσία: Αθήνα village
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από cpulse » 13 Ιούλ 2011 16:05

Christianago ο pimpogio είναι Θεός, αλλά σε άλλο χωροχρονικό συνεχές.
Οπότε θα σου πρότεινα να ακούσεις τις γνώμες όλων των υπόλοιπων.

Άβαταρ μέλους
cherouvim
Script Master
Δημοσιεύσεις: 3137
Εγγραφή: 13 Ιούλ 2005 22:56
Τοποθεσία: Athens, Greece
Επικοινωνία:

Πιο γρήγορα στρινγκς!

Δημοσίευση από cherouvim » 13 Ιούλ 2011 16:09

Ωραίος pimp. Πάντως ο producer μάλλον σίγουρα θα είναι πολύ πιο αργός από τον consumer οπότε ο 2ος την περισσότερη ώρα απλά θα περιμένει, σωστά;

Απάντηση

Επιστροφή στο “PHP Προγραμματισμός”

Μέλη σε σύνδεση

Μέλη σε αυτήν τη Δ. Συζήτηση: Δεν υπάρχουν εγγεγραμμένα μέλη και 0 επισκέπτες