1 / 5
Oct 2015

Jako że język Ruby jest moim ulubionym językiem to często lubię śrubować najlepsze wyniki właśnie w nim. Ostatnio zwróciłem uwagę na fakt, że odpalając rozwiązane już zadania, dostaję gorsze rezultaty. Pierwszy przykład z brzegu: http://pl.spoj.com/status/PTEST,radarek/2 Zgłoszenia o id 15374614 i 14010695 to dokładnie ten sam kod. Oznacza to, że od kwietnia do dzisiaj musiało się coś zmienić w systemie SPOJ co wpływa negatywnie na wydajność rubiego. Nie wiem jak wygląda dokładnie sposób w jaki odpalacie programy, nie wiem także nic o instalacji rubiego na waszych serwerach. Jednak nie podejrzewam, żeby degradacji uległ sam interpreter rubiego. Podejrzewam natomiast, że może to być związane z dwoma rzeczami.

Po pierwsze, jeśli używacie takich rozwiązań jak rbenv albo rvm, to odpalając polecenie "ruby" odpalamy tak naprawdę nakładkę w postaci skryptu bashowego:

$ file `which ruby`
/Users/radarek/.rbenv/shims/ruby: a bash script text executable

Ten skrypt zajmuje się dopiero wyborem odpowiedniej wersji i odpaleniem jej z ostatecznej ścieżki, np. takiej:

$ ~/.rbenv/versions/2.1.5/bin/ruby -v
ruby 2.1.5p273 (2014-11-13 revision 48405) [x86_64-darwin14.0]

I teraz porównajmy czas odpalania tych dwóch programów:

$ time ruby -e "puts 'hello'"
hello

real    0m0.111s
user    0m0.057s
sys     0m0.045s

$ time ~/.rbenv/versions/2.1.5/bin/ruby -e "puts 'hello'"
hello

real    0m0.033s
user    0m0.025s
sys     0m0.006s

Czyli już widać pierwszą różnicę rzędu 0.08s. Na tym jednak nie koniec. Ruby domyślnie ładuje tzw. rubygems, które pozwalają na użycie bibliotek w postaci gemów. To niestety też dodaje trochę czasu. Im więcej zainstalowanych jest gemów w systemie, tym większy narzut. Oznacza to, że z czasem, jeśli np. administrator doinstaluje jakieś gemy, ten narzut będzie rosnąć. Zobaczmy jak duży jest ten narzut:

# włączone rubygems (domyślnie)
$ time ~/.rbenv/versions/2.1.5/bin/ruby -e "puts 'hello'"
hello

real    0m0.033s
user    0m0.025s
sys     0m0.005s

# wyłączone rubygems
$ time ~/.rbenv/versions/2.1.5/bin/ruby --disable=gems -e "puts 'hello'"
hello

real    0m0.011s
user    0m0.006s
sys     0m0.003s

Czyli kolejne 0.022s.

Ładowanie rubygems na serwerach SPOJ nie ma sensu, dlatego, że użytkownik nie ma możliwości ich instalacji, zatem nie może zakładać, że jakiś gem jest dostępny.

Sumarycznie daje to 0.1s, co przy wielu zadaniach jest narzutem ogromnym.

Byłbym wdzięczny gdyby administrator zerknął na ten problem.

tl;dr: zalecałbym (jeśli tak nie jest) odpalanie rubiego bez wrapperów (rbenv, rvm) i z wyłączonymi gemami (--disable=gems).

  • created

    Oct '15
  • last reply

    Oct '15
  • 4

    replies

  • 654

    views

  • 3

    users

  • 1

    link

Moim zdaniem nie ma to najmniejszego znaczenia, w jaki sposób jest to robione na SPOJ'u. Ważne tylko aby działało i jakoś działało i .... a dopiero na końcu dawało w miarę powtarzalne wyniki czasowe. A, że coś się zmieniło, inne czasy? Czy dlatego, admini nie mają uaktualniać wersji programów [kompilatorów, interpretorów, wraperów i różnych innych skryptów]? Ale jeżeli chcesz opinii - odpowiedzi od adminów, to tutaj [na forum] masz małe szanse na otrzymanie odpowiedzi. Musiałbyś napisać na adres kontaktowy.

PS
Jak będziesz pisał do adminów, to raczej nic nie pisz o swoich podejrzeniach i nic im nie zalecaj. Myślę, że powinieneś tylko poprosić uprzejmie o wyjaśnienie twojego problemu i wątpliwości.

@narbej bez przesady smile administratorzy nie gryzą, nie demonizuj ich tak smile
@radarek jest dokładnie jak mówisz, tzn. używane jest do uruchomienia polecenie "ruby". jeśli w debianie jest to zrobione tak jak opisałeś to może to być przyczyną spowolnienia. Myślę, że zmiana tego aby odpalać to bez wrapperów to dobry pomysł, natomiast co do gemów - trzeba by sprawdzić czy jakieś jednak nie są potrzebne.

Bez [poprzez] sieć [virtualnie] ciężko ugryźć, ale też można się trochę odgryźć. wink
@radarek coś mi tu nie pasuje. U mnie::

file `which ruby`
/usr/bin/ruby: symbolic link to `ruby1.9.1' 
ls -l `which ruby`
lrwxrwxrwx 1 root root 9 lut 15  2014 /usr/bin/ruby -> ruby1.9.1
ruby -v
ruby 1.9.3p484 (2013-11-22 revision 43786) [x86_64-linux]

Używam linux'a [na SPOJU też jest linux], a jakiego os'a używasz Ty? Może tu jest częściowo pies pogrzebany?.
Czy time jest dobrym narzędziem do śrubowania? Ja używam go tylko do sprawdzania, czy kolejna wersja kodu jest [dużo] szybsza od wcześniejszej. DO śrubowania, trzebaby szukać "wąskich" gardeł [używając profilowania i dużych tetów] i te fragmenty poprawiać, a przy odrobinie wprawy to wiadomo bez profilowania gdzie one są - odpowiedni algorytm, a potem i/o.
Oczywiście nie mówię o programach typu: "Hello World!". No i warto zauważyć, że SPOJ powstał i nadal służy do nauki programowania, a ranking, punkty, czasy itd służą do zwiększenia motywacji a nie są celem samym w sobie, czyż nie?

Oczywiście kwestia wrapperów dotyczy tylko sytuacji gdy stosuje się tzw. managery wersji (np. rbenv albo rvm). Jeśli ruby jest zainstalowany z paczki to tego akurat problemu nie ma. Polecenie ruby jest od razu exekiem. Natomiast zostaje kwestia gemów. Prosiłbym o porównanie czasów dla polecen "time ruby -e 'puts 1'" i "time ruby --disable=gems -e 'puts 1'".

Suggested Topics

Topic Category Replies Views Activity
System SPOJ 1 196 Jan 30
System SPOJ 2 139 Apr 15

Want to read more? Browse other topics in System SPOJ or view latest topics.