Closed chergert closed 7 years ago
It just seems to be the best of two worlds (language & environment).
With #148 it should be possible to generate binding for Gjs and Python as that it would remove unfriendly dependencies from libvalum
and libvsgi
.
It's best to keep templating outside Valum and let people should choose how they want to do it.
I will write recipes and examples for templating that will cover CTPL, Mustache-GLib and hopefully template-glib ;)
If I can contribute in any possible way, please let me know. I am not really proficient in C (I try to, be assured), but I have a good background in templating language and Vala.
I maintain a copr repository (https://copr.fedoraproject.org/coprs/arteymix/valum-framework/) with interesting packages related to web development. I can surely make it available from there as soon as it's usable in Vala.
Just a side note: how would waf sit in Builder?
For waf, we basically just need someone who knows the build system to implement the various components. In particular, you need to implement IdeBuildSystem
, IdeBuilder
, and generally, an IdeBuildResult
.
The good news, is that can be done via Python or Vala plugins these days.
I'll check that out, waf has waflib.Scripting
for that kind of things.
@chergert is it possible to lower dependencies for Template-GLib? At least support GLib 2.32?
I went through the code and APIs look really nice! It looks very promising and I am sure it will integrate like a charm with Valum.
I am seriously reconsidering the value of a Mustache implementation. It's a very nice language though.
I've been working a bit on the routing and I figured I can sort rules lexicographically, which can sure help figuring out the next route in logarithmic time.
Hey just saying, the throughput of the framework is really impressive (about 6.3k req/sec on my chromebook).
@chergert
Just a few remarks:
tmpl_template_parse_location
to let the locator figure out the root templateWe can probably lower the dependencies just fine, I didn't use g_autoptr()
for that reason.
As for throughput, it's hard to tell if 6.3k is impressive or not without a couple of other data points. For example:
I remember working on a libsoup web-server a few years ago and getting over 10k, so there might be some room for improvement (or not, hard to tell without more measurements).
Another place you might run into contention is the thread pool. I haven't looked to see if you're doing your own thread pool, but GIO's internal thread pool for I/O workers is rather small. Additionally, GThreadPool
will contend on a single GAsyncQueue
as you scale up the CPUs. This is why I wrote the IrisWSScheduler (work-stealing scheduler) a few years back. I'm not suggesting using it, its sort of out-dated, but it's about a linear 8x speedup over a traditional thread-pool when running at load.
TmplTemplate:location
property seems reasonable.TmplTempltaeLocator
uses GInputStream
, but you can simply pass a GFileInputStream
from g_file_read
. Template parsing is meant to be thread-safe, in that you can do it from a thread pool worker.Cheers!
It's for relatively small messages (only a few bytes) served with SCGI under lighttpd. For that kind of load, it's around 1MB/s. I need to test different load types on a decent machine.
Soup does not perform that well however, but maybe it's not used optimally. I rather see it as a development/testing implementation.
Right now, it's single-threaded, but it might be interesting to dispatch in worker threads. I'll look into that, it would probably just be a thin rework in VSGI.Server
. I'm not much into under-the-hood I/O and try to keep things simple.
I try to focus on features and correctness for now and complete the roadmap for the 0.3. Once there, Valum will be sufficiently complete to address real use cases and it will be adequate to do some plumbing!
That would be really nice, it's kind of inconvenient to pass a template loader and not use it to load the actual template.
This is something I try to address in Mustache-GLib by making node renders into a stream (i.e. https://github.com/valum-framework/mustache-glib/blob/master/src/mustache-template.vala#L29)
This, and the streaming parser never holds the whole AST in-memory: it consumes and render incrementally while keeping minimal information about the section stack.
It's still a work-in-progress though.
It's really nice to see projects intersect like that.
I'm not sure what the value is of unloading AST nodes from memory. How many templates will a project have? I'd venture a guess to say the normal use case would be to keep a parsed-template around and reuse it rather than constantly reparse them. It also allows, if someone cared to, JIT the expansion code (although I'm not signing up to work on another JIT) :)
As for writing out to streams, generally we want to coalesce writes to file-descriptors, so to get decent performance we'd use a memory stream (on top of X stream) anyway. We do buffer to a GString, which is almost the same thing (unless you are generating many-MB responses).
Another problem with writing directly to output streams (without a memory stream), is that if the client is slowly reading from the server, you can block the generation process while it blocks on write (unless your kernel buffers everything). If you do everything async, this can be okay'ish, but not really if you are holding on to network resources like a database connection, cache connection, etc during the template expansion.
The problem with template is not the size of AST, but the size of tokens! Of course, that kind of use case are rarely occurring, but it's not impossible to have to deal with an heavy template, especially in bio-informatics ;)
This is why we have buffered streams: provide a stream API with bulk operations. But here again, if you have a heavy template and loops in it, be prepared!
An hybrid approach would probably be interesting: keep the AST in memory, but swap the text/heavy tokens with some cache algorithm (FIFO would work best). Implement a JIT upon that and you get the ultimate template engine.
It's not really appropriate to hold anything while doing I/O, not matter how it's done.
Basically, you want the capability to write directly: see Server-Sent Events for example. It's always possible to wrap the response body using FilteredResponse
for more specific use case. There's some work on that in #117
FWIW, template-glib does not keep around the lexer tokens, only the AST nodes.
Yes, but the terminals can hold text data. This is what I meant by tokens.
If you wanted ultra lightweight, just mmap()
the template files. Then you can have a string pointer + length
.
More realistically, we could put them into a GStringChunk
so they are contiguous in memory. It's probably only a few pages of memory in most cases, and you save the fragmentation too.
@chergert is there an equivalent for GBytes
?
Just found memory slices..
Hi,
I wrote a templating engine for GLib/GObject-Introspection this last week. Not sure if it is a fit for your project or not, but thought I'd mention it.
https://git.gnome.org/browse/template-glib
Unlike some others I've seen, it has a lexer/parser done with flex/bison. It can also extract GObject properties and call into GObject functions via GObject introspection. The syntax is somewhat similar to what you see in other templating systems out there.
I have some more plans for this, but we are going to be using it for the templating engine in Builder (for file/project templates) and I always love having collaboration :)
Anyway, you get the idea. The library is introspectable, so it should be usable from Vala. I tested Gjs and Python, which both work fine.
Cheers!