-
Notifications
You must be signed in to change notification settings - Fork 26
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
Great job, I have a few questions #8
Comments
Hey Tim thanks for the interest, let me answer your questions and then go over other topics.
I'm planning to use this in production soon, but I don't advise it, use at your own risk. Thanks a lot for the note, you are the first person asking about this. This is my side project, I use it because it speeds up things and I don't have to write APIs and Front-end side stuff, just as most regular Django as I can (html over the wire) and some interactive components I write them in using this. Also this library has support out of the box to subscribe to server side notifications using the pubsub that Django Channels offers. |
Hi Eddy, Tim, let me multiply Tim's kudos for this project ! I'm currently working with it for a website in beta with few users. I deployed it with gunicorn with uvicorn workers. For now the deployment with django 3.0 is not possible due to incompatibilities with channels. I made 3 major adjustments to speed things up:
I do not have facts about the exact speed-up but it's quite visible and made this usable for me. I've added the following features:
I also like vuejs and I made 2 companions apps:
Anyway, it's a wonder to use and sped up the development by a huge amount for this first website. I didn't pull your last updates with the vue syntax I also made some experiments:
I have a few questions:
Congrats again with this awesome project ! |
Hahaha, this got even better... 😄 I'm happy Let me go point by point:
I'm running the current version with Django 3 already
I was guessing that would work, but I didn't want to add
Cool!
I was not expecting this, is this diff that slow? Is it even slow for normal django templates? Should we allow this feature go on or off using configuration? On features you added:
I don't want to write
Cool! I needed this and did it as On the two companion apps...Let me take a look to understand better what you did. On your experiments:
Answers
Yes, please!
I'm not sure what you did there, but async is concurrent but not parallel and threads in Python are not real threads is time-slicing, so they are concurrent but not parallel. |
Me too :)
I think I had troubles with gunicorn + uvicorn and django 3... some weird "no traceback" kick out of the app... it was too weird and I did not have enough time to investigate and just stick to 2.4.
Totally agree.
I will make a full performance testing example, just to be more factual about my own claims.
This is exactly what I did. You have to explicitly return
Yes it's quite useful. I had to tweak the
The way I did it is the second you mention: I just update a
I used js to manage the file input, convert to b64, send it to the python component, which just convert it back to bytes. At the end it's quite clean and straightforward...
Yep ! It was just to see if we can do something similar to the LiveView demo animation.
Nice ! Here is my plan: the code I made is quite dirty for now (too much experiments :) ), so in the coming month I will clean it up, merge your last updates and push it back on github. I will add the 2 companions apps:
Let me explain a little bit more: in the store I track which component should be updated when an attribute of the state is mutated. When multiple components "listen" to the same store state attribute, I would like to alert all of them concurrently. I don't need their answer, I just want them to update whatever the order... So threading here should work, it does not. The listening components are updated one after the other, in the order they were registered to the store. I think it's not a problem of GIL + threads, it seems that spawning threads do not work at all... Whatever it's not an emergency for now. Again, great work you did with that project ! It may become something big :) I'm totally convinced with it becoming a very convenient "SPA" like building framework with a lot of pros:
To be fair there are some cons:
I can't stop thinking about all the possibilities for our team. We may gain an order of magnitude for speed of dev, that's crazy. Thank you again ! |
Had this problem, upgrade your
To raise is even more weird and try catching is slow in Python and also is goto oriented programming, so.. no way.
Yes do that! That could be the first PR. 😄 since sounds very straight forward and does not change the current logic. I played with the For the moment I don't want to remove the html diffing, because I'm scared of the volume of traffic that can cause, but had not used this at scale to tell you if CPU load on the server is high or is too much outgoing traffic sending full html. I don't know, I did it because it sounded reasonable and LiveView in Phoenix does something similar. On the topic of companion apps, I'm curious to see what you did. For the moment, I'm not making full pages on this, just simple components that need to be interactive or I want to update them in real-time. I try to use as much of old-style django as I can. I hope this project is useful, even if it is just to we both. |
Guys, I'm glad that I've ignited this discussion! There are a lot of interesting insights! |
Haaa great !
Seems alright then.
Ok.
Ok.
Yeah here we reach the compromise CPU/IO that will depend on each specific case. A lot of small components that update often or big components slowly changing. I will take your code again from scratch and run benchmarks on all those options so that we step forward based on facts. Maybe we can agree on some "typical" usecases ? To start, I suggest:
Measuring:
What do you think ? Eddy, Tim ? We may have to also design a benchmark to assess more specifically the multi-user limits... memory especially I guess.
Those apps have "hard corners" for now, not really polished, especially the router. But anyway I will push them as soon as possible, which is within a month range at best.
I'm convinced it will be for others as well, I guess we are not so special :) @timonweb Yes, I wanted to talk to Eddy anyway but your questions woke me up ! |
Making those benchmarks? Amazing, thanks! @jbjuin don't worry about hard corners, this project is all hard corners... just push so I get a better idea of what you are talking about, and then I can disagree.. 😆 |
Just to start, first benchmarks give: Bench1The 10000 rows HTML table in single component.
|
I get it, this is just how much it takes to server-side render and transmit to the front-end. I aim for simplicity and good defaults, so I we have to compile and have our own diffing later we can do it. But now, do you suggest to remove diff-match-patch? |
I will make the bench 2: update a single row in a big table... in that case diff match patch will probably win when using django templates, the question is versus jinja2. We also have to evaluate results using the C++ python wrapped diff match patch. I tried and it seems that it did not improve a lot, but I will formalize that. We could start with sane defaults and propose an option "per component" in the class definition... since this is very component specific. |
Hi, Bench1The 10000 rows HTML table.
Bench2A 10000 row HTML table. 10 rows
100 rows
1000 rows
I did not expect this. It seems that diffing time increase with number of lines. I'm running this locally so transport time is negligible... so this is not in real conditions. |
I think responsiveness I think is the most important. Even if that costs a bit more of data-transfer. Optimize for raw speed is better. For the client and also for the server side. |
On the responsiveness side, I tried to use Mako templates. I wanted to try "spitfire" (see https://github.com/youtube/spitfire) but it's only for python 2.7. I just saw the elixir liveview official trailer by ChrisMccord. I envy the elixir templating system and how they build the diff, so smart: minimal payload + fast as hell... With the situation right now in France I have a little more time (no job commute) to work on this. I will try to publish my changes soon. |
I think you had gone very very deep down the rabbit hole and that's enough.... but is good to know. |
Congrats for you company ! Quite a promise ! I thought you were employed in another company, is this new ? Do you provide GPUs ? On the reactor side I really love it. I'm just catching with your last development and will propose some pull requests as soon as I have the time to clean my mess. |
Dear @edelvalle et. al. I've also been very inspired by Elixirs Liveview and wanted to drop by and say hi. After going through the whole journey of writing code for the web during the last decade, and having felt the pains of the different programming models:
combined with ever decreasing network latency - LiveView feels like a breath of fresh air. And one that has the potential to give an advantage like for instance Djangos Admin had back in the day. Therefore it's very exciting following your progress with a LiveView in the Django space! I've been working on a similar project over at https://github.com/runekaagaard/hypergen. Some of the differences to your project are:
It's still not ready for production, but there are some demoes that work. The first place where I reached a hard problem was with making an efficient pipeline between the server and the client. I - like you - also experienced with diff-match-path, and found it to be a non-optimal solution. You have to render the entire page on every request and it's a pretty expensive algorithm both on the server and the client. After the initial full page load optimally you would only render on the server and send to the client:
By part i mean a reasonably sized chunk of HTML. And then we are right back to a cache invalidation problem - we need a way to know if any of the data used by a part has changed since last time we rendered it. This led me to begin a new project at https://github.com/runekaagaard/django-treeform. It's still just in the beginning. The idea is that we need a declarative way of describing a transformation from stuff in the database to a tree structure with leafs made of scalars. When we have that, we can reason about the transformation a lot better, which allows for asking questions about the transformation without actually running it. In the context of Django, that is useful for:
With such a system in place, it gets a lot easier to know if you should render a given part or not. Then in the context of django-reactor a template could look something like: {% for guy in guys %}
{% cachepart guy %}
<h1>This part is expensive to render</h1>
<p>We better cache it!</p>
{% for friend in guy.friends %}
<p>
Good thing the database automatically invalidates
the cache of the guy when one of his friends change.
</p>
{% endfor %}
{% endcachepart %}
{% endfor %} Then it would be trivial to send only changed parts to the frontend. Anyway, thanks for reading. It felt like a good place to talk with like-minded individuals :) P.S.: Did you ever consider using the javascript from Elixir LiveView and reverse engineering a python backend for it? It already seems like a pretty mature piece of software. |
Nice! Very interesting observations. Wow, I really like the ideas in https://github.com/runekaagaard/django-treeform That's an interesting (declarative and functional) way to pipeline data transformation, and could allow to reason about it. Yes
Yes, @jbjuin benchmarked this and is really slow, but I'm also concerned with network latency and sending the whole HTML.
Doing this means implement the same protocol they use, could be possible to mimic, and use it as the golden standard. But when I started this I just experimented with many things, to do that I would have to do a complete rewrite or start a new project. I would like to experiment, with the most optimal option for python, not rendering in the backend. But having a client template langauge and pushing state to the client. In this way there is no need for rendering in the backend everytime. It could be nice to create an abstraction that is django independent because I would like to use this also with https://github.com/encode/starlette, for example. Right now I'm quite busy in other areas of my company that are not web related, but when I focus again in the web part I will think harder about this. Thanks for your post.... is very inspiring! |
This is really great work! While people are chiming in with previous iterations, I tried this in the past:
Maybe some ideas can be taken from these proof of concept iterations as well. My goal was to just be able to use Django-based templates on the backend and frontend while the frontend parts would refresh on |
@jbjuin you were sooooooo damn right about |
Hi Edy, numbers talk :) |
@jbjuin to remove external dependencies and still have some level of diffing I'm using in the latest release Company is going, we are going to release a new product this week: prediction of any column in an csv or excel... and providing those predictions over GUI or API. |
Hey, difflib is a great idea ! Nice ! Good luck for the product launch ! |
Hello Eddy,
I just wanted to say "Hi" and thank you for doing this! I've been dreaming about LiveView for Django since the day it first got announced. Definitely going to play with Reactor.
I have a few questions:
Other than that, great job and thank you again!
The text was updated successfully, but these errors were encountered: