Czy wiesz, czy używanie podwójnych cudzysłowów zamiast pojedynczych cudzysłowów w Rubim zmniejsza wydajność w znaczący sposób w Rubim 1.8 i 1.9?
więc jeśli napiszę
question = 'my question'
czy to jest szybsze niż
question = "my question"
Wyobrażam sobie, że ruby próbuje dowiedzieć się, czy coś wymaga oceny, kiedy napotyka podwójne cudzysłowy i prawdopodobnie spędza kilka cykli, robiąc to.
ruby
performance
syntax
dimus
źródło
źródło
Odpowiedzi:
Uwaga: zaktualizowałem to, aby działało z nowszymi wersjami Rubiego, wyczyściłem nagłówek i uruchomiłem test porównawczy na szybszym systemie.
Ta odpowiedź pomija kilka kluczowych punktów. Zobacz zwłaszcza te inne odpowiedzi dotyczące interpolacji i powodu, dla którego nie ma znaczącej różnicy w wydajności przy użyciu apostrofów i cudzysłowów.
źródło
'
i,"
ponieważ są one analizowane do tego samego.Podsumowanie: brak różnicy prędkości; ten wspaniały, oparty na współpracy przewodnik po stylu Ruby zaleca zachowanie spójności. Teraz używam
'string'
chyba, że potrzebna jest interpolacja (opcja A w przewodniku) i podoba mi się, ale zwykle zobaczysz więcej kodu z"string"
.Detale:
Teoretycznie może to mieć znaczenie, gdy twój kod jest parsowany , ale nie tylko jeśli nie obchodzi cię ogólnie czas parsowania (pomijalny w porównaniu z czasem wykonania), nie będziesz w stanie znaleźć znaczącej różnicy w tym przypadku.
Ważne jest to, że kiedy zostanie wykonany , będzie dokładnie taki sam .
Benchmarking pokazuje tylko brak zrozumienia, jak działa Ruby. W obu przypadkach ciągi zostaną przeanalizowane do a
tSTRING_CONTENT
(zobacz źródło wparse.y
). Innymi słowy, procesor wykonuje dokładnie te same operacje podczas tworzenia'string'
lub"string"
. Te same bity będą odwracane dokładnie w ten sam sposób. Benchmarking pokaże tylko różnice, które nie są znaczące i spowodowane innymi czynnikami (włącza się GC itp.); pamiętaj, w tym przypadku nie może być żadnej różnicy! Takie mikro testy porównawcze są trudne do wykonania. Zobacz mój klejnotfruity
za przyzwoite narzędzie do tego.Zwróć uwagę, że jeśli występuje interpolacja formularza
"...#{...}..."
, zostanie ona przetworzona do atSTRING_DBEG
, kilkutSTRING_DVAR
dla każdego wyrażenia in#{...}
i finałutSTRING_DEND
. Dzieje się tak tylko wtedy, gdy występuje interpolacja, a nie o to chodzi w PO.Kiedyś sugerowałem, abyś wszędzie używał podwójnych cudzysłowów (ułatwia to
#{some_var}
późniejsze dodanie ), ale teraz używam pojedynczych cudzysłowów, chyba że potrzebuję interpolacji\n
, itp ... Podoba mi się wizualnie i jest nieco bardziej wyraźny, ponieważ nie ma trzeba przeanalizować ciąg, aby sprawdzić, czy zawiera jakieś wyrażenie.źródło
#{n}
że będzie wykonywał konwersję liczb). Czy to nie pokazuje różnic w analizowaniu?Nikt jednak nie zmierzył konkatenacji w porównaniu z interpolacją:
W szczególności należy pamiętać
assign interp = 2.62
vsconcat single = 3.76
. Wisienką na torcie jest też interpolacja, która jest bardziej czytelna niż'a' + var + 'b'
zwłaszcza w odniesieniu do przestrzeni.źródło
Bez różnicy - chyba że używasz
#{some_var}
interpolacji ciągów stylów. Ale wydajność osiągniesz tylko wtedy, gdy faktycznie to zrobisz.Zmodyfikowano na podstawie przykładu Zetetic :
wynik
źródło
Pojedyncze cudzysłowy mogą być nieco szybsze niż podwójne cudzysłowy, ponieważ lekser nie musi sprawdzać
#{}
znaczników interpolacji. W zależności od implementacji itp. Należy pamiętać, że jest to koszt czasu analizy, a nie koszt czasu wykonania.To powiedziawszy, rzeczywiste pytanie brzmiało, czy użycie podwójnych cudzysłowów „zmniejsza wydajność w jakikolwiek znaczący sposób”, na co odpowiedź brzmi „nie”. Różnica w wydajności jest tak niewiarygodnie mała, że jest zupełnie nieistotna w porównaniu z rzeczywistymi problemami z wydajnością. Nie trać czasu.
Rzeczywista interpolacja to oczywiście inna historia.
'foo'
będzie prawie dokładnie 1 sekundę szybszy niż"#{sleep 1; nil}foo"
.źródło
Podwójne cudzysłowy wymagają dwa razy więcej naciśnięć klawiszy niż pojedyncze cudzysłowy. Zawsze mi się spieszy. Używam pojedynczych cudzysłowów. :) I tak, uważam to za „wzrost wydajności”. :)
źródło
Pomyślałem, że dodam porównanie 1.8.7 i 1.9.2. Prowadziłem je kilka razy. Wariancja wynosiła około + -0,01.
ruby 1.8.7 (2010-08-16 poziom poprawki 302) [x86_64-linux]
ruby 1.9.2p0 (2010-08-18 wersja 29036) [x86_64-linux]
źródło
Nie ma znaczącej różnicy w żadnym kierunku. Musiałby być ogromny, żeby miał znaczenie.
Z wyjątkiem sytuacji, w których masz pewność, że występuje rzeczywisty problem z synchronizacją, zoptymalizuj je pod kątem łatwości konserwacji przez programistę.
Koszty czasu pracy maszyn są bardzo małe. Koszty czasu programisty na napisanie kodu i utrzymanie go są ogromne.
Jaki pożytek daje optymalizacja, aby zaoszczędzić sekundy, a nawet minuty czasu działania w tysiącach uruchomień, jeśli oznacza to, że kod jest trudniejszy do utrzymania?
Wybierz styl i trzymaj się go, ale nie wybieraj tego stylu na podstawie statystycznie nieistotnych milisekund czasu działania.
źródło
Też myślałem, że pojedyncze cudzysłowy mogą być szybsze do przeanalizowania dla Rubiego. Wydaje się, że tak nie jest.
W każdym razie myślę, że powyższy test porównawczy mierzy niewłaściwą rzecz. Jest zrozumiałe, że obie wersje zostaną przeanalizowane do tych samych wewnętrznych reprezentacji ciągów, więc aby uzyskać odpowiedź, która z nich jest szybsza do przeanalizowania, nie powinniśmy mierzyć wydajności za pomocą zmiennych łańcuchowych, ale raczej szybkość przetwarzania łańcuchów przez Rubiego.
Wydaje się, że powtarzane biegi nie mają większego znaczenia. Wciąż zajmuje mniej więcej tyle samo czasu, aby przeanalizować każdą wersję ciągu.
źródło
Z pewnością jest to możliwe w zależności od implementacji, ale część skanująca interpretera powinna patrzeć na każdy znak tylko raz. Będzie potrzebował tylko dodatkowego stanu (lub możliwego zestawu stanów) i przejść do obsługi bloków # {}.
W skanerze opartym na tabeli będzie to jedno wyszukiwanie w celu określenia przejścia i tak czy inaczej będzie się to działo dla każdego znaku.
Kiedy parser otrzyma dane wyjściowe skanera, już wiadomo, że będzie musiał ocenić kod w bloku. Więc narzut jest tak naprawdę tylko narzutem pamięci w skanerze / parserze do obsługi bloku # {}, za który płacisz w obu przypadkach.
Chyba że czegoś mi brakuje (lub źle pamiętam szczegóły konstrukcji kompilatora), co też jest na pewno możliwe :)
źródło
źródło
Jest jeden, którego wszyscy przegapiliście.
TUTAJ doc
Spróbuj tego
To dało mi
i
więc jest to z pewnością lepsze niż konkatowanie i pisanie tych wszystkich wstawień.
Chciałbym, aby Ruby uczył czegoś więcej na wzór języka manipulacji dokumentami.
W końcu, czy naprawdę nie robimy tego w Railsach, Sinatrze i testach?
źródło
Zmodyfikowałem odpowiedź Tima Snowhite'a.
Wyniki:
źródło
Próbowałem następujących rzeczy:
A oto wyniki:
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
Jeśli się nie pomyliłem, wydaje mi się, że oba zajmują mniej więcej tyle samo czasu, chociaż pojedyncze cudzysłowy są w większości przypadków nieco szybsze.
źródło