About Me
Michael Zucchi
B.E. (Comp. Sys. Eng.)
also known as Zed
to his mates & enemies!
< notzed at gmail >
< fosstodon.org/@notzed >
Web N Shit ... N Stuff.
Hmm, so i've been poking away at webifiying[sic] our client's application.
Overall i'm making pretty good progress: worked out the async ajax stuff / XMLHttpRequest, 'hidden' form submission, RESTful resource mapping, handling long-running tasks and so on. The Enterprise bean stuff is pretty good, and particularly things like JMS, all the bean types, jax-rs, and jaxb. The latter two helping to hide some of the horrible shit going on under the bonnet.
But I dunno ... it's just boring. I probably would've found this stuff neat 5 years ago, and had a puppy over it 15 years ago, but now it's still enough of a pain in the arse having to deal with that given a choice I wouldn't be doing it.
Probably help if i'd had more than 4 hours sleep each day this week ...
Kobo
So i've mostly just been using my kobo for reading lately (not a lot, but i'm usually so tired I cna barely go 5 pages before i fall asleep) - and it's crappy software is giving me the shits, particularly when reading text files. I'm not sure I could do much better, but at least I could try ...
It even got me riled up enough to have another go at working out suspend: but again I had no luck. I just can't tell how it's going into suspend mode. If I could work out that I would have enough to keep me happy and I would do some more work on ReaderZ.
But without it i'm just stuck and it just pisses me off.
Update So it occurred to me later that the problem might be more related to the wifi adaptor since I'm always doing this stuff from telnet. If I try to suspend using /sys/ it never recovers and I need to reset the machine.
Easy Burmese 'tofu'
So yesterday I managed to get away from the machine for most of the day. Actually I got a bit sunburnt pulling out weeds and doing some gardening. Also mowed the lawn and did some work on the compost pile. And planted some winter vegetable seeds in pots: I have never had any luck whatsoever with winter vegetables (if I ever get the seeds to germinate they struggle and usually get eaten to death by bugs), but maybe this time ...
Well, I've been watching SBS's latest food show lately - Luke Nguyen's Greater Meekong - with all the advertising they fill each half hour slot with now it really needs to be a full 1 hour show - but Luke is a good presenter and although the editing could be a bit better he always finds interesting food and people who want to share it.
This week he had some chick-pea 'tofu' soup thing from Burma. The soup itself looked a bit heavy for my liking but although i'm no vegetarian I'm partial to some of the fare they like. I also like to learn about ethnically or geographically important staple grains. Actually it's a bit of a bummer looking for recipes with such ingredients because all you come across is vegatarian and vegan nutters who are looking for a filling main meal - not a tasty snack or accompaniment. It also involved a great deal of work - from a stone grinder, to muslin cloths to a giant stirred pot.
Because i'm lazy, the overnight soaking of the chick-peas seemed enough work for me, so instead I just blended the fuck out of them. I first tried topping up with water but that wasn't enough and I lost track of just how much I added. But I blended for at least 10 minutes and ended up with something akin to cream at the end of it. Enough blending that you could barely taste the fibrous material you otherwise end up with.
Then I cooked it on low with a good dose of salt and a bit of tumeric (as recipe I found suggested). At this point it was pretty much just making polenta. The old man used to make that and toast it on the AGA (which doubled as our only source of hot water as kids) all the time, and we all used to turn our noses up at it; and unfortunately I never learnt to make it before he died, so I had to learn how to make it by trial and error. It's also not something I make very often so I usually forget the finer details ... but I guess 'stir constantly until you're sick of it' pretty much sums it up. It didn't go quite as hard as the polenta i've made, but then again maybe it had more water in it. By the time it turned into a bubbling lava-pit my arms were tired so I decanted it into a cotton-lined dish and let it cool.
It looks and smells like polenta but tastes a lot better. Texturally it was fine: soft and creamy with no hint of fibrousness, I'm sure not straining it affected the result but what I ended up with was quite ok.
I diced and fried some up and it was pretty much like tofu in texture on the outside, moist on the inside, and tasted ok just on it's own (closest flavour I know would probably something like a papadum). Tofu isn't something i'd normally buy since it's pretty bland and I just don't know how to select it. The pre-cooked stuff is dry in addition to bland.
Since I also made up some hummus with some of the chick peas, I had a bit of a anti-pasto arvo snack. Some olives, hummus, biscuits, fried tofu, chilli sauces, and some fresh chillies as well (and beer and wine of course).
Amongst the chillies I picked I scored a triple-habanero from the garden ... I get doubles fairly often but this is the first triple. Unfortunately my habanero crop isn't so great this year, but I noticed I still have a few hundred (~5litres) in the freezer from last year so i've started trying to use them more often - but as they are so potent, I'm sure I will still end up with more than a winter's supply worth!
Web N Shit
So, as inevitably happens, the client wants to look at some mobile interface to some of the application we have.
Which for various reasons at the moment, means: web/html5/all that jazz. Fortunately someone else is working on the browser stuff so I get to avoid javascript ...
I get to play on the backend, so that means Java EE 6 ... Boy it's been a long time since I used any of this. Well I had a play with a wiki/documentation system a couple of years ago for fun but the last time I was paid to work on it was around 12 years ago: you know back when CORBA was mentioned on the first page ...
Java EE 6 has a fairly sleep learning curve - and a lot of reading required - but so far i'm pretty impressed. As you might imagine, with a decade of maturity behind it, there is a good bit of polish in the design. Some of the errors you get from the implementations could be a bit more meaningful though - array index out of bounds exception because one didn't specify proper attributes on the class or method don't help much. So after a couple of days of swearing violently ... it starts to fall into place really well.
I knew this was coming so for the last month or so I'd been re-architecting the desktop application in a more tiered and re-usable fashion so much of the jax-rs interface just slotted straight over the top with only a couple of lines of code for each request type. But that's the easy stuff: I also need long-running async tasks, so thats another big chunk of api to get to grips with.
And the winner is ...
Well I kept poking somewhat disinterestedly at some JNI code generator ideas. Just feeling pretty blah over-all, maybe it's the weather ... hay-fever, sleep apnoea, insomnia, all a big pita over the last few days.
I started looking into m4, and it could probably create a fairly concise definition and generator: but boy, the escaping rules and special cases are such a prick to learn it just isn't worth the effort. For all the intricacies of learning m4 there's very little pay off - it isn't a very useful tool in general and as I wont be using it all the time i'd just have to learn it all again whenever I looked at it. No thanks.
The cpp stuff is still an idea, but the definitions are clumsier than they need to be; one cannot automate the parameter passing convention inferencing which is often possible.
But the exercise did provide useful for the programme design. I took the way it worked and ported it to perl instead (now perl is a tool which is easy to learn with a massive pay-off; definitely not the one to use for every problem though). Macro processors do more work than they appear to on the surface, but after a bit of mucking about (and some fighting with weird perl inconsistencies with references and so on) I had something going. Well I suppose it's an improvement; it halved the amount of code required to do the same thing so that's gotta be better than a poke in the eye.
Because the jjmpeg binding generator is the oldest it's also the crustiest - so when i care I will look into it i'll probably replace it: it isn't a high priority since what is there does work just fine.
f'ing the puppy
Hmm, I haven't really been keeping up much with nvidia lately - they've obviously never really cared about OpenCL and what little effort they did for show seemed to disappear early 0-11. Oh and gmail suddenly decided they're developer updates were spam ... (they haven't mentioned opencl in any update for over a year).
Still, they make hardware that is capable of computing jobs, and they still seem to want to push their own platform for the job, so one must keep abreast - and if nothing else healthy competition is good for all of us.
I'd seen the odd fanboi post about how 'kepler' was going to wipe the floor of all the competition, and after all this time to see what has been released looks pretty disappointing. It's nice to see that they've tackled the power and heat problems, but this part is all about games, `compute' and OpenCL is left in the dust, behind even their older parts. And even then the games performance whilst generally better isn't always so. It looks like they skimped on the memory width in order to reduce the costs so they could be price competitive with AMD - so presumably a wider-bus version will be out eventually and is sorely needed to re-balance the system design.
I guess they've decided general purpose compute is still a bit before it's time, not ready as a mainstream technology and therefore not worth the investment. Well it's a gamble. Probably just as much a gamble as AMD putting all their eggs into that basket: although AMD have more to win and lose as for them it is all about CPU / system performance than simply graphics. Still, with multi-core cpu's hitting all sorts of performance ceilings AMD (nor intel for that matter) really has no choice and time will tell who has the better strategy. AMD certainly have a totally awesome vision, whether they can pull it off is another matter. Nvidias vision only seems to be about selling game cards - nothing wrong with that as money is what any company is about, but it's hardly inspiring.
I'm not sure how big the market is for high-end graphics-only cards. When reading
fanboi
'enthusiast' sites one has to put in perspective that they are still a niche product, and most graphics cards in use are embedded or the lower-end of the price range. Comments from kids saying they're going to throw away their recently bought top-of-the-range amd/nvidia card now that nvidia/amd have a new one out are just ludicrous and simply not believable (and if they really do such things, their behaviour isn't rational and not worth consideration).
Macro binding
So, late into the night I was experimenting with an alternative approach to a binding generator: using a macro processor.
Idea being: one relatively simple and expressive definition of an interface using macros, then by changing the macro definitions one can generate different outputs.
So for example, for field accessors I ended up with something like this:
class_start(AVCodecContext)
build_gs_int(AVCodecContext, bit_rate, BitRate)
...
class_end(AVCodecContext)
With the right definitions of the macros I then generate C, Java, or wrapper classes by passing this all through the C pre-processor. It's not the most advanced macro processor but it is sufficient for this task.
Then I thought I hit a snag - wont this be totally unwieldy for defining the function calls themselves?
So I looked into an alternative approach, using Java with annotations to define the calling interface instead, and then use reflection to generate the C bindings from that. The problem with this is: it just takes a lot of code. Types to define the type conventions, virtual methods for the generators, so on and so forth. Actually I spent several times the amount of time I spent on the field generator before I had something working (not terribly familiar with the reflection api required).
The definitions are relatively succinct, but only for function calls: for field accessors one ends up writing each get/set function as well. Still not the end of the world and it might be a reasonable approach for some cases.
e.g.
@JGS(cname = "frame_size")
static native int getFrameSize(AVCodecContext p);
@JGS(cname = "frame_size")
static native void setFrameSize(AVCodecContext p, int v);
@JNI(cname = "avcodec_open")
static native int open(AVCodecContext p, AVCodec c);
The annotations are relatively obvious.
Then I had another thought this morning: dynamic cpp macro invocation. I forgot you can create a macro call based on macro arguments. All I would need to then define is a new macro for each number of possible arguments, and other macros could handle the various conventions used to marshal that particular argument. And even then it would mostly be simple cut and paste code once a single-argument macro was defined.
So after half an hour of hacking and 50 lines of code (both java and perl were about 400 to do this, with perl being much more dense), I came up with some macros that generate the JNI C code once something like this is defined:
call2(AVCodecContext, int, int, avcodec_open, open,
object, AVCodecContext, ctx, object, AVCodec, c)
The arguments are: java/c type, return 'convention', return type, c function call name, java method name, argument 1 convention, type, name, argument 2 convention, type, name. If I removed the argument names - which could be defined in the macro - it would be even simpler.
I 'just' need to define a set of macros for each convention type - then I realised I'd just wrote some dynamic object-oriented c-pre-processor ... hah.
For a binding like FFmpeg where there are few conventions and it benefits from grouping and 'consistifying' names, i.e. a lot of manual work - this may be a practical approach. And even when there are consistent conventions, it may be a practical intermediate step: the first generator then has less to worry about and all it has to do is either infer or be told the specific conventions of a given argument.
Of course, using a more advanced macro processor may help here, although i'm not as familiar with them as cpp (and more advanced means harder to learn). So that got me thinking of a programming exercise: try to solve this problem with different mechanisms and just see which turns out the easiest. XSLT anyone? Hmm, maybe not.
I'd started to realise the way I'd done it in jjmpeg's generator wasn't very good: i'm trying to infer the passing convention and coding it in the generator using special cases: rather than working it out at the start and parametrising the generator using code fragment templates. The stuff I was playing with with the openal binding was more along these lines but still has some baggage.
openal weirdness
Hmm, so after my previous post I later noticed a strange detail on the alcGetProcAddress and alGetProcAddress functions (BTW the specification, unlike the opencl one, isn't very concise or easy to read at all): they may return per-device or per-context addresses(!?).
So rather than the routing to the correct driver that occurs transparently using OpenCL, the application must do it manually by looking up function pointers on the current context or on a given device ... although it isn't clear when which is exactly needed as some extension docs mention it, and others do not (although some function args are suggestive of which way the functions go). Further complicating matters is that the context may be set per-thread if the ALC_EXT_thread_local_context extension is available. A search on the openal archives nets a conclusion that it's a bit confusing for everyone.
Obviously java can't be looking up function pointers explicitly, so what is a neat solution?
- When using openal-soft (i.e. any free operating system), just ignore it: that's all it does. i.e. just use the same static symbol resolution mechanism as for the core functions.
- Look up the function every time - openal-soft uses a linear scan to resolve function names, so this probably isn't a good solution.
- I thought of trying to use a function table which can be reset when the context changes and so on, but the thread_local_context extension makes this messy, and it's just messy anyway.
- Move all extension functions to a per-extension wrapper class that loads the right pointers on instantiation. Have factory methods only available on a valid context or device depending on the extension type and associate the wrapper directly with that.
4 is probably the cleanest solution ...
Copyright (C) 2019 Michael Zucchi, All Rights Reserved.
Powered by gcc & me!