Giter Site home page Giter Site logo

sneeze's People

Contributors

ckampfe avatar junekelly avatar sinourain avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar

sneeze's Issues

Public iodata render function?

Hi, thank you for the excellent library. I love hiccup and I was really glad to see someone made an Elixir equivalent, so thank you.

I was curious, have you given any thought to having an additional public function that returns the raw iodata produced by _render(data), rather than the binary that results from IO.iodata_to_binary(_render(data))? I ask because lots of IO functions in Elixir/Erlang take iodata for efficiency reasons (e.g. :gen_tcp.send, File.write, etc.), and being able to pass a raw iodata rather than a binary can (in some circumstances) significantly increase throughput.

I made an additional function to render to iodata, like so:

def render_iodata(data) do
  _render(data)
end

And ran a quick benchmark on a relatively small template (about 50 lines of Elixir lists, rendered HTML size: 690 bytes) and it looks like there is some pretty good throughput there to unlock by avoiding the binary allocation:

at [ 00:28:57 ] ➜ MIX_ENV=bench mix run bench.exs
Compiling 1 file (.ex)
Operating System: macOS
CPU Information: Apple M1 Max
Number of Available Cores: 10
Available memory: 64 GB
Elixir 1.14.5
Erlang 25.3.2.2

Benchmark suite executing with the following configuration:
warmup: 2 s
time: 10 s
memory time: 2 s
reduction time: 0 ns
parallel: 1
inputs: none specified
Estimated total run time: 28 s

Benchmarking render/1 ...
Benchmarking render_iodata/1 ...

Name                      ips        average  deviation         median         99th %
render_iodata/1      170.58 K        5.86 μs   ±255.20%        5.04 μs       13.96 μs
render/1             119.27 K        8.38 μs   ±153.85%        7.42 μs       22.96 μs

Comparison:
render_iodata/1      170.58 K
render/1             119.27 K - 1.43x slower +2.52 μs

Memory usage statistics:

Name               Memory usage
render_iodata/1        12.88 KB
render/1               12.90 KB - 1.00x memory usage +0.0234 KB

**All measurements for memory usage were the same**

Would you be open to adding another function that returns the raw iodata? Thanks again for your efforts!

OTP 26 test failure

On OTP 26 (both Elixir 1.14.5 and 1.15.0) I'm getting this test failure:

  1) test create attribute string from map (SneezeInternalTest)
     test/sneeze_test.exs:186
     Assertion with == failed
     code:  assert Internal.attributes_to_iolist(%{class: "foo", id: "bar"}) == [
              [" ", "class", "=\"", "foo", "\""],
              [" ", "id", "=\"", "bar", "\""]
            ]
     left:  [
              [" ", "id", "=\"", "bar", "\""],
              [" ", "class", "=\"", "foo", "\""]
            ]
     right: [
              [" ", "class", "=\"", "foo", "\""],
              [" ", "id", "=\"", "bar", "\""]
            ]
     stacktrace:
       test/sneeze_test.exs:187: (test)

............................
Finished in 0.06 seconds (0.00s async, 0.06s sync)
30 tests, 1 failure

Randomized with seed 682196

which I believe is due to the (implicit) assumption that the map arg (%{class: "foo", id: "bar"}) will be iterated first by the class key and then the id key.

I believe this assumption which was previously valid is no longer valid because in the OTP team in OTP 26 made an optimization to maps which changed the iteration order of maps from being by the term order of the keys to being undefined:
"The new order is undefined and may change between different invocations of the Erlang VM." (https://www.erlang.org/blog/otp-26-highlights/#changed-ordering-of-atom-keys)

I've previously run into issues like this, and solved them by comparing the collections as sets (MapSet.equal?(s1, s2)) rather than lists, if order is not important. I'm happy to PR this change if you want it or discuss further if you have other ideas.

Thanks again for your efforts on this library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.