|
| 1 | +--- |
| 2 | +title: "JSON Logic Without Models" |
| 3 | +date: 2024-04-18 09:00:00 +1200 |
| 4 | +tags: [json-logic, architecture, performance] |
| 5 | +toc: true |
| 6 | +pin: false |
| 7 | +--- |
| 8 | + |
| 9 | +Holy performance increase, Batman! |
| 10 | + |
| 11 | +I recently made an update to _JsonLogic.Net_ that cut run times and memory usage **in half**! |
| 12 | + |
| 13 | +## In half?! |
| 14 | + |
| 15 | +Yes! Here's the benchmark: |
| 16 | + |
| 17 | +| Method | Count | Mean | Error | StdDev | Gen0 | Allocated | |
| 18 | +|------- |------ |-------------:|------------:|------------:|-----------:|------------:| |
| 19 | +| Models | 1 | 1,655.9 us | 26.76 us | 26.28 us | 410.1563 | 838.03 KB | |
| 20 | +| Nodes | 1 | 734.5 us | 8.16 us | 7.23 us | 236.3281 | 482.61 KB | |
| 21 | +| Models | 10 | 16,269.0 us | 167.06 us | 139.50 us | 4093.7500 | 8380.5 KB | |
| 22 | +| Nodes | 10 | 7,210.7 us | 25.26 us | 21.09 us | 2359.3750 | 4826.08 KB | |
| 23 | +| Models | 100 | 164,267.3 us | 2,227.54 us | 1,974.66 us | 41000.0000 | 83803.81 KB | |
| 24 | +| Nodes | 100 | 72,195.7 us | 139.28 us | 116.30 us | 23571.4286 | 48262.05 KB | |
| 25 | + |
| 26 | +In this table, "Models" is the old way, and "Nodes" is the new way. |
| 27 | + |
| 28 | +As you can see, "Nodes" takes less than half as long to run, and it uses just over half the memory. |
| 29 | + |
| 30 | +## What do "Models" and "Nodes" represent? |
| 31 | + |
| 32 | +From the initial release of the library, JSON Logic is represented using its own object model via the `Rule` abstraction. It would result in a large tree structure of strongly typed rules. This is "Models". |
| 33 | + |
| 34 | +The benefit of this approach is that strong typing, meaning that if you wanted to build some logic in code, you could use the associated builder methods on the static `JsonLogic` class and you didn't have to worry about getting argument types wrong. |
| 35 | + |
| 36 | +However, as you can expect, building out this rule tree means heap allocations, and allocations, in general, are slow. |
| 37 | + |
| 38 | +The "Nodes" approach, introduced with v5.2.0, doesn't use the object model. Instead, the system is stateless. It uses `JsonNode` to represent the logic, and the system runs "static" handlers depending on which operation key is present. This is the approach that I took with JSON-e, and it worked out so well that I wanted to see where else I could apply it. |
| 39 | + |
| 40 | +> I've had several attempts at making this approach for JSON Schema, and while it works, the performance isn't there yet. |
| 41 | +{: .prompt-info} |
| 42 | + |
| 43 | +JSON-e and JSON Logic also share a common basic design: they're both JSON representations of instructions that are processed with some kind of context data. |
| 44 | + |
| 45 | +## So no more strong typing? |
| 46 | + |
| 47 | +I think that's where I want to take this library. With all of the soft typing and implicit conversions that JSON Logic uses anyway, I don't think it's going to be much of a problem for users. |
| 48 | + |
| 49 | +Even on the [JSON Logic playground](https://jsonlogic.com/), you enter your logic and data as JSON and it runs from there. I don't see why this library can't work the same way. |
| 50 | + |
| 51 | +I don't really see a reason to need an object model. (And with functional programming on the rise, maybe this stateless approach is the way of the future.) |
| 52 | + |
| 53 | +But ultimately, it comes down to you. Have a play with the new setup. The [docs](https://docs.json-everything.net/logic/basics/) are already updated. I'd like to hear what you think. |
0 commit comments