Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Status of diff & patch #58

Closed
bobkocisko opened this issue Sep 20, 2018 · 8 comments
Closed

Status of diff & patch #58

bobkocisko opened this issue Sep 20, 2018 · 8 comments

Comments

@bobkocisko
Copy link
Contributor

Juanpe,

I'm currently considering options to simplify the application state management in a large app. So far the whole app has been coded imperatively and it gets somewhat tricky because one requirement we have is to track and send updates externally of only the state that has changed. It's becoming somewhat unmanageable as more new global features are being added...I guess we're just reaching the point of diminishing returns with the current approach. So I started looking into functional programming techniques which led me to immutable data structures and I came across your library. This is exciting stuff. One thing that is holding me back though from testing immer is the lack of diff / patch support. Since high performance is also a requirement but since we need to be very aware of updating only what has changed, support for efficient diffing would be essential. What is the status of this? And what is the level of difficulty to implement it?

@arximboldi
Copy link
Owner

arximboldi commented Sep 20, 2018 via email

@bobkocisko
Copy link
Contributor Author

JP,

Thanks! The app is basically MVC but the model also represents external device state which must be kept in sync. We need to support up to 250 external devices, each of which has about 10-300 settings. When a command is fired from the UI it needs to map to about 1-50 individual settings changes as well as some app state changes and many of these are asynchronous. Each setting has to be successfully sent and acknowledged by the external device(s). We must accurately track each device's current settings in memory because if we try to set something but it was already at that value, we get no acknowledgment from the device and have to assume something is wrong. And eventually we would like to have this all work transactionally so that if any of the settings requests fail that the others are rolled back to return to consistency. Additionally, each command needs to be able to be run in parallel with others; we cannot force them to run sequentially since they can be delayed with the network round-trips and multiple external APIs that we must update at the same time.

So far everything is working pretty well with some annoying caveats (annoying to a software architect, not so much the users). But new requirements are coming all the time and making the software harder and harder to reason with. I think that functional programming techniques like map/reduce/filter and immutable data structures would dramatically simplify the code and lessen brain fatigue :). But I don't want to lose performance in the meantime. The app is extremely performant right now and we want to keep it that way. Besides using immer for storing the state of the app, are there any optimized libraries for implementing map/reduce/filter in a performant way in C++, similar to what GHC does for Haskell (https://stackoverflow.com/a/35038374/4307047)?

One reason why I'm asking about performant diffing / patching is because I could see that as a way to answer some of these problems in a more encapsulated way and to help with merging the state of asynchronous commands into the rest of the application state. Another reason is that we have hundreds of controls in our UI and we have specific algorithms and signal/slot mechanisms to make sure that only the minimum number of OpenGL draw calls are run to update only the control(s) that have changed rather than re-drawing the whole screen. Our app runs on limited hardware so the user experience would be pretty bad and the processor would be running much hotter if we had to redraw everything all the time. I think that perhaps transitioning into a map/reduce architecture and hooking the UI updating signal/slot into the end of that pipeline might be an answer here but I'm only speculating.

Also, do you have any recommendations for maintaining pointers between nodes in an immutable document, which stay up-to-date across changes? The current design of our app does this everywhere. But every time I try to think about applying that to an immutable structure, my brain goes into an infinite loop. :) I suspect the only answer would be to store the identity or path from the document root and then re-traverse that path after every update to find the latest changes. Am I missing an easier/faster way?

Bob

@arximboldi
Copy link
Owner

arximboldi commented Oct 1, 2018 via email

@bobkocisko
Copy link
Contributor Author

bobkocisko commented Oct 8, 2018 via email

@arximboldi
Copy link
Owner

arximboldi commented Oct 8, 2018 via email

@bobkocisko
Copy link
Contributor Author

Thanks JP. Yeah it's a wild new world, and fun to be on the cutting edge doing it in C++. :) I appreciate your labors to explore this frontier!

Also one note: I think boost
hana also supports addressing struct members via constexpr strings.
Depending on your use-case, it might make versioning the data easier.

Could you elaborate how this would help with versioning? And is there a way to use those strings at runtime? I'm still green with understanding TMP-to-runtime communication and I haven't actually started using boost.hana yet.

@arximboldi
Copy link
Owner

Could you elaborate how this would help with versioning? And is there a way to use those strings at runtime? I'm still green with understanding TMP-to-runtime communication and I haven't actually started using boost.hana yet.

It helps with versioning if you are persisting these data-structures and cursors into the data-structure, such that the cursors become more resilient if you reorder the elements of the structs. And yes, I think you can use those strings at runtime too, just iterate over the members of the struct (at compile time or run-time), which might come super-handy to do the diffing in a generic way: https://www.boost.org/doc/libs/1_61_0/libs/hana/doc/html/group__group-Struct.html

@bobkocisko
Copy link
Contributor Author

bobkocisko commented Oct 8, 2018 via email

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants