2011-03-17 6 views

Odpowiedz

2

PHP definiowalne stałe, ale to naprawdę nie jest bardzo przydatne w tym kontekście.

Więc nie. Użyj ciągów jako kluczy.

+0

Jako że była to przyjęta odpowiedź, chciałbym wyjaśnić, że zdefiniowane przez PHP lub stałe nie są równoważne symbolom Ruby w bardzo wielu aspektach, z wyjątkiem tych, które muszą być wyrażeniami stałymi. – Matthew

1

PHP nie ma nic podobnego do symboli, a nawet stałe działają w PHP znacznie inaczej niż w ruby. Klucze tablicowe muszą być ciągami lub numerycznymi. Możesz przypisać ciąg lub liczbę do stałej, a następnie "użyć" stałej jako klucza tablicy. Ale stałe w PHP są statyczne, więc może to nie być to, czego potrzebujesz, wymaga więcej "podstawowego kodu", a rzeczywisty klucz tablicy nadal będzie albo ciągiem lub liczbą (w oparciu o wartość stałej).

2

Jeśli twoim problemem jest przeciążenie używania łańcuchów jako kluczy tablicowych i fakt, że tablica jest kopiowana zamiast przekazywana jako referencja za każdym razem, mogę zasugerować, aby użyć stdClass, czyli w zasadzie klasy obiektu, która może być modyfikowana dynamicznie, jak w tablicy, ale zachowuje się jak obiekt.

1

Nie, PHP nie ma czegoś takiego. Największym przybliżeniem w PHP byłoby użycie pojedynczych cudzysłowów dla twoich kluczy hashowych - tylko po to, aby upewnić się, że nie ma w nich "interpolacji".

kilka przykładów:

  • $arr[key] - to będzie działać jak $arr['key'] w większości przypadków, ale ma kilka wad: a) jeżeli jest rzeczywiście zdefiniowanej stałej (np define('key', 'rubbish') - będziesz dostępu . $arr['rubish'] Tak, to jest po prostu niebezpieczne b) spowodowałoby to wiadomości „Zawiadomienie” PHP (chyba że powiadomienia są tłumione)

  • $arr[@key]. - podobnie jak wcześniej, ale bez powiadomienia. W rzeczywistości tłumienie błędów jest bardzo złe pod względem łatwości konserwacji.

  • $arr["key"] - absolutnie prawidłowy sposób, chyba że masz jakieś specjalne symbole wewnątrz podwójnie cytowanego ciągu. Na przykład: "ab\ntc" != 'ab\ntc', "ab$c" != 'ab$c' i tak dalej. Uważam jednak, że jest to trochę paranoiczne, jeśli chodzi o takie przypadki.

  • $arr['key'] - jest to, moim zdaniem, najbliższy Ruby z arr[:key], jak można uzyskać w PHP.

0

Możesz używać prostych obiektów, aby uzyskać podobny efekt, jak symbole w rubinach. Niektóre funkcje bazy danych mają opcję FETCH_OBJECT, aby emulować ten efekt.

class StoreMe { 
    public $A; 
    public $B; 
    public $C; 
    public $D; 
} 

Główną zaletą symboli jest użycie klawiszy skrótów do optymalizacji wydajności i wykorzystania pamięci. Ponieważ PHP używa "Kopiuj przy zapisie" do przechowywania zmiennych, łańcuchy mogą być równoważne jak symbole w ruby. Ale PHP używa pewnego rodzaju tabeli translacji, aby uzyskać indeks tablicy z klucza hash.Więc każda mała tablica ma pewien narzut.

Testscript

pisałem ten mały skrypt, aby przetestować zużycie pamięci z PHP.

error_log("Start: " . memory_get_usage()); 
$iterations = 10000; 

$hash = []; 
for ($i=0; $i<$iterations; $i++) { 
    $hash[] = [ 
     "A" => "Test", 
     "B" => "Test", 
     "C" => "Test", 
     "D" => "Test", 
    ]; 
} 
error_log("String: " . memory_get_usage());  
$hash = null; 
error_log("Reset: " . memory_get_usage()); 

$hash = []; 
for ($i=0; $i<$iterations; $i++) { 
    $hash[] = [ 
     "Test", 
     "Test", 
     "Test", 
     "Test", 
    ]; 
} 
error_log("Raw: " . memory_get_usage()); 
$hash = null; 
error_log("Reset: " . memory_get_usage()); 

$hash = []; 
$copy = [ 
     "Test", 
     "Test", 
     "Test", 
     "Test", 
    ]; 
for ($i=0; $i<$iterations; $i++) { 
    $hash[] = $copy; 
} 
error_log("Copy: " . memory_get_usage()); 
$hash = null; 
error_log("Reset: " . memory_get_usage()); 

$hash = []; 
for ($i=0; $i<$iterations; $i++) { 
    $store = new StoreMe(); 
    $store->A = "Test"; 
    $store->B = "Test"; 
    $store->C = "Test"; 
    $store->D = "Test"; 
    $hash[] = $store; 
} 
error_log("Object: " . memory_get_usage()); 
$hash = null; 
$store = null; 
error_log("Reset: " . memory_get_usage()); 

Oto wyniki z oficjalnymi obrazami Docker dla PHP. Właściwą wartością jest zużycie pamięci w bajtach.

PHP 5,6

Start: 225680 
String: 8837400 
Reset: 226088 
Raw: 8837400 
Reset: 226088 
Object: 5580488 
Reset: 1209264 

PHP 7,0

Start: 355400 
String: 4643840 
Reset: 355400 
Raw: 4643840 
Reset: 355400 
Copy: 884216 
Reset: 355776 
Object: 2127096 
Reset: 478656 

PHP 7,1

Start: 355336 
String: 883776 
Reset: 355336 
Raw: 883776 
Reset: 355336 
Copy: 883776 
Reset: 355336 
Object: 2126656 
Reset: 478216 

Podsumowanie

Obiekty wymagają mniej pamięci, niż oczekiwano. Ale wydaje się, że PHP 5.6 ma problemy z usuwaniem śmieci przy użyciu obiektów. Wyniki PHP 7.1 wydają się być optymalizacją kompilatora, ponieważ nie ma różnicy w "Kopii przy zapisie" i tworzeniu tablic.