5
Liebranca
62d

YGGG IM SO CLOSE I CAN ALMOST TASTE IT.

Register allocation pretty much done: you can still juggle registers manually if you want, but you don't have to -- declaring a variable and using it as operand instead of a register is implicitly telling the compiler to handle it for you.

Whats more, spilling to stack is done automatically, keeping track of whether a value is or isnt required so its only done when absolutely necessary. And variables are handled differently depending on wheter they are input, output, or both, so we can eliminate making redundant copies in some cases.

Its a thing of beauty, defenestrating the difficult aspects of assembly, while still writting pure assembly... well, for the most part. There's some C-like sugar that's just too convenient for me not to include.

(x,y)=*F arg0,argN. This piece of shit is the distillation of my very profound meditations on fuckerous thoughtlessness, so let me break it down:

- (x,y)=; fuck you in the ass I can return as many values as I want. You dont need the parens if theres only a single return.
- *F args; some may have thought I was dereferencing a pointer but Im calling F and passing it arguments; the asterisk indicates I want to jump to a symbol rather than read its address or the value stored at it.

To the virtual machine, this is three instructions:

- bind x,y; overwrite these values with Fs output.
- pass arg0,argN; setup the damn parameters.
- call F; you know this one, so perform the deed.

Everything else is generated; these are macro-instructions with some logic attached to them, and theres a step in the compilation dedicated to walking the stupid program for the seventh fucking time that handles the expansion and optimization.

So whats left? Ah shit, classes. Disinfect and open wide mother fucker we're doing OOP without a condom.

Now, obviously, we have to sanitize a lot of what OOP stands for. In general, you can consider every textbook shit, so much so that wiping your ass with their pages would defeat the point of wiping your ass.

Lets say, for simplicity, that every program is a data transform (see: computation) broken down into a multitude of classes that represent the layout and quantity of memory required at different steps, plus the operations performed on said memory.

That is most if not all of the paradigm's merit right there. Everything else that I thought to have found use for was in the end nothing but deranged ways of deriving one thing from another. Telling you I want the size of this worth of space is such an act, and is indeed useful; telling you I want to utilize this as base for that when this itself cannot be directly used is theoretically a poorly worded and overly verbose bitch slap.

Plainly, fucktoys and abstract classes are a mistake, autocorrect these fucking misspelled testicle sax.

None of the remaining deeper lore, or rather sleazy fanfiction, that forms the larger cannon of object oriented as taught by my colleagues makes sufficient sense at this level for me to even consider dumping a steaming fat shit down it's execrable throat, and so I will spare you bearing witness to the inevitable forced coprophagia.

This is what we're left with: structures and procedures. Easy as gobblin pie.

Any F taking pointer-to-struc as it's first argument that is declared within the same namespace can be fetched by an instance of the structure in question. The sugar: x ->* F arg0,argN

Where ->* stands for failed abortion. No, the arrow by itself means fetch me a symbol; the asterisk wants to jump there. So fetch and do. We make it work for all symbols just to be dicks about it.

Anyway, invoking anything like this passes the caller to the callee. If you use the name of the struc rather than a pointer, you get it as a string. Because fuck you, I like Perl.

What else is there to discuss? My mind seems blank, but it is truly blank.

Allocating multitudes of structures, with same or different types, should be done in one go whenever possible. I know I want to do this, and I know whichever way we settle for has to be intuitive, else this entire project has failed.

So my version of new always takes an argument, dont you just love slurping diarrhea. If zero it means call malloc for this one, else it's an address where this instance is to be stored.

What's the big idea? Only the topmost instance in any given hierarchy will trigger an allocation. My compiler could easily perform this analysis because I am unemployed.

So where do you want it on the stack on the heap yyou want to reutilize any piece of ass, where buttocks stands for some adequately sized space in memory -- entirely within the realm of possibility. Furthermore, evicting shit you don't need and replacing it with something else.

Let me tell you, I will give your every object an allocator if you give the chance. I will -- nevermind. This is not for your orifices, porridges, oranges, morpheousness.

Walruses.

Comments
  • 1
    Nice one.

    Regarding memory, I just discovered "Arena". it's a block of memory that's on the stack. It works like malloc. The performance difference with malloc is insane. I benchmarked it. Got the idea from a graphics library that needed to be fast.

    What assembler do you use? I played with fasm a while ago. Would be bit easier than others. tsoding has nice video about it
  • 1
    @retoor Stack allocation itself is a single instruction -- substract size from pointer; preserving the previous frame would take it to three.

    A conservative estimate for traditional malloc, from having implemented it a few times, would be anywhere between a hundred and a thousand times more expensive. Now multiply that for every object.

    There's simply no contest. But the problem is moreso in norm than nature; we design around a bad approach.

    And coincidentally, I'm using fasm. Discovered it through Tsoding when he started enumerating assemblers in the early days of Porth. He moved to fasm himself some time after this.

    Useless bit of trivia: you can implement a rudimentary virtual machine in fasm using nothing but macros and virtual blocks. It's not at all usable, as it will dramatically escalate memory usage, but I find it fascinating that it's even possible.
  • 0
    @Liebrance i've just built a very precise benchmarking tool and want to play with it. Is there any way to benchmark stack memory? Or is only allocated at boot of your application? I did write a test that executes a malloc app and a heap for many times but ofc that didn't gave good results. Too much overhead of other stuff
  • 1
    @retoor Heap and stack are a false dichotomy. Mental exercise: at start, ie before main is called, use mmap or brk to get however many pages you want, then move ptr+size to rsp.

    If you push rax, rsp will decrease -- allocating 8 bytes -- and the value in rax is written to the new position. You now have a buffer that is, technically, both heap and stack.

    A similar effect could be achieved by just reserving some space via data declarations on a writeable segment -- db N dup $00 or similar idiom to get N bytes initialized to null. Point being, RAM is RAM.

    Here, catch: https://gist.github.com/Liebranca/...

    Obviously, running out of space means a crash at best, as you'd expect; and the OS is likely to give you enough stack space at program boot, so this delirium isn't something you're likely to ever want to seriously do.

    Anyway, how and when you get the memory doesn't matter for the benchmark, is what I'm trying to say.
  • 1
    (I was running out of characters) Most of what produces the difference in performance you observe is the overhead of searching for blocks that an allocator has to do.

    Suppose you are malloc incarnate. You have N pages of memory you got from the OS via one or another syscall, and are responsible for managing those. So anytime the user asks for however many bytes, you have to first make sure you have enough to accomodate the request.

    The more requests you need to satisfy, the more complicated the task becomes, because the volume of data you have to sift through grows. It's one of __those__ problems.

    Solution, as I see it, isn't more complex algorithms but the other way around. Allocate less -- by grouping objects -- and try to avoid the problem altogether. That means the allocator can be simpler, and thus, the overhead is smaller.
  • 1
    @Liebranca what do you prefer for returning string content in C? I prefer lately giving the result value as argument. The caller of the function knows what kinda data he's dealing with and is able to supply the correct size. Before that i preferred the static value method since values are mostly used once and forgotten. This keeps memory clean. Mostly i pass local vars. Before I used only mallocs (you can do 30.000 of them in less than a ms). I wrapped malloc so it counts my free's and allocations. Beats valgrind. Got that from nginx source code.

    Nice projects do you have. Especially the daf project. I've build a zip library recently encrypting files enough so that google (what i use as backup for projects) doesn't see my projects as virus anymore. I'm amazed that this 10yr old laptop does 250.000 file pointer seeks (going though zip file of 250.000 items) in a few seconds.

    Anyway, join the devrant matrix chat group. Devtalk there (sometimes :D). Also a few C devs
  • 1
    @retoor If I have to do it proper, then passing a pointer and getting the result back through it, yeah. It's more of a pain in the ass sometimes, C being like that fuels every other dev to write another language.

    There's a habit I've picked up, from working on this fucking compiler, I'm always counting cycles. It's faster to do that in my head, but CPU speeds are insane -- most inefficiencies I can detect this way only become noticeable when scaled up a few hundred thousand, or millions of times even. Directly benchmarking is obviously more practical, but I like having some objective idea of how much work I'm asking the computer for. A lot of my ranting here is just paranoia eating my brain.

    daf doesn't need to exist, but accessing single files from a giant tar isn't all that great. I lashed out at the problem until it went away.

    What is matrix? Can I run it from urxvt?
  • 2
    @Liebranca matrix is a chat protocol. Devrant has a room, search for drcc here and it' some message from @vintprox with the url in it.

    I'm almost sure some client works on urxvt.

    See my current benchmarking of my regex parser. I'm beating the C one so far, but it took two rewrites. The C one is extremely fast but it has a slow bytecode compiler. If i combine the parser + executor for every match, mine will win easy. It's bit weird that mines wins. It only has this: [1]{3} becomes [1][1][1]. Longer string but easy, executor doesn't have to think.

    See screenshot of my benchmark tool (tool so presice, it can measure how long printf takes. Nanoseconds and displays it nice).

    My printf is also a benchmark tool. if i do printf("\\T ago before previous statement") it will measure time since last statement that contained \\T.. It can also do colors, line numbers and "Hit any key to continue". Yes, in a print statement :D
  • 1
    Benchmarking of output functions like printf, putc, putchar, fwrite. The last, slowest to are mine. Those have much functionality.

    printf is written VERY well, offering such performance (often even beating fwrite) while providing so much functionality.

    I should check its source.

    I've more fun stuff but don't want to make you crazy :P
  • 1
    Fuck, i attached wong picture. I can't change using desktop site? Hmm, let's file a bug report
  • 2
    @Liebranca urxvt is a terminal, right? As @retoor has mentioned, it's a chat protocol. Somehow, she's found the chat appropriate for code review. Eh, I don't mind.

    Matrix is available through command line with element.el, iamb and gomuks.

    📎 If you have emacs: https://github.com/alphapapa/...

    📎 Prefer vim mode? https://iamb.chat/

    📎 For better screen estate usage: https://github.com/tulir/gomuks

    Once you're done, you can visit the room through your matrix client of choice, type:

    #drcc:matrix.org
  • 2
    @retoor printf as a benchmark tool? Sounds interesting. How's that work?

    Random: most regexes I've ever written are const. But now that I think about it, I'm not clear whether they're compiled at runtime or not. I mean to say, C compilers may or may not be stupid about this, but the parsing stage should be entirely skipped in such cases. Mmmh...

    @vintprox Nice! I'll check it out when I have some time ;>
  • 1
    @Liebranca I do printf("\\t"); to reset timer. I execute the code and then I just printf("It took \\T to execute."); To nano second precise Benchmark whereever you want, without writing any code for it. My regex interpreter is 6 times slower than the fastest C solution doing the same, so regex vs programming language. I consider this amazing. It's almost ready, I only need to add support for {n,}. Now it only supports {n}.

    We had a coding challenge yesterday. A simple one and we kinda failed in sense how much time we spent on it. It started with gpt code that we thought "that can better". Fun moment
  • 1
    @retoor Brilliant. A utility like that could be useful in a debugger, say for approximating execution time between two breakpoints. Eh, there are ways to do it in cgdb but you have to write the command, I think there's no builtin for it.

    I've been (likely unnecessarily) stressing a bit too much for the last few days, trying to get myself up to speed with the codebase for the new job; I feel I'm doing okay, but my brain is too tired to get other stuff done. Ugh, and it takes me so long to write a reply to anything, it's beyond stupid.
  • 1
    @Liebranca new job is hard, does the project look good so far? Ask access to sentry ASAP :p Nobody expects smth from you yet. I hope
  • 1
    @retoor The project is nice! I'm getting cool vibes from the people, also learning some stuff here and there. They didn't task me with anything too hard either, just picking whatever I feel capable of doing from pending issues; there's really no big pressure being put on me, but I am highly paranoid, so I want to try my best anyhoo.
Add Comment