Problems changing the value of a reactive signal returned from a function
I was testing what would happen if I changed the entire value of the board, not the squares but the entire board, in case at some point I want to change the board. And I saw that if I change the value of the board, the anonymous function "loadBoard.get("chess_standard_8x8")();" is executed again. But I don't understand why this happens or how to solve it.
38 Replies
I tried creating a constant outside the component and calling it inside. And now it works correctly.
But I don't understand why, could someone explain to me?
Reading signals inside functions can create derived signals
For example,
Now, if you read doubleCount in a reactive scope and count is updated, doubleCount will also be updated.
In the example, the createEffect will log whenever the count changes
In this case, I'm not too sure why it's rerunning but I would untrack your reads of
board
in addPiece
I understand, and that solution I found also works, or would it be something bad?
Do you know if we could untrack the addPiece function that I returned. It's just that I'm not convinced that it does an untrack every time the addPiece is called, it would be good if the addPiece was already untrackable
I found createStore to be very convenient for handling these kind nested signals.
Like (sorry, the code is a bit messy) here:
https://github.com/edygar/minesweeper
https://github.com/edygar/puzzle
GitHub
GitHub - edygar/minesweeper: Simple minesweeper
Simple minesweeper. Contribute to edygar/minesweeper development by creating an account on GitHub.
GitHub
GitHub - edygar/puzzle: A simple puzzle made using solidjs+tailwind
A simple puzzle made using solidjs+tailwind. Contribute to edygar/puzzle development by creating an account on GitHub.
Good projects, I liked the minesweeper one. Although I didn't understand what createStore does. And why should I use it in my case?
It's up to you, but I find it easier to let the store handle the whole matrix, while reading, you are spared from calling the signals such as
board[0]()
, if board was a store, all it would take would be board[0]
. Also, the update function has a lot of useful things like: update members of an array with a filter function; a range and things like that; you can read more on https://docs.solidjs.com/concepts/stores#path-syntax-flexibility
Summing up, the code is more concise, and still have the read / write segregationI tried to create the Store in my case, but I couldn't 😅
You can untrack basically everything
I tried to untrack the function but it gave me an error, maybe I did it wrong.
You do it the same way you did before. Just don't forget to add the return so that your createAddPiece actually returns something
But I realized something. I can return the board without it being a Signal, and the returned board I convert to a Signal, and there is no need to untrack.
Yeah that works too
this?
Close
Just wrap what you had originally in untrack(()=>
I don't get it
I had tried that, but it doesn't seem to work because it keeps tracking it.
Maybe you can't untrack a function 🤔
@edygar I have managed to create the 'Storage'.
I decided to use CreateMutable because I find it easier and more convenient to change object variables. Although on the internet they recommend using CreateStorage more, but I guess CreateMutable is not bad.
this is how it looks 😁
In general there’s a performance gap in between them both, but let’s be real, the difference is waaaay to small for you to concern, it’s still orders of magnitude faster than React
And the code is very readable now
The only downside for createMutable is that in an application, passing around this ref is exposing your state to 3rd party components that my mutate your state without you knowing about it, but that’s on a large scale app
I don't understand it, can you give me a small example?
That's true 😅
Imagine now you grab a 3rd party component and pass the board as property. If they mutate your board, it will update the screen, but how are you going to reason about it other than looking the component’s code?
I am new at this. What does a third-party component mean?
I think I understood, with third-party component you mean like a library to add to my project, and that this library has a component and that if I pass the board as a parameter, if it modifies the value of the board from the other component, it would be modifying the state of my current component? Is that?
Exactly, the worst part is not knowing what’s causing some update. Again, in your case I don’t think it will ever be the case
It's good to keep that in mind
Regarding this message, it mentions a performance gap between the two, just out of curiosity which one would have better performance and why? I try to search on the internet but I didn't find any performance comparison.
There's this benchmark to help you understand a bit: https://krausest.github.io/js-framework-benchmark/2024/table_chrome_125.0.6422.60.html#eyJmcmFtZXdvcmtzIjpbImtleWVkL3NvbGlkIiwia2V5ZWQvc29saWQtc3RvcmUiXSwiYmVuY2htYXJrcyI6WyIwMV9ydW4xayIsIjAyX3JlcGxhY2UxayIsIjAzX3VwZGF0ZTEwdGgxa194MTYiLCIwNF9zZWxlY3QxayIsIjA1X3N3YXAxayIsIjA2X3JlbW92ZS1vbmUtMWsiLCIwN19jcmVhdGUxMGsiLCIwOF9jcmVhdGUxay1hZnRlcjFrX3gyIiwiMDlfY2xlYXIxa194OCIsIjIxX3JlYWR5LW1lbW9yeSIsIjIyX3J1bi1tZW1vcnkiLCIyM191cGRhdGU1LW1lbW9yeSIsIjI1X3J1bi1jbGVhci1tZW1vcnkiLCIyNl9ydW4tMTBrLW1lbW9yeSIsIjQxX3NpemUtdW5jb21wcmVzc2VkIiwiNDJfc2l6ZS1jb21wcmVzc2VkIiwiNDNfZmlyc3QtcGFpbnQiXSwiZGlzcGxheU1vZGUiOjF9
solid/store, either the createMutable and the createStore, resort to wrapping the object/array with a Proxy, and there's an overhead cost for that
I think I understood:
Solid/store, both createMutable and createStore, resort to wrapping the object/array with a Proxy, and that has an additional performance cost. This is because the Proxy intercepts read and write operations, executing additional code each time a property is accessed or modified, which introduces overhead.
And the overhead depends on the code that is executed in the Proxy's setter and getter interceptors.
But even though it has an overhead, you said it was very little, and with the benefit it has in terms of ease of use, it is better to use createStore and createMutable instead of using a createSignal (for cases like this)
Regarding the benchmark, I did not understand the information very well, I do not see the part in which the performance of both is compared 😅. (It doesn't matter though, I was just curious.)
Vanilla is the most optimized way, solid createSignal gets reaaaaaaally close to it, with store you lose just a bit, but when you compare to react, there’s no reason for concerns
Thanks for the images, now I understand it better.
One last question. Can you recommend me a page where I can do a benchmark, there are many and I don't know if all of them are good, or how do you do the benchmarks? I wanted to make a benchmark of:
this.data[byte] |= 1 << bitIndex; //The maximum bitIndex value would be 8 (1byte)
this.data[byte] |= BIT_MASKS[bitIndex]; //The maximum bitIndex value would be 8 (1byte). BIT_MASKS is a Uint8Array
I know that probably if there is a difference, the difference will be very small, but since the bot will have to do a lot of iterations, I wanted to do a test to see.The problem with benchmarks is not what we measure but rather what we miss to measure. xD So besides the CPU time, you should measure the pressure on the GC. Having that said, xD I've no idea, the benchmark I usually do is just the DevTools' ones, Lighthouse+memory snapshots.
I tried iterating both to see how long they lasted.
And it was faster: "this.data[byte] |= 1 << bitIndex;". But it seems strange to me that this is faster than using a MASK, if from what I saw on the internet the MASK is used to avoid the "1 << bitIndex", perhaps it is that since the bit offset is up to where bitIndex says, and the maximum value of bitIndex is 8 (1 byte) so it is faster than accessing the MASK element.
I have no idea 🤣
Hypothetically bit operations can be done directly in a CPU register which is the fastest operation there is (“hypothetically” because … JS).
Using
BIT_MASKS
forces a memory lookup which is comparatively slow.
ref
Data-Oriented Design (Or Why You Might Be Shooting Yourself in The Foot With OOP) (2009)Yaser Zhian
YouTube
Pitfalls of Object Oriented Programming, Revisited - Tony Albrecht ...
In this 2017 talk, Tony Albrecht (from Riot Games) revisits his earlier "Pitfalls of OOP" talk from 2009 ( https://www.slideshare.net/EmanWebDev/pitfalls-of-object-oriented-programminggcap09 .)
That's what I assumed, thanks for confirming it.
And About Data-Oriented Design. It's something like this?
The problem goes a lot deeper than that and given that JS has no control over memory layout it's not an issue that can be addressed within its purview.
The closest to the metal you can get is the JS runtime (V8, JavaScriptCore, SpiderMonkey) and the Web API; so the goal is to have as little JavaScript between what you are trying to accomplish and the JS engine; so every dependency better earn its keep.
If you want to benefit from ECS you'd likely have to choose a systems language compiling to WASM which comes with it's own, unique set of problems just to get the potential benefit of staying within the same cache line.
tree-shaking, the horticulturally misguided algorithm — wingolog
wingolog: article: tree-shaking, the horticulturally misguided algorithm
What's wrong?
What's wrong?
Thank you for the explanation.
I see that it has potential benefits in terms of performance and memory, although I believe that in my case it would be better to keep my BitBoard in JavaScript. Currently, I don't have practical knowledge about those topics, and it could be a significant challenge to implement them correctly. If in the future I find it to be too slow and I want to improve it even further, I will try to take it into account.
The point wasn't to dissuade you from using JS.
Both JavaScript and WebAssembly have the same peak performance. They are equally fast. But it is much easier to stay on the fast path with WebAssembly than it is with JavaScript. …https://youtu.be/njt-Qzw0mVY?t=1064 You may like Proxx (github) related content https://web.dev/articles/proxx-announce https://youtu.be/TsTt7Tja30Q
Chrome for Developers
YouTube
WebAssembly for Web Developers (Google I/O ’19)
WebAssembly is often hailed as a performance tool for critical tasks or to bring existing C++ code bases to the web – such as games. But WebAssembly is so much more. You can use WebAssembly as a puzzle piece to give the web platform the few missing capability that you are missing or to surgically replace a JavaScript bottleneck.
Watch more #io1...
PROXX — a game of proximity
PROXX — a game of proximity
Help your crew navigate space by marking out the black holes using proxx, your proximity scanner.
web.dev
Introducing PROXX | Articles | web.dev
PROXX as a minesweeper-like game built as a PWA. It works on a vast variety of devices and progressively enhances the visual appearance the more capable the device is.
Jamstack TV
YouTube
Jake Archibald & Surma - Setting up a static render in 30 minutes
In this session, Surma & Jake will take a JS-driven app and give it a static render, massively improving the time to first render, and time to interactive. They'll go through the useful build tools, and show how to avoid all the gotchas.
Recorded at JAMstack_conf_london 2019. Learn about upcoming dates and locations at https://www.jamstackconf.com
With that video it became clearer to me.