Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [PHP]Baaardzo dziwny problem, VertrigoServ
Forum PHP.pl > Forum > Przedszkole
robert-s
Jak to jest w ogóle możliwe? co_jest.gif Kod pochodzi z tego miejsca: http://www.progresowi.pl/2011/10/26/robimy-mieszarke.html Jest to mieszarka synonimów.

  1. <?php
  2. class SEOMixer
  3. {
  4. public $input;
  5. public $output;
  6. public $limit = 1;
  7. private $braces = array("{", "}");
  8. private $delimiter = "|";
  9. function __construct($input)
  10. {
  11. $this->input = $input;
  12. }
  13. function mixAll()
  14. {
  15. $this->output = $this->input;
  16. while (strpos($this->output, $this->braces['1']) !== false)
  17. {
  18. $closed = strpos($this->output, $this->braces['1']);
  19. $substr = substr($this->output, 0, $closed + 1);
  20. $from = strrpos($substr, $this->braces['0']);
  21. $substr = substr($substr, $from);
  22. $_substr = $this->mixText($substr);
  23. $this->output = str_replace($substr, $_substr, $this->output);
  24. $substr = "";
  25. $_substr = "";
  26. }
  27. return;
  28. }
  29. function mixText($text)
  30. {
  31. $text = str_ireplace($this->braces, "", $text);
  32. $elements = explode($this->delimiter, $text);
  33. return $elements[array_rand($elements)];
  34. }
  35. function mix()
  36. {
  37. $this->mixAll();
  38. return $this->output;
  39. }
  40. }
  41. //tylko to dopisałem ja
  42. $tekst_do_mieszania = '{jakieś|{synonimy|zagnieżdżone}}';
  43. $mieszarka = new SEOMixer($tekst_do_mieszania);
  44. $text_wymieszany = $mieszarka->mix();
  45. echo $text_wymieszany;
  46. ?>


Problem dotyczy bardzo długich tekstów z zagnieżdzonymi synonimami, przy krótkich wydaje się że jest ok. Mój ma 86188 znaków, jest w nim 100 zdań i losuje się jedno z nich. Dodatkowo każdy wyraz ma synonimy. Po wysłaniu na serwer wszystko działa jak trzeba. Natomiast gdy odpalam to na domowym komputerze (zainstalowany VertrigoServ) źle miesza. W kółko wyskakuje około 5 dokładnie takich samych zdań. Najlepsze jest to, że zawsze pojawiają się w tej samej kolejności! Jakim cudem tak się dzieje? co_jest.gif Czy może powstawać jakiś bład wynikły z konfiguracji VertrigoServ? W zasadzie to nic w ustawieniach nie zmieniałem.
zielu001
Ja bym pierwsze sprawdził wersje PHP ;p Najlepiej zainstalować najnowsze. Możliwe że w tej wersji która jest w VertrigoServ jest za stara i któraś z funkcji ma trochę inne działanie..
robert-s
Najnowsza była. Zresztą teraz zmieniłem na WAMPSERVER i to samo. Musi być jakieś racjonalne wyjaśnienie... Na hostingu losuje jak trzeba. U mnie na localhost zachowuje się jakby zapamiętał kilka wyników i wyświetlał kolejno co_jest.gif Intrygujące... I dzieje się tak tylko przy dużej ilości tekstu.
IProSoft
Nie zagłębiałem się w kod ale to, że pojawiają się w tej samej kolejności prawdopodobnie wynika z wersji PHP bo chyba od 5+ array_rand nie miesza zwracanej tablicy, dodaj po:
  1. $elements = explode($this->delimiter, $text);

  1. shuffle($elements);

i sprawdź czy zmieni się cokolwiek.
robert-s
Częściowo pomogło tzn. z tych 100 zdań losują się już wszystkie. Jednak dla danego zdania zawsze losowane są te same synonimy. I nie ma reguły, że jest brany zawsze np. pierwszy wyraz z {wyraz 1|wyraz|2wyraz 3}, ale przy drugim, trzecim itd wylosowaniu danego zdania zawsze wygląda ono tak samo. Znowu problem z zagnieżdżeniami występuje tylko przy dużej ilości tekstu. Przy 5 zdaniach jest ok. Sprawdzane tylko lokalnie, na serwerze już nie mogę bo domownicy się burzą, że nie mogą spać smile.gif Trzeba będzie stawić czoło problemowi dopiero rano.
Niktoś
Spróbuj w funckcji mixText za liniką:
$elements = explode($this->delimiter, $text);

dodać SLEEP(10);
mianowicie:
  1. $elements = explode($this->delimiter, $text);
  2. sleep(10);
  3. return $elements[array_rand($elements)];

Poza tym masz literówke:
str_ireplace-co to za polecenie?
phpion
@Niktoś:
str_ireplace

@robert-s:
Spróbuj użyć tego (konieczne PHP 5.3):
  1. class text {
  2. public static function shuffle($text) {
  3. $text = (string)$text;
  4.  
  5. while(strstr($text, '{')) {
  6. $text = preg_replace_callback('/{([^\{\}]*?)}/', function($text) {
  7. $text = explode('|', $text[1]);
  8.  
  9. return $text[array_rand($text)];
  10. }, $text, TRUE);
  11. }
  12.  
  13. return $text;
  14. }
  15. }
  16.  
  17. echo text::shuffle('siema {pion|phpion|{Michał|Michałku}} {jak sie masz|co u ciebie}?');
robert-s
SLEEP odpada, bo skrypt wykonuje się niemiłosiernie długo przy długich zdaniach. Zawsze Timeout, więc nawet nie mogę porównać.

W nawiązaniu do wersji bez żadnych modyfikacji. Hosting z wersją PHP 5.3.1326. Działa dobrze. Hosting z wersją PHP 5.2.17 również. WAMPSERVER PHP 5.3.13 w kółko w wyniku daje dokładnie 9 tych samych zdań.

Dodanie shuffle($elements); u mnie na localhost poprawia nieco losowość, ale i tak jest bardzo słaba. Dochodzi trochę zdań, ale na pewno nie losują się z całej puli. Z synonimów zagnieżdżonych prawie zawsze losuje się to samo. To jest przykładowy plik zawierających dwieście wygenerowanych linijek i posortowanych według długości. Proszę się nie przestraszyć, bo to jest bełkot, niemniej pokazuje problem:

https://dl.dropbox.com/u/46580461/zlemieszanie.txt

Dla porównania plik wygenerowany tym samym kodem, na hostingu z PHP 5.3.1326

https://dl.dropbox.com/u/46580461/dobremieszanie.txt

I na szybko zrobiony pliczek, który generuje te 200 linijek razem z tekstem źródłowym:

https://dl.dropbox.com/u/46580461/mieszacz.php

W zasadzie powinienem się cieszyć, że kod dobrze działa w miejscu docelowym, ale... Sytuacja jest dla mnie niezrozumiała puke.gif i ciężko mi się jest z tym pogodzić, ponieważ jestem człowiekiem dociekliwym. Zauważyłem jeszcze, ze u mnie kod wykonuje się o wiele dłużej niż po wgraniu na hosting. Teraz pobawię się kodem dostarczonym przez phpion'a. Zagadka tak czy inaczej zostaje.
Niktoś
Może zrób sobie experyment. Na localchoście póść np 30-40 razy w pętli losowanie dużej liczby i wyświetl to.Zrób to samo dla rand(),srand() i mt_rand(). Zobaczysz efekty i różnice.
Coś takiego:
  1. for($i=0;$i<10;$i++){
  2. $dane=rand(0,1000000000);
  3. echo $dane;
  4. }


Potem przed $dane spróbuj dodać polecenie sleep().
robert-s
Nie widzę jakiś różnic. We wszystkich przypadkach liczby są dobrze losowane, bez takich powtórzeń. Przy sleep też.

Kod phpion'a daje taki sam efekt jak w załączonych wyżej plikach. Pewnie wina leży w konfiguracji i złym działaniu array_rand, tylko gdzie dokładnie? Znamienne jest to, że błąd objawia się przy dużym obciążeniu (długi tekst z synonimami zagnieżdżonymi). Można w jakiś elegancki i wydajny sposób zastąpić array_rand?

Edit: Problem rozwiązany przez napisanie zupełnie innego kodu bez array_rand. Niemniej jakby ktoś znał prawdopodobną przyczynę takiego stanu rzeczy, niech da znać.
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.