2014-02-15 5 views
2

Я играю с Racket и пропустил понимание байтовой строки. Когда я нашел for/fold/derived примеры в документации, я решил свернуть свой собственный байт строки макроса на слух, как любой новичок будет:для/list vs custom for/bytes в Racket

(define-syntax (for/bytes stx) 
    (syntax-case stx() 
     ((_ clauses . defs+exprs) 
     (with-syntax ((original stx)) 
     #'(let-values 
      (((bstr i max-length) 
       (for/fold/derived original ((bstr (make-bytes 16)) (c 0) (ln-incr 32)) clauses 
       (define el (let() . defs+exprs)) 
       (let-values (((new-bstr new-ln-incr) 
          (if (eq? c (bytes-length bstr)) 
         (values (bytes-append bstr (make-bytes ln-incr)) (* ln-incr 2)) 
         (values bstr ln-incr)))) 
        (bytes-set! new-bstr c el) 
       (values new-bstr (+ c 1) new-ln-incr))))) 
    (subbytes bstr 0 i))))))  

У меня есть несколько взаимосвязанных вопросов:

  1. Is этот способ Racket так или иначе?
  2. Является ли макрос нормально? В основном я объединил примеры из документации for/fold/derived с макрорасширением for/vector
  3. Есть ли очевидная оптимизация производительности?

К сожалению, это на самом деле не быстрее, чем (list->bytes (for/list ... Этот микро-тест:

(define size 50000) 
(define (custom-byte-test) (for/bytes ((i (in-range size))) (modulo i 256))) 
(define (standard-list-test) (list->bytes (for/list ((i (in-range size))) (modulo i 256)))) 
(profile-thunk custom-byte-test #:repeat 1000) 
(profile-thunk standard-list-test #:repeat 1000) 

дает 3212ms против 3690ms. Для размеров, размер которых намного меньше 50000, мой for/bytes проигрывает, для размеров больше, чем выигрывает.

ответ

2

Мои ответы:

Является ли это Ракетка путь так или иначе?

Да.

Является ли макрос нормально? В основном я объединил примеры из документации для/fold/производных с макро-расширением для/vector

Да, я думаю, это выглядит хорошо.

Есть ли очевидная оптимизация производительности? К сожалению, это не намного быстрее, чем (list->bytes (for/list ...

Я не знаю, как это сделать быстрее. «Победа» здесь заключается в том, что сложность изменения размера буфера скрыта от пользователей for/bytes.

2

Я немного ускорил ваш код.

1) Расчет bytes-length во внутреннем цикле не используется, поскольку вы уже знаете текущую длину. Я заменил ваш ln-incr на bstr-len, который представляет как текущую длину, так и сумму, чтобы увеличить длину.

Это дало ~ 15% улучшения.

2) Поскольку вы уже проверите длину, вы можете безопасно использовать unsafe-bytes-set!, что ускоряет работу до ~ 10%.

На моей машине custom-byte-test сейчас ~ 1200 мс против ~ 1750 мс для standard-list-test.

#lang racket 
(require racket/unsafe/ops profile) 

(define-syntax (for/bytes stx) 
    (syntax-case stx() 
    [(_ clauses . defs+exprs) 
    (with-syntax ([original stx]) 
     #'(let ([init-bstr-len 32]) 
      (let-values 
      ([(bstr i max-length) 
       (for/fold/derived 
       original 
       ([bstr (make-bytes init-bstr-len)] 
       [c 0] 
       [bstr-len init-bstr-len]) ; <-- use as curr len + extend len 
       clauses 
       (define el (let() . defs+exprs)) 
       (let-values 
        ([(new-bstr new-bstr-len) 
        (if (= c bstr-len) ; <-- remove len calculation 
         (values 
          (bytes-append bstr (make-bytes bstr-len)) 
          (* bstr-len 2)) 
         (values bstr bstr-len))]) 
        (unsafe-bytes-set! new-bstr c el) ; <-- unsafe op 
        (values new-bstr (add1 c) new-bstr-len)))]) 
      (subbytes bstr 0 i))))])) 

(define size 50000) 
(define (custom-byte-test) 
    (for/bytes ([i (in-range size)]) (modulo i 256))) 
(define (standard-list-test) 
    (list->bytes (for/list ([i (in-range size)]) (modulo i 256)))) 
(profile-thunk custom-byte-test #:repeat 1000) 
(profile-thunk standard-list-test #:repeat 1000) 
+0

Интересно.Обычно я не пытаюсь кэшировать '{string, bytes} -length', как я бы сказал в C/C++, потому что в Racket я предполагаю, что это не намного больше, чем приложение плюс struct de-ref. Однако, даже если это правда, в этом случае это будет достаточно высокая доля внутренней петли для материи. Хорошее улучшение. –

Смежные вопросы