ホームページ >バックエンド開発 >PHPチュートリアル >PHP の基盤となる高性能データ構造と実装方法

PHP の基盤となる高性能データ構造と実装方法

王林
王林オリジナル
2023-11-08 19:42:491135ブラウズ

PHP の基盤となる高性能データ構造と実装方法

PHP の基礎となる高パフォーマンスのデータ構造と実装方法には、特定のコード例が必要です

インターネット アプリケーションの継続的な開発に伴い、PHP はサーバーサイド スクリプティングとして広く使用されるようになりました。言語。しかし、大規模な Web アプリケーションでは PHP のパフォーマンスの問題が無視できない問題となっており、多くの大規模な Web サイトでパフォーマンスのボトルネックやシステムクラッシュが発生しています。

PHP のパフォーマンスを向上させるには、基礎となる高パフォーマンスのデータ構造と PHP の実装方法を理解する必要があります。この記事では、PHP のいくつかの高性能データ構造とその実装方法を紹介し、読者が PHP パフォーマンスの最適化を深く理解できるように、対応するコード例を示します。

  1. 配列

PHP では、配列は最も一般的に使用されるデータ構造の 1 つです。ただし、PHP の配列実装ではハッシュ テーブルが使用されるため、特に大量のデータを反復処理する場合にパフォーマンスのオーバーヘッドが生じます。

PHP の配列パフォーマンスを向上させるために、C 言語拡張機能を使用してそれを実現できます。

以下は、簡単な PHP 拡張機能の例です。これは、大量のデータの保存に使用できる高性能ハッシュ テーブルを実装し、さまざまなデータ型の保存とアクセスをサポートします。

typedef struct {
    zend_ulong h;
    zval data;
} hashtable_entry;

typedef struct {
    hashtable_entry *table;
    zend_ulong num_entries;
    zend_ulong max_entries;
    zend_ulong rehash_pos;
    zend_ulong rehash_size;
} hashtable;

typedef struct {
    zend_object std;
    hashtable *ht;
} hash_table_object;

static zend_object *hash_table_object_new(zend_class_entry *class_type)
{
    hash_table_object *intern = 
        (hash_table_object *)ecalloc(1, sizeof(hash_table_object));
    zend_object_std_init(&intern->std, class_type);
    object_properties_init(&intern->std, class_type);
    intern->std.handlers = &hash_table_object_handlers;
    intern->ht = 
        (hashtable *)emalloc(sizeof(hashtable));
    return &intern->std;
}

static void hash_table_object_free(zend_object *object)
{
    hash_table_object *intern = 
        hash_table_object_from_obj(object);
    if (intern->ht != NULL) {
        zend_ulong i;
        for (i = 0; i < intern->ht->max_entries; i++) {
            zval_dtor(
                &intern->ht->table[i].data
            );
        }
        efree(intern->ht->table);
        efree(intern->ht);
    }
    zend_object_std_dtor(object);
}

static void hash_table_put(hash_table_object *intern, 
                           zval *key, 
                           zval *value)
{
    zend_ulong idx;
    zend_string *str_key;
    if (Z_TYPE_P(key) == IS_STRING) {
        str_key = Z_STR_P(key);
        idx = zend_inline_hash_func(
            str_key->val, str_key->len
        ) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_LONG) {
        idx = Z_LVAL_P(key) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_DOUBLE) {
        idx = zend_dval_to_lval(Z_DVAL_P(key)) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_TRUE) {
        idx = 1 % intern->ht->max_entries;
    } else {
        idx = 0;
    }
    if (Z_TYPE(intern->ht->table[idx].data) != IS_NULL) {
        zval_dtor(
            &intern->ht->table[idx].data
        );
    }
    intern->ht->table[idx].h = idx;
    ZVAL_COPY_VALUE(
        &intern->ht->table[idx].data, value
    );
}

static zval *hash_table_get(hash_table_object *intern, 
                             zval *key)
{
    zend_ulong idx;
    zend_string *str_key;
    if (Z_TYPE_P(key) == IS_STRING) {
        str_key = Z_STR_P(key);
        idx = zend_inline_hash_func(
            str_key->val, str_key->len
        ) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_LONG) {
        idx = Z_LVAL_P(key) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_DOUBLE) {
        idx = zend_dval_to_lval(Z_DVAL_P(key)) % intern->ht->max_entries;
    } else if (Z_TYPE_P(key) == IS_TRUE) {
        idx = 1 % intern->ht->max_entries;
    } else {
        idx = 0;
    }
    if (Z_TYPE(intern->ht->table[idx].data) == IS_NULL) {
        return NULL;
    } else {
        return &intern->ht->table[idx].data;
    }
}

static zend_class_entry *hash_table_class_entry;

static zend_function_entry hash_table_methods[] = {
    PHP_ME(HashTable, put, arginfo_hashtable_put, ZEND_ACC_PUBLIC)
    PHP_ME(HashTable, get, arginfo_hashtable_get, ZEND_ACC_PUBLIC)
    PHP_FE_END
};

static zend_object_handlers hash_table_object_handlers;

static void hash_table_object_init(zend_class_entry *class_type)
{
    hash_table_object_handlers = 
        *zend_get_std_object_handlers();
    hash_table_object_handlers.offset = 
        XtOffsetOf(hash_table_object, std);
    hash_table_object_handlers.free_obj = 
        hash_table_object_free;
    hash_table_object_handlers.clone_obj = 
        zend_objects_clone_obj;
}

PHP_MINIT_FUNCTION(hash_table)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "HashTable", hash_table_methods);
    hash_table_class_entry = zend_register_internal_class(&ce);
    hash_table_class_entry->create_object =
        hash_table_object_new;
    hash_table_object_init(
        hash_table_class_entry
    );
    return SUCCESS;
}

上記の拡張機能を使用すると、PHP 配列のパフォーマンスが大幅に向上し、特に大規模なデータの処理に適しています。

  1. ヒープ

ヒープは、優先キュー、並べ替え、その他の操作に使用できる一般的に使用されるデータ構造です。 PHP のパフォーマンスを向上させるために、C 言語拡張機能を使用してヒープ データ構造を実装できます。

次は、最小限のヒープを実装し、並べ替えや検索などの操作に使用できる簡単な PHP 拡張機能の例です。

typedef struct {
    zend_ulong size;
    zend_ulong capacity;
    zval *data;
} min_heap;

static min_heap *min_heap_new()
{
    min_heap *heap = emalloc(sizeof(min_heap));
    heap->size = 0;
    heap->capacity = 4;
    heap->data = emalloc(sizeof(zval) * heap->capacity);
    return heap;
}

static void min_heap_free(min_heap *heap)
{
    zend_ulong i;
    for (i = 0; i < heap->size; i++) {
        zval_dtor(&heap->data[i]);
    }
    efree(heap->data);
    efree(heap);
}

static void min_heap_push(min_heap *heap, zval *value)
{
    if (heap->size + 1 > heap->capacity) {
        heap->capacity *= 2;
        heap->data = 
            erealloc(heap->data, sizeof(zval) * heap->capacity);
    }
    zend_ulong hole = ++heap->size;
    while (hole > 1 && 
           zend_is_smaller(
               value, &heap->data[hole / 2]
           )) {
        ZVAL_COPY(
            &heap->data[hole], &heap->data[hole / 2]
        );
        hole /= 2;
    }
    ZVAL_COPY(
        &heap->data[hole], value
    );
}

static void min_heap_pop(min_heap *heap)
{
    zend_ulong hole = 1;
    zend_ulong child = 2;
    zval tmp;
    ZVAL_NULL(&tmp);
    zval_dtor(
        &heap->data[1]
    );
    heap->data[1] = heap->data[heap->size--];
    while (child <= heap->size) {
        if (child < heap->size && 
            zend_is_smaller(&heap->data[child + 1], &heap->data[child])) {
            child++;
        }
        if (zend_is_smaller(&heap->data[child], &heap->data[hole])) {
            ZVAL_COPY(
                &tmp, &heap->data[hole]
            );
            ZVAL_COPY(
                &heap->data[hole], &heap->data[child]
            );
            ZVAL_COPY(
                &heap->data[child], &tmp
            );
        } else {
            break;
        }
        hole = child;
        child *= 2;
    }
}

static zval *min_heap_top(min_heap *heap)
{
    if (heap->size > 0) {
        return &heap->data[1];
    } else {
        return NULL;
    }
}

static zend_class_entry *min_heap_class_entry;

static zend_function_entry min_heap_methods[] = {
    PHP_ME(MinHeap, push, arginfo_min_heap_push, ZEND_ACC_PUBLIC)
    PHP_ME(MinHeap, pop, arginfo_min_heap_pop, ZEND_ACC_PUBLIC)
    PHP_ME(MinHeap, top, arginfo_min_heap_top, ZEND_ACC_PUBLIC)
    PHP_FE_END
};

static zend_object_handlers min_heap_object_handlers;

static void min_heap_object_init(zend_class_entry *class_type)
{
    min_heap_object_handlers = 
        *zend_get_std_object_handlers();
    min_heap_object_handlers.offset = 
        XtOffsetOf(min_heap_object, std);
    min_heap_object_handlers.free_obj = 
        min_heap_object_free;
    min_heap_object_handlers.clone_obj = 
        zend_objects_clone_obj;
}

static zend_object *min_heap_object_new(zend_class_entry *class_type)
{
    min_heap_object *intern = 
        (min_heap_object *)ecalloc(1, sizeof(min_heap_object));
    zend_object_std_init(&intern->std, class_type);
    object_properties_init(&intern->std, class_type);
    intern->std.handlers = &min_heap_object_handlers;
    intern->heap = 
        min_heap_new();
    return &intern->std;
}

static void min_heap_object_free(zend_object *object)
{
    min_heap_object *intern = 
        min_heap_object_from_obj(object);
    if (intern->heap != NULL) {
        min_heap_free(intern->heap);
    }
    zend_object_std_dtor(object);
}

PHP_MINIT_FUNCTION(min_heap)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "MinHeap", min_heap_methods);
    min_heap_class_entry = zend_register_internal_class(&ce);
    min_heap_class_entry->create_object =
        min_heap_object_new;
    min_heap_object_init(
        min_heap_class_entry
    );
    return SUCCESS;
}

上記の拡張機能を使用すると、PHP でヒープ データ構造を簡単に実装し、PHP の並べ替え、検索、その他の操作のパフォーマンスを向上させることができます。

  1. キュー

PHP のキューは、マルチスレッド タスクの管理などのアプリケーション シナリオで使用できる一般的なデータ構造です。 PHP のパフォーマンスを向上させるために、C 言語拡張機能を使用してキュー データ構造を実装できます。

次に、簡単な PHP 拡張機能の例を示します。これは、高パフォーマンスのキューを実装し、マルチスレッド タスク処理などのアプリケーション シナリオで使用できます。

typedef struct {
    zend_ulong head;
    zend_ulong tail;
    zend_ulong size;
    zend_ulong capacity;
    zval *data;
} queue;

static queue *queue_new()
{
    queue *q = emalloc(sizeof(queue));
    q->head = 0;
    q->tail = 0;
    q->size = 0;
    q->capacity = 4;
    q->data = emalloc(sizeof(zval) * q->capacity);
    return q;
}

static void queue_free(queue *q)
{
    zend_ulong i;
    for (i = q->head; i != q->tail; i = (i + 1) % q->capacity) {
        zval_dtor(&q->data[i]);
    }
    efree(q->data);
    efree(q);
}

static void queue_push(queue *q, zval *val)
{
    if (q->size >= q->capacity) {
        zend_ulong new_capacity = q->capacity * 2;
        zval *new_data = emalloc(sizeof(zval) * new_capacity);
        zend_ulong i;
        for (i = q->head; i != q->tail; i = (i + 1) % q->capacity) {
            ZVAL_COPY(&new_data[i], &q->data[i]);
        }
        efree(q->data);
        q->data = new_data;
        q->capacity = new_capacity;
        q->head = 0;
        q->tail = q->size;
    }
    ZVAL_COPY(&q->data[q->tail], val);
    q->tail = (q->tail + 1) % q->capacity;
    q->size++;
}

static void queue_pop(queue *q)
{
    if (q->size > 0) {
        zval_dtor(&q->data[q->head]);
        q->head = (q->head + 1) % q->capacity;
        q->size--;
    }
}

static zval *queue_front(queue *q)
{
    if (q->size > 0) {
        return &q->data[q->head];
    } else {
        return NULL;
    }
}

static zend_class_entry *queue_class_entry;

static zend_function_entry queue_methods[] = {
    PHP_ME(Queue, push, arginfo_queue_push, ZEND_ACC_PUBLIC)
    PHP_ME(Queue, pop, arginfo_queue_pop, ZEND_ACC_PUBLIC)
    PHP_ME(Queue, front, arginfo_queue_front, ZEND_ACC_PUBLIC)
    PHP_FE_END
};

static zend_object_handlers queue_object_handlers;

static void queue_object_init(zend_class_entry *class_type)
{
    queue_object_handlers = 
        *zend_get_std_object_handlers();
    queue_object_handlers.offset = 
        XtOffsetOf(queue_object, std);
    queue_object_handlers.free_obj = 
        queue_object_free;
    queue_object_handlers.clone_obj = 
        zend_objects_clone_obj;
}

static zend_object *queue_object_new(zend_class_entry *class_type)
{
    queue_object *intern = 
        (queue_object *)ecalloc(1, sizeof(queue_object));
    zend_object_std_init(&intern->std, class_type);
    object_properties_init(&intern->std, class_type);
    intern->std.handlers = &queue_object_handlers;
    intern->q = 
        queue_new();
    return &intern->std;
}

static void queue_object_free(zend_object *object)
{
    queue_object *intern = 
        queue_object_from_obj(object);
    if (intern->q != NULL) {
        queue_free(intern->q);
    }
    zend_object_std_dtor(object);
}

PHP_MINIT_FUNCTION(queue)
{
    zend_class_entry ce;
    INIT_CLASS_ENTRY(ce, "Queue", queue_methods);
    queue_class_entry = zend_register_internal_class(&ce);
    queue_class_entry->create_object =
        queue_object_new;
    queue_object_init(
        queue_class_entry
    );
    return SUCCESS;
}

上記の拡張機能を使用すると、PHP でキュー データ構造を簡単に実装し、PHP マルチスレッド タスク処理やその他のアプリケーション シナリオのパフォーマンスを向上させることができます。

概要

上記の紹介の後、PHP の基礎となる高性能データ構造とその実装方法について学び、対応するコード例を提供しました。拡張機能を使用して高パフォーマンスのデータ構造を実装すると、特に大量のデータやマルチスレッド タスクを処理する場合に、PHP のパフォーマンスが大幅に向上し、システムのパフォーマンスが大幅に向上します。

以上がPHP の基盤となる高性能データ構造と実装方法の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。