Skip to content
  • Jean Boussier's avatar
    3c0b7872
    Speedup Trilogy#escape by 3 to 5x · 3c0b7872
    Jean Boussier authored
    Copying characters one by one is very inneficient, especially since each
    time the buffer capacity has to be checked again and again.
    
    Using `memcpy` for chunks of bytes that don't need any escaping, we can
    save a lot of time.
    
    Before:
    
    ```
    ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
    Warming up --------------------------------------
                2k-plain    23.802k i/100ms
           2k-few-escape    22.693k i/100ms
    Calculating -------------------------------------
                2k-plain    239.746k (± 0.5%) i/s    (4.17 μs/i) -      1.214M in   5.063403s
           2k-few-escape    227.900k (± 0.6%) i/s    (4.39 μs/i) -      1.157M in   5.078454s
    ```
    
    After:
    
    ```
    Warming up --------------------------------------
                2k-plain    94.975k i/100ms
           2k-few-escape    61.998k i/100ms
    Calculating -------------------------------------
                2k-plain      1.039M (± 1.0%) i/s -      5.224M in   5.025882s
           2k-few-escape    658.756k (± 1.3%) i/s -      3.348M in   5.082975s
    ```
    
    Bench:
    
    ```ruby
    
    require "trilogy"
    require "benchmark/ips"
    t = Trilogy.new(database: "test")
    
    plain = "A" * 2000
    few_escapes = (("a" * 19) + "\n") * 100
    Benchmark.ips do |x|
      x.report("2k-plain") { t.escape(plain) }
      x.report("2k-few-escape") { t.escape(few_escapes) }
    end
    ```
    3c0b7872
    Speedup Trilogy#escape by 3 to 5x
    Jean Boussier authored
    Copying characters one by one is very inneficient, especially since each
    time the buffer capacity has to be checked again and again.
    
    Using `memcpy` for chunks of bytes that don't need any escaping, we can
    save a lot of time.
    
    Before:
    
    ```
    ruby 3.3.4 (2024-07-09 revision be1089c8ec) +YJIT [arm64-darwin23]
    Warming up --------------------------------------
                2k-plain    23.802k i/100ms
           2k-few-escape    22.693k i/100ms
    Calculating -------------------------------------
                2k-plain    239.746k (± 0.5%) i/s    (4.17 μs/i) -      1.214M in   5.063403s
           2k-few-escape    227.900k (± 0.6%) i/s    (4.39 μs/i) -      1.157M in   5.078454s
    ```
    
    After:
    
    ```
    Warming up --------------------------------------
                2k-plain    94.975k i/100ms
           2k-few-escape    61.998k i/100ms
    Calculating -------------------------------------
                2k-plain      1.039M (± 1.0%) i/s -      5.224M in   5.025882s
           2k-few-escape    658.756k (± 1.3%) i/s -      3.348M in   5.082975s
    ```
    
    Bench:
    
    ```ruby
    
    require "trilogy"
    require "benchmark/ips"
    t = Trilogy.new(database: "test")
    
    plain = "A" * 2000
    few_escapes = (("a" * 19) + "\n") * 100
    Benchmark.ips do |x|
      x.report("2k-plain") { t.escape(plain) }
      x.report("2k-few-escape") { t.escape(few_escapes) }
    end
    ```
Loading