-
Notifications
You must be signed in to change notification settings - Fork 284
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
Automatically recompile and reload Diet templates in the background in development mode #676
Comments
It could be possible to have a separate library for compiling diet templates into a .d format and generating the dub information, so that a vibe.d project can refer to them as a dependency? |
That would definitely be possible (just basically |
Unless you mean to use DUB just as a tool for building the dynamic library. In that case, the discussed support for single-file packages would come in handy. |
Oh I see where you're getting at. My approach was to make the server restart less damaging, but reloading the diet templates as a shared object during runtime could do well. In my current design of a config manager I'm also wondering if the server could be restarted without closing the processes (to re-build routes and listeners). |
I'll try to work on that, as it's a good showcase for shared libraries. |
That would definitely be great, I've actually heard that argument quite a number of times, that D was bad because of this increase of turnaround time and that people would rather stay with their dynamic interpreted language. "During development", I'd say, should just mean some kind of opt-in switch, probably using For file system monitoring, Regarding the template issue, even if it slightly changes the semantics, I think using a * This is currently only implemented for the win32 driver, but I could invest some time to get that running in the libevent driver, too. |
So this mechanism is very similar to Martin's repl mechanism :-) Hopefully one day we can also have And for a more general case, can we make this mechanism work for other parts of the application so that when each part is modifed, it will be hot compiled and reloaded. Of couse, before that we need to define a |
What I just fear is that generalizing this to ordinary D modules makes it too easy for people to step on their own feet by for example changing the data layout of certain types. Java has a lot more possibilities to detect such situations due to the detailed run time reflection, but a D application would either just crash, or produce wrong output. |
You mean data layout for messages? maybe we need another |
The problem I was thinking about is when you allow a component to reuse its old memory after it has been reloaded, which would be the most efficient approach, but would be prone to silent data corruption errors when for example a Maybe a hybrid approach, where each component gets the chance to explicitly serialize it's state before going down and then gets that serialized blob of data when starting up next time to restore its state. Still leaves potential for silently lost state, but at least enables the possibility to make a reload seamless. BTW, there is Cmsed by @rikkimax, which supports component reloading. I'm not sure if it uses any form of message passing or another runtime machanism, or simply allows sharing memory between the components. In general I think architecturally it would be the best solution to keep this functionality to a separate framework, either a higher-level one like Cmsed, or a totally generic one (one that is vibe.d compatible, of course) - because it should be possible to separate it and to avoid feature creep in vibe.d itself (there is already a lot of functionality that would be better off in Phobos for example). Template reloading on the other hand would just be a development aid and would not not really be part of the overall architecture. * If component A imports a module from component B that defines a |
Cmsed does not yet support reloading of templates ext. at runtime just yet. This is mostly from the state of my Actor framework Dakka. It is so far not able to call methods on other nodes. But that is not my next target, but the other one. Current is singleton actors, yes awful but hey great for controller classes. The policies I was going to use was quite simple:
Basically it shouldn't automatically include in the compilation any code that isn't required. Use the route as being the source file to be compiled and the rest just follows so to speak. But have the appropriate import paths added. Now this doesn't solve the dependency problem. My method for this is to have a directory by this which essentially allows for single dependency binary file and a directory with all import files. I am worried about how this will hold up on the routers end, and pushing it out to so many different processes to a request. But atleast this is only for testing and not production level usage. But right now this is purely theory. I'm personally open to making this less Cmsed specific if thats what you guys want. |
@s-ludwig I agree your thoughts about separating vibe.d and the component framework (akka like). Cmsed looks interesing :) About memory layout, is there an aproach to diff the data layouts of each modification? But that would become too complicated. In JVM which I'm more familiar, hotswap is a very complicated problem that leads to a commercial product, JRebel. I would not sugget we go that far :-) |
@rikkimax Does Dakka use the same technique to Akka to send messages between actors? like: remoteActor.send(action, &data, &handler); or do some compile time magic to make actor RPC just like function calls? remoteActor.action(data, &handler); // this translate into remoteActor.send(action, &data, &handler); or even better, use technich similar to vibe.d, making async calls look like sync? auto result = remoteActior.action(data); // suspends current Task waiting for remote actor's reply |
@zhaopuming Lots and lots of CTFE magic. I certainly love that stuff. Example: auto aref = new ActorRef!MyActorA;
aref.onChildError(null, "okay hi there!");
aref.test("Hiii from the client");
aref.die(); Ignoring that so far remote method call aren't implemented (but onChildError is as its a special case) here is a sample code I'm using to test with. Keep in mind it can create an instance of MyActorA locally. The reason its not, is because of the capabilities feature. It will support async and sync calls, based upon if it has a return value. I.e. ref, out or a return type. |
There's also the option of the front-end pulling data directly from some (cache?) storage to force a stable API on it. I'm leaning more towards that, but sending serialized data could also be a stable API type of option. |
One idea would be to create a unique "fingerprint" of each type that uniquely identifies the data layout and always send that together with the actual data. The receiver could then at least detect a mismatch and perform an appropriate action. |
Or the diet compiler could find the modules/files in which the types are defined and detect changes/import those automatically. |
On another hand, for frequent iterations I'm thinking it would be a good idea to enhance the The filesystem can prove to be a great document database vs. a dll or binary, Javascript is great for user-interface interactivity, and JSON is a great back-end connector. For debugging, using a e.g. For redaction of a blog post, a Also, it's easier for a CMS to interface with HTML files with a restricted API, than to interface with a dynamic templating format with (hard to parse) D code inside it. Finally, it's easier this way for ANY front-end developer around the world to implement third-party templates like those from http://themeforest.net .. copy-paste? |
The main problem is that the alias arguments are only accessible in nested functions, |
I'd just do it like |
Variant would at least avoid the necessity to import most of the project and vibe.d.
Yeah, I also arrived there, still juggling some other ideas though. There are two remaining questions.
|
I've built wrappers around HTTPServerRequest and HTTPResponse (HTTPServerResponse was too specific) upon Dakka https://github.com/rikkimax/dakka/blob/master/source/vibe-d_wrappers/dakka/vibe/client.d Also for reference: https://github.com/rikkimax/skeleton https://github.com/rikkimax/livereload (livereload handles the actual recompilation and rerunning of Dakka nodes). |
I fiddled around with this a bit and here are my findings. I still haven't found a way to pass data from the app to a shared
The latter two solutions have the severe drawback, that they require to import the app. #!/bin/sh
if [ $# -lt 1 ]; then
echo "Usage: $0 <cmd>"
exit 1
fi
APP=$*
dub build
$* &
pid=$!
while inotifywait -r -e modify ${PWD}; do
kill -TERM $pid
dub build
$* &
pid=$!
done While that works pretty nice, it's the the 5s turnaround time that we need to get down to about 1s. Let's break it down for a simple vibe.d project (vibe.d/examples/diet). From the 4.3s it takes to run Shrinking the time needed to compile the app will be a bit harder. For debug builds the compiler spends a big part of it's time lexing and parsing all imported source files. The last big part is spend by dub itself which is loading metadata and checks Overall I think we can reach the 1s even for real-sized apps. |
I've had a solution in mind that involved sharing the types between multiple libraries, by specifically putting them in a "common" D file or folder of files. For the speed issue, I also think a better solution would be to build a diet template compiler as a separate application, rather than using purely CTFE. This way, a simple set of D files that consist of functions and string appenders would be generated for each diet template. Maybe the type definitions could be isolated by the diet compiler itself. Thanks for the benchmarks =) |
I'm thinking of DScanner, and it would be of great use to search for the diet template |
Yes, that's what you would need to do, although you can cheat, use --export-dynamic and link the template against your app.
Yeah with many templates CTFE will become the bottleneck.
They'd also contain arbitrary code otherwise it would be trivial.
Still wouldn't allow to access private or voldemort types.
Interesting idea, DScanner isn't ready yet for code rewriting though. |
BTW, automatic reloading is always an option for further improvements, but it also benefits from any compile time reductions. |
Any updates on this? @s-ludwig |
FYI, anyone who wants to just make HTML changes to their diet templates can use the new live mode to avoid having to recompile. And it's much faster than a recompile. See the latest diet-ng description here: https://github.com/rejectedsoftware/diet-ng#experimental-html-live-mode I'm wondering if this issue shouldn't be moved to diet-ng (if not already) and closed here. An automatic recompile would be very nice intermediate step in addition to the live mode. |
Going to close this on account that:
|
During development, a file system watcher could be used to monitor file changes in the Diet templates that make up the application. Each diet template, instead of being statically compiled into the application, would then be compiled as a separate shared library/DLL and dynamically loaded and unloaded as needed.
The text was updated successfully, but these errors were encountered: