sql >> データベース >  >> RDS >> Mysql

PHP / MySQLアプリケーションでマルチコアCPUをどのように活用しますか?

    はじめに

    PHPには完全なマルチスレッド があります さまざまな方法で最大限に活用できるサポート。さまざまな例でこのマルチスレッド機能を実証することができました:

    クイック検索 追加のリソースを提供します。

    カテゴリ

    1:MySQLクエリ

    MySQLは完全にマルチスレッド また、オペレーティングシステムが複数のCPUをサポートしている場合は、複数のCPUを使用します。また、パフォーマンスを適切に構成すると、システムリソースが最大化されます。

    my.iniの一般的な設定 スレッドのパフォーマンスに影響を与えるのは:

    thread_cache_size = 8
    

    thread_cache_size 新しい接続がたくさんある場合は、パフォーマンスを向上させるために増やすことができます。通常、適切なスレッド実装がある場合、これによってパフォーマンスが大幅に向上することはありません。ただし、サーバーが1秒間に数百の接続を検出する場合は、通常、ほとんどの新しい接続がキャッシュされたスレッドを使用するように、thread_cache_sizeを十分に高く設定する必要があります

    Solaris を使用している場合 その後、

    を使用できます
    thread_concurrency = 8 
    

    thread_concurrency アプリケーションがスレッドシステムに、同時に実行する必要のあるスレッドの希望数に関するヒントを提供できるようにします。

    この変数はMySQL5.6.1で非推奨になり、MySQL5.7で削除されました。 Solaris 8以前の場合を除いて、MySQL構成ファイルを表示するたびにこれを削除する必要があります。

    InnoDB:

    を使用している場合、このような制限はありません。 Innodb スレッドの同時実行性を完全にサポートしているため、ストレージエンジンがあります

    innodb_thread_concurrency //  Recommended 2 * CPUs + number of disks
    

    innodb_read_io_threadsもご覧ください。 およびinnodb_write_io_threads デフォルトは4です。 64まで増やすことができます ハードウェアによって異なります

    その他:

    他にも確認すべき構成には、key_buffer_sizeがあります。 、table_open_cachesort_buffer_size など、すべてがパフォーマンスの向上につながります

    PHP:

    純粋なPHPでは、各クエリが別々のPHPスレッドで実行されるMySQLワーカーを作成できます

    $sql = new SQLWorker($host, $user, $pass, $db);
    $sql->start();
    
    $sql->stack($q1 = new SQLQuery("One long Query")); 
    $sql->stack($q2 = new SQLQuery("Another long Query"));
    
    $q1->wait(); 
    $q2->wait(); 
    
    // Do Something Useful
    

    これは、SQLWorkerの完全な実例です

    2:HTMLコンテンツの解析

    すでに問題を知っている場合は、イベントループ、ジョブキュー、またはスレッドを使用して簡単に解決できます。

    一度に1つのドキュメントで作業することは、非常に可能です。 遅くて痛みを伴うプロセス。 @ka ajaxを使用して複数のリクエストを呼び出す方法をハッキングすると、一部のクリエイティブマインドは pcntl_fork ただし、windowsを使用している場合 そうすると、pcntlを利用できなくなります

    pThreadsを使用 WindowsとUnixシステムの両方をサポートしているので、そのような制限はありません。と同じくらい簡単です..100ドキュメントを解析する必要がある場合は? 100スレッドを生成...シンプル

    HTMLスキャン

    // Scan my System
    $dir = new RecursiveDirectoryIterator($dir, RecursiveDirectoryIterator::SKIP_DOTS);
    $dir = new RecursiveIteratorIterator($dir);
    
    // Allowed Extension
    $ext = array(
            "html",
            "htm"
    );
    
    // Threads Array
    $ts = array();
    
    // Simple Storage
    $s = new Sink();
    
    // Start Timer
    $time = microtime(true);
    
    $count = 0;
    // Parse All HTML
    foreach($dir as $html) {
        if ($html->isFile() && in_array($html->getExtension(), $ext)) {
            $count ++;
            $ts[] = new LinkParser("$html", $s);
        }
    }
    
    // Wait for all Threads to finish
    foreach($ts as $t) {
        $t->join();
    }
    
    // Put The Output
    printf("Total Files:\t\t%s \n", number_format($count, 0));
    printf("Total Links:\t\t%s \n", number_format($t = count($s), 0));
    printf("Finished:\t\t%0.4f sec \n", $tm = microtime(true) - $time);
    printf("AvgSpeed:\t\t%0.4f sec per file\n", $tm / $t);
    printf("File P/S:\t\t%d file per sec\n", $count / $tm);
    printf("Link P/S:\t\t%d links per sec\n", $t / $tm);
    

    出力

    Total Files:            8,714
    Total Links:            105,109
    Finished:               108.3460 sec
    AvgSpeed:               0.0010 sec per file
    File P/S:               80 file per sec
    Link P/S:               907 links per sec
    

    使用クラス

    Sink

    class Sink extends Stackable {
        public function run() {
        }
    }
    

    LinkParser

    class LinkParser extends Thread {
    
        public function __construct($file, $sink) {
            $this->file = $file;
            $this->sink = $sink;
            $this->start();
        }
    
        public function run() {
            $dom = new DOMDocument();
            @$dom->loadHTML(file_get_contents($this->file));
            foreach($dom->getElementsByTagName('a') as $links) {
                $this->sink[] = $links->getAttribute('href');
            }
        }
    }
    

    実験

    8,714の解析を試みています 105,109を持つファイル スレッドのないリンクを作成し、所要時間を確認してください。

    より良いアーキテクチャ

    あまりにも多くのスレッドを生成しますが、これは本番環境では賢明なことではありません。より良いアプローチは、プーリング を使用することです。 。 ワーカー を定義するプールを用意します 次に、スタック Taskを使用

    パフォーマンスの向上

    いいでしょう、上記の例はまだ改善できます。システムが単一のスレッドですべてのファイルをスキャンするのを待つ代わりに、複数のスレッドを使用してシステムでファイルをスキャンし、データをワーカーにスタックして処理することができます

    3:検索インデックスの更新

    これは最初の回答でほぼ回答されていますが、パフォーマンスを向上させる方法はたくさんあります。イベントベースのアプローチを検討したことがありますか?

    イベントの紹介

    @rdlowrey 引用1:

    @rdlowrey 引用2:

    event-drivenを試してみませんか 、non-blocking I/O あなたの問題へのアプローチ。 PHPにはlibevent があります アプリケーションを過充電します。

    私はこの質問がすべてMulti-Threadingであることを知っています ただし、時間があれば、このPHPで記述されたNuclearReactor を見ることができます。 @igorw

    最後に

    考慮事項

    Cacheの使用を検討する必要があると思います およびJob Queue あなたの仕事のいくつかのために。簡単にメッセージを送ることができます

    Document uploaded for processing ..... 5% - Done   
    

    次に、バックグラウンドですべての時間を無駄にするタスクを実行します。 大規模な処理ジョブを小さくするをご覧ください 同様のケーススタディについて。

    プロファイリング

    プロファイリングツール? Xdebug のWebアプリケーション用の単一のプロファイルツールはありません。 Yslow へ すべて非常に便利です。例えば。 Xdebugはサポートされていないため、スレッドに関しては役に立ちません

    お気に入りはありません



    1. MySQLのテキストフィールドから2桁の連続した数字を抽出するにはどうすればよいですか?

    2. 簡単なレビューと5つ星の評価システムを構築するにはどうすればよいですか?

    3. SQLServerの「IDENTITYをデータ型に変換する算術オーバーフローエラー…」を修正しました

    4. 例外'yii2での移行中にドライバーが見つかりませんでした'