Mam kod, który wykonuje pewne parsowanie plików zgodnie z określonymi regułami. Całe parsowanie odbywa się w monadzie, która jest stosem ReaderT/STTrans/ErrorT.Generalizując monadę, wydajność spada prawie o 50%.
type RunningRule s a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String Identity)) a
Ponieważ byłoby przydatne do uruchomienia niektórych IO w kodzie (np zapytań do zewnętrznych baz danych), myślałem, że chciałbym generalizować parsowania, tak aby mógł on działać zarówno w systemie ewidencji ludności lub IO bazowej monady, w zależności od funkcjonalność, której pragnę. Zmieniło to podpis:
type RunningRule s m a = ReaderT (STRef s LocalVarMap) (STT s (ErrorT String m)) a
Po zmianie odpowiednie podpisy typu (i korzystania z niektórych rozszerzeń, aby ominąć typów) Pobiegłem go ponownie w monady Identity i było ~ 50% wolniej. Chociaż zasadniczo nic się nie zmieniło, jest znacznie wolniej. Czy to normalne zachowanie? Czy jest jakiś prosty sposób, aby uczynić to szybszym? (np. łączenie stosu ErrorT i ReaderT (i prawdopodobnie STT) w jeden transformator monad?)
Aby dodać próbkę kodu - jest to rzecz, która na podstawie przeanalizowanego wejścia (podanego w języku C) konstruuje parser. Kod wygląda następująco:
Czy kompilowałeś z optymalizacją i profilowałeś ją z kryterium? Jakie kroki profilowania podjęto, aby znaleźć to spowolnienie? – bheklilr
Skompilowany z optymalizacjami, włączonym profilowaniem i uruchomionym z + RTS -p, porównywał wyjścia - wynik sugerował głównie nic (poza tym prawdopodobnie ma coś wspólnego z monadami). Użyłem ogólnego "czasu", aby sprawdzić wydajność, na moich danych testowych zajęło to 2 sekundy z "zakodowaną tożsamością" i 3 sekundy, gdy pozwolono ustawić monadę tożsamości jako "parametr". – ondra
"i używanie niektórych rozszerzeń do obejścia typów" <- może oznaczać, że coś się zmieniło. Rozszerzony przykład kodu może pomóc szybciej znaleźć wyjaśnienie. –