#๐ช -progaming
1 messages ยท Page 109 of 1
no it actually matters
because threading is "fuck it, dont care throw this task on another thread, w/e, jsut dont fuck my main thread"
multithreading is "fuck i need this complex task computed as fast as possible across all cores"
it's kinda the first but i also don't want it to take for ages so multiple workers on demand
so im making sure this aint an A/B problem
i wish i was using go rn
what are you trying to do?
go doThing()
because i know few things that scale well with multi-threading in JS
just image manip
it's not about scaling, it's just for @elder yarrow
just not to block the main thread (and also be able to do multiple requests at once)
rn if u generate a gif with venbot it just blocks the entire bot lmao
yeah workerpool is useless for that then, you want to spawn a separate worker for each manip, as the requests come in
since you cant do image manip across multiple threads at once
how is it useless? isn't using a pool that can reuse workers way more efficient than always spawning a new one
why not?
how does it not scale wdym
this isn't gonna be editing 1000 images at once
a few at once at max
those should be done parallely
yeah, and you'll be performing likely synchronous merge operations on a single data array, this isnt C, and you wont be micro optimising mutexes
node threads are green threads, so you can simply spawn 10k of them, they are very low cost to start
but sorry, to answer your question, i've never used workerpool, since as a rule of thumb, all worker pool implementations in JS are dogshit, because its JS, when I need that kind of performance I usually opt for NAPI and C multi threading, which performs x1000 better
lemme have a gander at the codebase and i'll give u my opinion
its dogshit
its a very generic worker pool implementation, but it converts all functions you pass to it to a string first
which it then executes in the worler
you could write something better yourself in 2 minutes
yeah i wouldnt use that lol you can also create a worker pool from a file
2 minutes is a bit of an overstatement 
no
really
i'm not even joking
this is rudementary at best
it horrendously overcomplicates this lol
implementing a promise task queue is like what, a minute? then simply manage the state of the task que via message channel between a list of workers
anyways, i'd still probs just spawn a worker per action, since i'm lazy as shit, and worry about perf if that problem shows up then, but it shouldnt
it is
no worker pools have very good uses, its just.... they arent very common
launching a worker obviously has its overhead
and idle workers are idle so its not wasting anything
yeah, but realistically its no more than creating an array
its just an object with its own scope
its a green thread
anyways @royal nymph https://github.com/piscinajs/piscina
this seems like a less... insane version of what u need
i dont think it has serialization doe, which might be a problem
if you launch 1 per request and dont limit it you'll selfddos
nope
yope
Why not just find a proper async version of library for image manipulation
what's there to async
because they dont exist
js is single threaded
this example from their readme is insane
'use strict';
function add({ a, b }) { return a + b; }
function multiply({ a, b }) { return a * b; }
add.add = add;
add.multiply = multiply;
module.exports = add;
why are they abusing the add function as an object instead of just creating a new object lmao
module.exports = { add, multiply } ๐ญ
it's below
I'm talking about this example specifically
did you even read what I said 
yeh
the cursed part is that they're doing ```js
add.add = add;
add.multiply = multiply;
export add
well i skimmed over it because i'm looking for that one benchmark that shows that nodejs can easily handle like 20k workers at once
for rini
Probably so const add = require("mymodule"); console.log(add(1, 2)); and const { add } = require("mymodule"); console.log(add(1, 2)); both work
Eris does same afaik
https://pkolaczk.github.io/memory-consumption-of-async/ ah yeah it was this
In this blog post, I delve into the comparison of memory consumption between asynchronous and multi-threaded programming across popular languages like Rust, ...
is that actually real everyone online says you should only create n cores where n = cpu threads lmao
i dont doubt that the selfdos is one million image generations at once
yep, its green threads
aka "fake in software threads"
I mean nothing wrong with that
go threading is really efficient
yeah, its GC isnt tho :////
i wish they'd improve it, go would be unbeatable if they did
never had problems with it
go has the best multithreading I've ever used
oh yeah no 100% agreed
and improve the error handling while they're at it (mainly reduce boilerplate via stuff like trust's ?๐ซจ
go would be best language then
the only thing stopping nodejs from having go-like threading is the language syntax, because the featureset allows it
which suuuucks major dick
we need inline threading so much its unfunny
honestly i might just use a single worker with a queue
like just let us do
function goCommitDie() {}
new Worker(goCommitDie)
people can wait a bit for their request it's not like 200 people will be using it at once
yeah pretty much
still probs more work than just using this lib
since it alr implements a q
but yeah
is there any point even sharing small buffers (like few hundred kb) or is it cheaper to just copy them
you should add an image generation currency
and always faster
didn't know the exact word
it can cause errors if you dont handle it correctly yes
but its 0 cost, and always faster
is it really 0 cost tho
In go it's usually faster to copy function parameters than pass a reference
Unlike child_process or cluster, worker_threads can share memory.
for small arguments this makes sense
it depends on ur throughput, if the data is like >50MB/s it REALLY helps
if its not then fuck cares tbf
no sir, 50MB/s
not 50MB/call
it could be 1k calls of 50kb
objects are also automagically transferred
so no need to worry there
you only need to specify transferable arguments manually for potentially problematic things like direct memory aka arraybuffers, GPU bitmaps, and images
since those are often controlled
nah small data is actually cheaper to copy due to cache
in go maybe?
im fairly sure not in v8
again, its pretty much the same process, so there's no copying even happening
if you pass a reference it has to deref it from memory which is slower
yes but its pretty much always faster than structure cloning it
unless the data is like 8 bytes
go really optimised struct cloning 
Also gc shenanigans
if it can put it on the stack it doesn't have to gc
if you use a pointer it likely has to put it on the heap and then it has to gc it later
:P
the smallest data benchmark i can find is for 32MB
which is still a nuts difference
this post seems fire https://medium.com/eureka-engineering/understanding-allocations-in-go-stack-heap-memory-9a2631b5035d
yeah id always transfer larger data like this
I was mainly interested in smaller data
32MB isnt large XD
I always shit myself when I see huge data structures until I realise it's actually not as much as it seems
like casual array with 1 million elements
it's not actually that much
lmao yeah
i recently got my torrent client to run at like 2Gbit/s @ 1k connections on a single fucking thread
and its so horrendously simple to do high perf at scale in JS its crazy
just dont .slice() and dont copy
its always that simple
yeah, but it depends a lot on how you write code
arraybuffer is bigger afaik, but you need to manually increase the max V8 VM memory size
a good while ago I was playing around with js performance a bit
I wrote a simple password brute force algorithm
my first implementation was so slow cause I used string manipulation & comparison
then I rewrote it with nodejs Buffer and it was better but still slow
then I rewrite it with raw Uint8Array and it was incredibly fast
anyways, always use trasnferables, its a good habit to have, and its good to get used to the edge cases
yeah nodejs buffer is doggy
lesson of the story Buffer sucks 
its ancient
so it suffers a lot from backwards compatibility problems
it sucks because it needs to support its first versions, which sucked
and readables suck for the same reason do
I compared my final implementation to a similar C implementation and it was surprisingly close
only like 20% slower iirc
i always replace all readable usages with streamx, because its API is 95% the same, and its x10 faster, and interoperable with streams
what's streamx
you could get this down to even less im sure
but not bad for a fucking GC language eh???
v8 is NUTS
its like nodejs streams
just, not dogshit
3rd party lib
im not joking when i say ALWAYS use streamx instead of nodejs streams if you need to
but its always best if you use async iterators
but u cant always, so just use streamx
its SO much faster, because it doesnt touch buffer
nodejs streams always do a Buffer.from() on incoming data
streamx doesnt care, it just passes whatever data is given to it
I never use streams much cause I don't usually have a need for them
nice, keep it that way!
and if you DO need to just use:
for await (const buffer of fs.createReadStream('/path/to/data')){
//stuff
}
and
async function data * () {
yield 42
}
Readable.from(data()).pipe(fs.createWriteStream('/path/to/data'))
its unfunny how much faster it is than streams, even with the promise overhead
I think the only time I used streams is when uploading / downloading files with fetch
res.body.pipe(createWriteStream())
i legit did this for the torrent client lib i work on, made it 80% faster, reduced bundle size down to 400kb from 3MB, and dropped memory usage by over half
its nuts XD
hashing in nodejs still sucks tho
I hate how in nodejs there's both web and node streams and different apis use either one so it's a pain to make them compatible and you have to constantly Readable.fromWeb
like i get the desire to be spec compliant but man does it suck
the web crypto api in nodejs is fucking slow, and the node api for it is synchronous and blocking, but x4 faster :/
oh fuck both of them
i strictly operate only on async iterators
seriously u should adopt this ideology
just async iterators everywhere
fuck stream bullshit
how do you do this with async iterators :P
here u dont need to since u dont douch the data
res.body is response from nodejs global fetch
so what u have works fine
this is what I mean btw https://codeberg.org/vee/bot/src/branch/main/src/util/fetch.ts#L39-L40
fetch.ts: Lines 39-40
const body = Readable.fromWeb(res.body);
await finished(body.pipe(createWriteStream(path)));
the fact that you gotta convert it to node from web first annoys me
its not that bad
node fs is stream only for the most part
ofc i have my own implementations which are faster, using handles and data flushing
for random access file
but u dont need that perf, so that is perfectly usable
yeah it almost never matters for the things I'm doing
import 'fast-readable-async-iterator'
import { open } from 'node:fs/promises'
const res = await fetch('gay')
const fd = await open('sample.txt')
for await (const data of res.body) {
await fd.writeFile(data)
}
await fd.close()
i think this should work
i dont remember i didnt use file handles for quite some time now
i dont remember if writeFile appended or overwrote
completely unrelated but I wish web had something like android's recyclerview
its really more difficult than it should be to make performant lists in html
like rendering thousands of items efficiently
android's recyclerview is so nice to work with for stuff like this
take a lot of items and render them efficiently in complex layouts with smooth scroll, filtering, etc
.parent {
will-change: scroll-position;
contain: strict;
}
thank you for coming to my ted talk
well it's not that simple lmao
it actually is
if you just render all elements at once it's gonna be uber laggy
skia is actually that good
nope
tested this on lists with like 40k items
works like a charm
its like 80% of the perf of a dynamic list
for how easy it is, might as well
there's a CSS property for this
if you have fixed sizes
one sec
contain-intrinsic-height
pretty much does dynamic lists like that
with content-visibility: auto
that is
here
The CSS content-visibility property enables web content rendering performance benefits by skipping rendering of off-screen content. This article shows you how to use this new CSS property for faster initial load times, using the auto keyword. You will also learn about the CSS Containment Spec and other values for content-visibility that give you...
this is simply why web is better than android or switft, you dont need to bother with implementing dogshit like that for rendering UI, the web does it for you
and its craaaaaaaaaazy discord uses none of this
i had to write a fuckload of css just to unfuck the discord UI perf
extremely simple example: there's noticeable lag here when you click generate and only will get worse the more complex your layout becomes & styles are added
this just rendered everything and if you had 1000 notifications it would lag for like 2 seconds no joke
i migrated it to Discord's lazy scroller implementation 
this uses none of the things i mentioned doe
okay so make it speeeedddy
show
also real word example is here https://badges.vencord.dev/explorer, the performance is really shitty
although the lag is kinda expected cause it's loading like 400mb worth of images (and this site is incredibly low effort)
ez.
but yeah 99% of the perf here is the images, not the list
so its not even the same problem
ez
is that with the images
actually
without the changes i cant get a single frame to drop on this
i added 2 0's to the list
and no problems
ah it finally died at 10000000
i added two zeroes and got this
and with one added zero theres incredible lag
this is 100000 elements
yeah i did a
for (let i = 0; i < elements.length; i += 100000) {
const batch = elements.slice(i, i + 100000)
container.append(...batch)
}
like here
yeah i gor the repro
yeah
i see your skill issue
you're thinking that the JS lagging is the UI lagging
the UI isnt frozen, its the JS chugging iterating the array
so this is a bad repro
and this is a bad repro, because 95% of the render goes towards the images
there's still noticeable lag between the append calls finishing and the ui appearing
also those js measurements seem really off so the js thread seems to be freezing a lot
because it's rendering?
no, because its iterating tru the array
<style>
#container {
height: 100vh;
overflow: auto;
will-change: scroll-position;
contain: strict;
content-visibility: auto;
contain-intrinsic-height: 34px;
}
</style>
<div id="container"></div>
<button id="generate">Generate</button>
<script>
generate.onclick = () => {
const data = Array.from({ length: 1000000 }, () => Math.random())
const elements = data.map(n => {
const p = document.createElement("p")
p.textContent = n
return p
})
for (let i = 0; i < elements.length; i += 100000) {
const batch = elements.slice(i, i + 100000)
container.append(...batch)
}
}
</script>
this will get the render down to 0
if u enable rendering -> frame renderign stats
and if u go on badges, and enable paint flashing
you'll see why that's lagging
you're also not using decoding="async" on the image
this still has really laggy scrolling
try scrolling fast you will get a lot of white screen
not for me?
oh yeah
fucking duh
thats ur GPU running out of memory
any virtual list will have 1:1 the same problem
scratch that, no virual list will catch up to those speeds
but i'm scrolling at my display's vsync
aka 165fps
virtual lists are supposed to fix that as well ๐ญ
no sir, virtual lists do not manage GPU memory
they cant tell skia to evict a bitmap
they can remove an element, which will schedule it for eviction
but that's still slower than simply scrolling it out of view
why would it not deallocate immediately
alright ma'am
no?
sir skia limits itself to <1.4GB of GPU bitmap memory
worst part, its shared across all active chromium processes
so if you have, discord, steam open, its reduced even more
wait what ๐ญ
lord i wish i knew, i've been trying to change this behavior for 2 years now
i have so many chromiums open is that really why
especially if its shit like steam's or discord's animated image frames, which are gifs, which allocate a single bitmap per image frame yes
because gifs are horrendously inefficient when it comes to repaints
oh i know
again, open ur badges thingy and enable paint flashing
ive had my share of pain with gifs
this is like genuinely so dumb it should just be configurable
i dont mind it using up most of my resources for a better experience
that's what i bought it for
fucking
mood
as
fuck
ive been fighting this for ages
and i still dont know the exact in and outs of it
but its horrendous
worst part? your shit will start blinking if ur fps is too high
and u have other views
its REALLY bad
also i love how this kept stressing my pc until i closed the page just now even minutes after i stopped
how do i make that site faster
i get that it's always gonna be laggy cause of rendering so many fucking images but man
why does it even take this long to load from disk cache
decoding='async'
on the img tag
and not using gifs
also if ur framework supports it, enhanced images
"my framework" bro it's just a single html file ๐ญ
yeah this seems to have made it better but now the ui is kinda glitchy
like this white empty bar at the top for a bit while it's loading
LMAO
its legit this XD
why does this happen
shit is already loaded in and should just show empty black border
i threw this crap together super quick
but u could do this to fix htat
nah look
it wasnt like this without async decoding (instead of empty white bar it would show empty black borders)
really
yes!
lmao srs?
this is with --disable-gpu
X D?
at least vencord badge explorer uses less ram than nixos config options page
enjoy linux i guess?
what does this mean
that you manually override rgb profiles for ur chromium instance most likely?
most likely?
i def dont
simple linux enjoyment then
well i dont have those in chrome fwiw
thats what i get
but yeah simply too many animated images at once
nah wtf just happened ๐ญ
and shit shits itself
yes, contain: strict isnt easy to work with
and intrinsic size needs to be sthe size of the element and its padding
oh my god zooming out was a mistake
you're legit working with the worst possible case scenario here
aka a fuckload of animated gifs
and massively oversized images
i should just merge them into one big spritesheet
lol yeah a lot of the old badges are insane
all the new ones are sane (mostly webp and all 64x64)
should probably write a script at some point that optimises all the old ones but no point really
the UI isnt
ya
is there any way to have fast scrolling like this not look terrible
or do we just have to accept that
uuuh
nuke all ur chromium processes and start ur chromium process with --force-gpu-mem-available-mb=9000 then use d3d9 ANGLE
will improve it a bit
not by much tho

also disabling raw-draw might help
only 500x500
only 75 frames
still 15mb
god i love the gif file format
dude i converted it to webp with no other changes and it's just 1mb ๐ญ
worst part? still asaggy as the original gif
as it causes a paint update each frame
KEKW
anyway the explorer isnt that important anyway i just made it for fun
this is just for displaying badges in discord @steady cloak
wouldn't it be a lot better cause it's way smaller?
40kb vs 15mb
if it really is less efficient than video why don't browsers make it more efficient
gif i get - gif is just inherently atrocious
but an optimised webp/avif?
a bit yeah
but not much
the repaints are the biggest problem
i will simply merge all images into one single sprite sheet 
I honestly don't know what's the best solution here
most people just use videos for this since they are less laggy
height:100%
fixed
legit no cap
is it finally a PR you'd merge in <3 months?

didnt feel any different (also had to use vh not %)
i have like 500+ favourite gifs
when you scroll it's just blue loading for eternity
a while ago i thought about making a plugin that generates thumbnails for each gif and displays those while stuff is loading
Hiya !
what is the rust equivalent of make -C someDir
For me it's like 1.5x times faster than before, I think the media proxy now returns webps/webms by default
cargo build โโmanifest-path someDir? Not sure what make -C exactly does (I do not use make)
oh yeah @royal nymph add loading='lazy' to the images too
yeah i did already ages ago
hm android wack
make -C:
- move to the directory specified after -C
- call Makefile in that directory
- return back
-C <DIRECTORY> Change to DIRECTORY before doing anything (nightly-only)
why is it nightly rust is so fucking dumb
@woven mesa trying to add something that presses cmd v to paste into a field but seems like it doesnt work idk how to fix
i havent used these apis yet
unfortunately i cant test it and figure out what to do correctly for you
sorry oomf
sad because the apis are super straight forward but idk whatโs wrong with it
makes a source and disables keyboard events for the time being
then press keys

also maccy making an entire class just for AXIsProcessTrustedWithOptions is kinda funny
might as well just use AXIsProcessTrustedWithOptions only, itโs just a bool
lmao
Why isnโt this default?
Animated webp support is complicated because it uses vp8 in RIFE in a non standard way
Most people and Linux distributions ship outdated versions of av1 encoders
riiiiiiight?
fuck cares, it has software fallback
I remember when Debian was shipping libaom 1.1 or whatever when 3.0 was about to release which was orders of magnitude faster
ah
Avif isnโt common cause to most people theyโre expensive to make
And cheaper to just use more bandwidth
Because server hardware is typically old as shit
no, avif isnt used because it doesnt have full browser support and because its slower to render as it causes more repaints
how difficult it is to make has NOTHING to do with it
for web def what matters is first contentful paint, and browser share support, legitimately nothing else matters, because those 2 things are DIRECTLY tied to revenue
4 cents of extra cpu time to encode an image is not the determining factor, trust me
Like, youโre wrong? Lol?
Iโve talked to actual discord staff about this
its also why progressive loading formats have been completly abandoned, becuase they imploded first contentful paint times
are you...
that dense?
or just pretending?
discord isnt a website
its an electron desktop app
its constraints are different
discord has a pre-determined featureset and feature support since its always running the same chromium version
Discord electron has supported av1/avif for years
great, cool
We used a bug to embed av1 for a long time 
But yes discord is different, but most CDNs also have strict transcode deadlines as well
Because of the amount they deal with
yep, is still is no way related to global adoption of AVIF
Then why donโt they if 96% of all web users have browsers with support?
HTML supports built in fall backs
thats the cool thing
the versions that support fallback support avif
the ones that dont support fallbacks dont support avif
its TRULLY that simple
So weโre stuck using jpeg forever by that logic
yes!
exactly!
its why webp failed
and one of the reasons why JXL failed
tho thats a MUCH longer list
google pretty much said that JXL and AVIF is effectively unusable because they implode first contentful paint times, and implode CPU on lower end phones, which are horrendously common
i could probably find the exact comment
its somewhere on web.dev
Webp wasnโt a failure
it is
All of Google uses webp, plenty of popular websites use webp
yeah this is simply wrong
they still use jpg
Probably cause the images being served are too big
All of Google images is transcoded to webp, their own assets use webp, all YouTube tumbnails are webp
why are you making shit up lol?
Iโm not?
legit none of google images is webp, none of youtube is webp
they have PARTIAL support for those formats, but 80% of the time they fall back to jpg because they dont have most thumbnails in webp
on google images out of 230 loaded images only one was a webp
on yyoutube not a single one was, and half is avif, since only half are actually in that format
since youtube simply doesnt do avif for most video thumbnails
they also fall back to jpeg based on user agent
Correction. The thumbnail for the latest Mr beast video is avif
Idk youโre saying I make shit up when Iโm right about YouTube
and they miss-label the extension of the image, because the source image is still just a jpeg, they just trancode it on the fly based on user agent
Maybe a year ago it was different. Does not matter 
Yet itโs avif
motherfucker are you reading what im saying
Google uses their own image formats itโs amazing
thats the sqp based converted image
Yes.
and the source image is a jpg
they convert it on the fly
based on browser's support
yeah the source images are still jpg mate
Why does that matter?
@alpine pecan, to be frank you are an annoying, rash, and intolerable person to talk to.
I'm far more invested into the project you have been seeing me complain about in #๐ช
-progaming than you ever will be and i know more than you ever will.
I'm not sure how the hell a person like you who is so insufferable can exist.
...?
are you insane or insane?
they cant use avif, because browsers dont support is simply
they always need to use jpeg
they simply detect my browser supports it
the source data is still jpg, it still operates on jpg
because they cant abandon it
because avif isnt good enough to replace jpg
Yes?
This is how internet works
Deleting the original jpg also means they add generation loss when AV2 releases in the next 1-2 years
They STILL use it for users who can see it
yes
but we're still gonna be using jpgs in 2 years
because webp and avif will never be able to replace it
thats why those formats failed
you are both stupid
Weโre always going to have to use JPEG but as a fallback.
you should be using protobuf instead
We can use anything better for 90% or all users
FALLBACKS are a good thing
I donโt think they should go away
youtube is giga specific because it doesnt run on mobile
which is likely why google decided to use avif only on youtube
and nowhere else
Even on mobile they serve avif
yes but the mobile userbase is 0.1% of what google image has as the mobile userbase
avif was developed at google lmao of course they're going to be using it
also youtube does use webp for things like those animated thumbnail previews
Jop
same for webp and av1
and it still takes ages to adopt it
avif is the newer format so it's the one they predominantly use
Youโre saying adoption is the total destruction of jpeg and itโs not
googles image proxy encodes as avif by default iirc
Discord even on mobile uses webp for thumbnails 
jpeg is never dying out lol
Yeah
every consumer camera I know outputs jpeg
google photos does webp for 20px previews, and jpeg for everything else
because webp is too computationally expensive to allow on mobile
every phone automatically converts to jpeg when you try to use pictures taken in anything but the built in gallery
Theyโre moving to avif on pixels
It even has causes some peoples libraries to become corrupted
i think they are changing that on android with the whole HDR picture/screenshot thing, dont quote me on that, afaik its still WIP
yop
it really is, but w/e
but it really is
my consumer camera outputs avif sorry to say
my camera has option to save in HEIF
thats when you use their "compress your pictures and we'll give you infinite image storage" thing
My friends are super into photography and their cameras output raws and jpeg by default
because jpeg "just works" on everything
Hopefully eventually JpegXL not jpeg
I had to use this to save my storage
14.8 gb down to 4 gb
Do they even use 10 bit jpegs
google said they will never allow JXL in chromium
jpeg xl isn't ever happening unless chrome adopts it
Wrong. They made a compromise to wait for a rust rewrite
Look at the mailing list
Libjxl is too big and.. buggy
not even remotely close to its biggest problems
Memory consumption for encoding yes thatโs the biggest one /j
nope
consume my memory
What is it then oh great oracle
decode times, cpu times for decoding, repaints caused during decoding, long large contentful paint times
keep in mind they are targetting android 8 phones from india with e-waste for CPUs with 3G internet
Avif is only slightly faster than jpegxl and thatโs only 8bit avifs
Enter the domain of HDR and JpegXL starts to win or anything > 8bit really
JpegXL internally represents everything as fp32
hm i see the problem
you're back in your "lets debate the best format in the world" mode where u ignore all other parts of the conversation, where im saying "whats the most viale format for websites"
JXL is good, but its not a good fit for the web
Gif /j
Itโs good for artists and why safari has native support for it
JXL decode times are so bad, this exists as an option for google's image encoder
Itโs a library feature in libjxl and svt av1 has a similar feature called fast decode
The main problem why avif is faster is chroma sub sampling and unfortunately 444 isnโt supported in the main profile
yes
because my world is web development
your world is "my best media format in the world"
Itโs not. If it was then Iโd be talking about VVC 
Both avif and JpegXL have their place. Everyone on the chromium team agrees as well as almost every other person in web dev that actually knows a thing or two about image formats
yeah they do have their hyper specific use cases
Every person in web dev that knows their stuff agrees that png is the best image format sorry to say
never seen anyone actually use avif
So true
png does replace jpeg, its pretty much a back and forth
the both have the same support
jpeg isn't gonna go away for a long time probably never
jpeg is better for compression, png is better for high quality and well... alpha
yep, which is simply why google's attempt att making webp the default image format failed
15 years and only like 3 years ago did all browsers fully support it
oh I thought webp was newer than that
nah its 2010
I think?
yeah 2010
i remembered right
ff added support after 9 yeasr XD
safari after 12
nuts.
Cause Mozjpeg is or was better than webp
It never had a reason to exist
But unfortunately most people donโt use mozjpeg
Breaking: Google announces JPEG support ending in Chrome in 2026
saw the article yesterday but i forgot the link
it still has all the limitations of jpeg
Webp has more limitations than JPEG
what encoder u use doesnt matter
No 422 no 444
it could lick my balls for all i care
that really doesnt matter for web
like trully doesnt matter
it has alpha, animations and better compression ratios
so fuck cares
web isnt about lossless quality
For a 8bit 420 image mozjpeg is better than webp at sane quality levels. Itโs not a format limitation.
its about loading content quickly
there are heavy asterisks around that
sometimes yes sometimes no
more often than not, yes
When webp first release jpeg was still the winner
15 years later webp wins by 10%
In MOS rankings
Not 30-50 like google claimed
Fucking 10
This still holds true depending on who is looking at the images
Or what format itโs in
I donโt think 10% is worth adding webp support
webpiss
True.
I will keep using the browser on my Nintendo DS so the unknown can never adopt anything better than jpeg
Or IE6 in a vm works too
nice banner
stole*
@young flicker
@hoary sluice @deep mulch @royal nymph
where is elle
I love
@valid jetty I have funny idea im gonna make
@valid jetty IR data transmitter and receiver for transmitting files and whatever
add rust as a block somewhere on the side
just like off to the side
XD
isnt this gonna take like... hours?
like 4-10 kbps
with a 50% error rate
idk bro
nop
i estimate I can get maybe at least 50 kbps
with error checking and possibly correction
most true statement made this year
TIL you can do this in c
typedef struct {
Color color;
bool bold;
} SuperPrintOptions;
#define super_print(text, ...) _super_print(text, (SuperPrintOptions){ __VA_ARGS__ })
void _super_print(const char *text, SuperPrintOptions opt);
// somewhere in code...
super_print("hello world!", .bold = true, .color = Color_Green);
just like python
Yeah the C preprocessor is very powerful.
i never thought of this though...
or used varargs
i'm not a huge fan of macro magic
but this is cool
it's enough to confuse vscode though..
autocompletion doesn't work
one trick i found useful was this
#include <stdio.h>
#include <stdbool.h>
#include <stdarg.h>
typedef struct {
int value;
bool __last;
} Foo;
void _print_Foos(int _, ...) {
va_list args;
va_start(args, _);
for (;;) {
Foo foo = va_arg(args, Foo);
if (foo.__last) break;
printf("Foo { value = %d }\n", foo.value);
}
va_end(args);
}
#define print_Foos(...) _print_Foos(0, __VA_ARGS__, (Foo){ .value = 0, .__last = true })
int main() {
print_Foos((Foo){ .value = 3 }, (Foo){ .value = 5 });
print_Foos((Foo){ .value = -42 }, (Foo){ .value = 32 }, (Foo){ .value = 39 });
return 0;
}
only works for single typed structs
but pretty awesome
i mean yeah you can do that too
@valid jetty add // @ts-ignore to Elle
@valid jetty make coal
does the abs function in c give you abs
no need for vaargs...
thats boring..
fasterr
elle needs the fastest implementation
you dare imply that elle should not support wasm
you dare sugggest it to have worse compatibility?
yes
anyways won't matter when elle works for java applets and runs on the jvm 
@valid jetty Elle JVM NOW
Yeah this is why I love that languages like golang implement generics within their own LSP. Rust does as well
And native things like reflection
what is the proper way to store callbacks in rust
example of what i mean in c++
static std::vector<std::function<void()> callbacks;
void add_callback(std::function<void()> callback) {
callbacks.push_back(callback);
}
int start_thread() {
new std::thread([] {
while (true) {
// wait for something
for (const auto& cb : callbacks) {
cb();
}
}
});
}
fast math (only integer arithmetic)
rust statics seem to require unsafe to be mutable and i'd like to avoid that if possible
(if this can't be done in safe code then rust is insane)
why does it have to be static
just pass it around
A value which is initialized on the first access.
bad example
i have one background thread
a function from javascript adds a callback for when something changes
@jade stone ```rs
use std::sync::{LazyLock, Mutex};
static CALLBACKS: LazyLock<Mutex<Vec<Box<dyn Fn() + Send + Sync>>>> =
LazyLock::new(|| Mutex::new(Vec::new()));
fn do_x() {
let callbacks = CALLBACKS.lock().unwrap();
for callback in callbacks.iter() {
callback();
}
}
fn main() {
CALLBACKS.lock().unwrap().push(Box::new(|| println!("hello world!")));
CALLBACKS.lock().unwrap().push(Box::new(|| println!("hello sadan!")));
do_x();
}
its a LazyLock not LazyCell
but yeah
this is so fucking terrible to use because rust needs to make sure the things are thread safe
tysm

@jade stone you can also do this if youre sure your functions wont capture anything
use std::sync::{LazyLock, Mutex};
static CALLBACKS: LazyLock<Mutex<Vec<fn()>>> = LazyLock::new(|| Mutex::new(Vec::new()));
fn do_x() {
let callbacks = CALLBACKS.lock().unwrap();
for callback in callbacks.iter() {
callback();
}
}
fn main() {
CALLBACKS.lock().unwrap().push(|| println!("hello world!"));
CALLBACKS.lock().unwrap().push(|| println!("hello sadan!"));
do_x();
}
they're not rust functions, they're napi threadsafe_function s
so 
ill try it
fn() is just a function pointer, Box<dyn Fn()> is a capturing lambda trait item
then you can probably just have function pointers
ah so fn() is like void (*)() and Box<dyn Fn()> is like std::function<void()>
i guess so yeah
yeah thats exactly correct
Box<T> is what means "this heap allocates"
yeah i knew that
rust closures dont usually heap allocate, however since theyre being stored, their captures must live long enough and be sharable between threads sooo
and i assume Mutex is just an raii mutex wrapper
in normal sane code youd just see Fn(i32) -> i64 as a type
yeah
but i've never heard of lazylock
yeah
before rust had this, i did it like this
#[macro_export]
macro_rules! global {
($name:ident : $type:ty = $value:expr, $getter:ident) => {
pub static mut $name: Option<$type> = Some($value);
macro_rules! $getter {
() => {
unsafe { $name.unwrap() }
};
}
#[allow(unused)]
pub(crate) use $getter;
};
}
so just using unsafe lool

well i technically still do it like this
i didnt update yet
thats gonna be part of my migration to rust 2024
I did literally the same lol
i think i stole it from you โค๏ธ

ermmm this is actually unsafe and you shouldn't use static mutable globals
is it possible to get the value of the input to a match clause in the catch all branch without using a variable
something like this
status is a massive enum
that's why i said something like ...
i didn't know the exact syntax
what then
huh
communication
python is cool
ok
@jade stone you love rust
ssh froze
time to pull out the jetkvm
dont have
go reboot
guhhh
its in the middle of an upgrade
oh my god
literally every ssh session freezes after like 20 seconds
this is so annoying
@jade stone Warning: Repository 'http://atl.mirrors.clouvider.net/debian stable InRelease' changed its 'Version' value from '12.11' to '13.0'
Error: Repository 'http://atl.mirrors.clouvider.net/debian stable InRelease' changed its 'Codename' value from 'bookworm' to 'trixie'
XInternAtom(display, atom_name, False);
so much simpler
STOP TIMING OUT OMG
????
i dont get it
literally every time i ssh it freezes several seconds later
then im just stuck in this useless frozen ssh session
@jade stone why is it preferring the ipv6 for lan
?????
Which part is one line, ignoring the errors?
Antway it is one line in rust too conn.intern_atom()?.reply()?.atom
yop
if this errors you have serious issues
rust 
what's that font
do you use this unironically
Yes
I think I'd pay like $50 if someone made ligatures for it.
dumb

That's not what I mean 
It should retain the typedef in docs.
Type aliases often convey a lot of meaning in their names
typealiases are a very good way to self document code
.map(_).flatten() is better written.and_then()
As clippy points out
Why are you not running clippy
rust api suffers from perl syndrome ๐
whats perl syndrome
is flat_map .flatten().map()?
No, .map().flatten()
so and_then == flat_map???
It's called and_then on Result/Option/Future and flat_map on iterators
ohhh i see
Both are traditionally called >>=
that makes sense
you use this kind of font so you can get icons in fastfetch and whatever
And in nvim devicons, and powerline-style prompts
rosie dumb
he's referring to the fact it's comic sans
is it possible to modify and load plugins into discord web on firefox
like saving/loading plugins on local files and running themes in real-time
i need someone to talk about x86 instrinsics with
mostly optimizing codesize
rather than performance
you can create functions in css
is it weird that i'm wishing rust had templates
??
like with duck typing like c++
a library i'm using has two types which happen to have the same methods but it's not shared with a trait

rust needs templates
template <typename T>
fn quack(duck: T) {
duck.quack();
}
You could also try writing code that doesn't suck
fn quack<T: Duck>(duck: &T) {
duck.quack();
}
?
that function won't automatically support any type that has a method called quack though
Yep, because function names mean nothing
What would you do if someone passes you a Doctor, which also is a quack?
solution: make function names as descriptive as possible
put the whole function body as the name
I think Duck::quack is a very descriptive name
with illegal chars replaced
are you a java dev
wait i guess rust allows you to implement triats for foreign types
a feature i'm not too fond of but oh well...
That's one of traits' biggest advantages over interfaces
I like C++ templates more
it does but it also does in a way where it shouldnt break stuff (needing to have the trait in scope to access the functions)
Like idk how would you express this in rust
yeah it's a good implementation
are templates not basically just generics
With traits
i just... basically everything about go aligns with my opinions and go doesn't have this xd

go is always right
impl Deserialize for BaseChannel
impl<K, V> Deserialize for QMap<K, V>
``` etc
if it quacks like a duck...
But there is nothing in that code that asks for quacks like a duck
It only asks for quacks
Unfortunately it turns into spam of trait Deserialize for X for everything and where
runtime error
no biggie
Glad i can have magic like complete math at compile-time
Better than a giant elseif
real answer: the return type is important too
let quack: Quack = doctor.quack()
quacks like a duck 
if quack returns something im blowing something else up i expect that to directly print to stdout if it does anything else someone will die
what do you think about destructors
ok i guess they're cool...
I LOVE DUCK TYPNG
look at this
fn Iterator::flat_map<T, U, AnyEnded>(Iterator<T, AnyEnded> self, fn(T) -> U cb) {
return self
.map(cb)
.map(fn(x) x.__iter__())
.reduce(fn(acc, it) acc.chain(it))
.unwrap_or_else(fn() Iterator::empty());
}
if it wasnt duck typed, x.__iter__ would NEED to return Iterator<U, ???>
however if youre returning something like a hashmap, the result is Iterator<(T, U), ???>
its helpful to have duck typing in some cases







