[HN Gopher] 4x Smaller, 50x Faster
___________________________________________________________________
4x Smaller, 50x Faster
Author : pama
Score : 705 points
Date : 2021-11-30 01:40 UTC (21 hours ago)
(HTM) web link (blog.asciinema.org)
(TXT) w3m dump (blog.asciinema.org)
| w-m wrote:
| The blog post mentions that seeking to any point works very well
| without having to create keyframes, just from the speed of the
| implementation. It would be great if the progress bar could
| actually respond to click-and-drag events, to quickly find a
| specific location.
| Tobu wrote:
| Scrubbing would be fun, I agree!
| iveqy wrote:
| This makes me worry less about the end of Mores law. It's clear
| that software development still has a long way to go.
| ajaxexact wrote:
| > ClojureScript is not that easy to integrate with the JS
| ecosystem. I know, there's been a lot of improvements done in
| this space over the years, and I'm sure someone will immediately
| point me to relevant docs, but it's still the extra mile you need
| to go when compared to regular JS codebase
|
| This always kills me. Clojure(script) is one of the neatest
| languages I've ever used, but it is just such a pain to work
| with. I spent hours getting NPM imports working in a project,
| when it ought to take seconds. It really makes it hard to
| recommend, even though the language itself is amazing.
| Cthulhu_ wrote:
| I just wonder why not just write straight JS? Adding a layer on
| top just means you have more complexities and steps to worry
| about. And clearly, in this case it was a big compromise in
| terms of performance and bundle size.
| keymone wrote:
| You'd have to torture me before I would make a conscious
| choice to pick JS over Clojure.
| michaelcampbell wrote:
| It sounds like that's exactly what happened to the GP.
| keymone wrote:
| GP didn't pick JS for a rewrite either, so yes, I'm
| pretty sure GP is with me on that.
| Scarbutt wrote:
| Yep, the author learnt their lesson. I bet they won't be
| using cljs again, not even for non-performant apps.
| jaxn wrote:
| I have also spent hours getting npm packages to work in JS
| before.
| nojito wrote:
| Fable is becoming the best way to compile to JS.
|
| https://fable.io/
| cunthorpe wrote:
| Maybe it's just me, but I don't think showing a string on screen
| requires React or any other view library.
|
| I'd probably paint it on canvas and then overlay an invisible
| plaintext node to allow selection.
| eatonphil wrote:
| If you made a library that does this I'm sure it would be
| welcome competition!
| Cthulhu_ wrote:
| Yeah but how can you quickly re-render the plaintext node in
| sync with the canvas? How are you doing font rendering? How are
| you handling things like accessibility and interactive
| controls?
|
| I feel like you may not be seeing the whole picture / problem
| domain.
| stjohnswarts wrote:
| People work with what they know and I'm sure they'd love to see
| a similar implementation done with the method you suggest. It's
| open source and hugs and thumbs up all around here :)
| winstonewert wrote:
| But that just means you have to manage both the text (what
| React/SolidJS are already doing) and a canvas, which means your
| twice the work for no good reason.
| sickill wrote:
| The player has other UI parts, mainly the control bar with
| current time, progress/seek bar, full-screen toggle etc. Of
| course it could be built with plain JS but a small library like
| Solid.js does the job well.
|
| The terminal lines with (colored) text definitely don't need a
| view library if you just want to display it, true. Canvas would
| be way more efficient here, and it's not out of the question
| for the terminal part in the future. One thing that using DOM
| (spans here) gives for free is copy-paste. Like you mentioned
| it could be solved by overlaying a text element on top of
| canvas (on mousedown, or when paused) or custom implementing
| copy-paste for canvas with mousedown/mousemove/mouseup, but
| that's all extra work, and as I mentioned in the blog terminal
| emulation was the bottleneck, not rendering.
| atoav wrote:
| While I applaude the engineering effort that went into the
| project, I really dislike documentation that uses asciinema for
| regular non-interactive CLI interfaces: instead of showing me the
| commands in an overview I have to sit through the whole thing.
| rodamaral wrote:
| asciinema is for showing off, specially TUI interfaces.
| Cthulhu_ wrote:
| It's fine for a quick demo of a CLI application, but
| documentation and usage instructions should follow.
| hnarn wrote:
| Documentation does not belong in asciinema. It's for
| presentation, and using it as an excuse not to document is pure
| laziness.
| tomxor wrote:
| Those same authors would probably have used a youtube video
| instead, so asciinema's existence is not the cause of this.
| qwertox wrote:
| It's a lean-back experience, like the difference between a book
| and a video. It does have its perks.
| vladvasiliu wrote:
| I think it can work well as a demo, but I wouldn't call that
| _documentation_.
|
| If you need to find something out, having to wait or randomly
| click through a video is extremely frustrating.
| omnicognate wrote:
| Ew, people are using it for docs? It always seemed clearly
| to be for those quick-look demos on projects' home pages,
| and it's fantastic for that.
| ReleaseCandidat wrote:
| What exactly is the advantage of asciinema over a video
| or a GIF if you're just showing something? If I don't
| need to copy text out of it, it has the same function as
| a video.
| omnicognate wrote:
| It's rendered by your browser so you get properly
| subpixel-hinted text instead of the horrible, blurry,
| compressed screenshot effect a video or gif gives. Also
| it's more convenient to generate than faffing around with
| screencasting software.
|
| Edit: well, not (lossily) compressed in the case of a gif
| but not as nice as text properly rendered for your
| display.
| qwertox wrote:
| I'd guess it's the bandwidth and compared to a GIF, you
| can pause them. While it's not usual to copy text from
| it, I've done that once this month and thought it was
| neat to be able to do that. I do believe that they have
| an advantage over video/GIF.
| 1_player wrote:
| It's definitely better than a GIF because you can seek
| forward. You never know when a GIF ends, and if you're
| distracted, you have to wait for it to loop back again.
| dredmorbius wrote:
| Note that this is a function of the GIF viewer. An image
| / video viewer that can play GIFs with length, speed, and
| movement controls would afford this.
|
| vlc seems to do this (Android version).
|
| I'll grant that the _usual_ methods of interacting with
| GIFs _don 't_ do this, and am not arguing that they do.
| But if you really want a specific functionality, you can
| look for a tool which might provide that.
| nyanpasu64 wrote:
| Asciinema is used for docs-ish in git-branchless's
| readme: https://github.com/arxanas/git-
| branchless/blob/master/README...
|
| It does have formal docs, but I didn't fully understand
| the program after reading them. I didn't enjoy sitting
| through branchless's videos or clicking around for the
| right point in time.
| vidarh wrote:
| If it's a video, it does noe exist for me. I _could_ watch
| them, but I have better things to watch if I want to watch
| something. So I move on to something else.
| EdwardDiego wrote:
| Most of us read far faster than someone umming and ahing
| through a presentation in a monotone can speak.
|
| At the very least, give us a frigging transcript.
| atoav wrote:
| It has, if the thing you are showing fits the media. If you
| show the different flags of ls without explaination you would
| be better of just showing me the printout of ls -h
|
| If you are showing off some beautiful TLI, an interactive
| prompt or ascii animations, this is the perfect tool.
|
| As someone who works in film: film also doesn't lend itself
| to everything. Certain internal observations that work great
| in literature would be unwatchable on film etc.
|
| Or to take it to the extreme: you don't expect the overview
| of an database to be experimental performance video art.
| ReleaseCandidat wrote:
| > If you are showing off some beautiful TLI, an interactive
| prompt or ascii animations, this is the perfect tool.
|
| If you want to just show something off, a GIF (or real
| video) is the answer.
|
| The defining feature of asciinema is that you can copy the
| text out of the animation. Which is actually not that
| useful most of the time, because you can't search for text
| in asciinema (AFAIK?) like you can in, well, documentation.
| uasi wrote:
| > a GIF (or real video) is the answer.
|
| Why so? You can't pause or seek GIFs. GIFs and video
| files are usually several times larger than asciinema
| recordings of the same content. And you can't copy text
| out of them when it is useful.
| RMPR wrote:
| Reposting here since the first submission didn't make it to the
| frontpage
|
| I started using asciinema two months ago and I must say that it's
| excellent! One minor annoyance though, it forces the use of the
| default shell instead of using the shell you launched it in.
| Other than that I am very excited by this release, more speed is
| always welcome.
| sickill wrote:
| It does try to launch the same shell as your current one by
| looking at SHELL env variable, and only falls back to sh if
| it's not there. See:
| https://github.com/asciinema/asciinema/blob/9ccf4efd4d3babc4...
| It seems that's not the most reliable method.
| MrYellowP wrote:
| Reading through the comments and as an assembly programmer, I
| think this whole topic is completely bonkers.
| genuine_smiles wrote:
| Why?
| [deleted]
| 71a54xd wrote:
| Asciinema server is still quite frankly my favorite Elixir
| Phoenix project of all time.
|
| https://github.com/asciinema/asciinema-server
| sickill wrote:
| Oh wow, thank you! Frankly I'm the least proud of it, as it's
| been my first Elixir/Phoenix project and there's many things
| I'd have written differently today, especially after spending
| last 4 years writing Elixir at work. But time will hopefuly
| come to bring more love to it too :)
| fnordsensei wrote:
| As an enthusiastic Clojure/Script user, the new tech stack
| absolutely makes sense for this application.
|
| For the decrease in size, I expect most of the gain to come from
| dropping ClojureScript. For the speed increase, though, I expect
| most of the gain to come from WASM. JS and ClojureScript are
| within the same margin of error compared to the performance that
| can be achieved with WASM.
| badestrand wrote:
| > Due to ClojureScript's immutable data structures, there's a
| lot of objects created and garbage collected all the time
|
| ^ From the article, sounds like a plausible cause for the speed
| difference.
| fnordsensei wrote:
| It's almost certainly part of it. I doubt that a
| ClojureScript application written mutably (which you can do)
| would compare favorably to WASM regardless.
| sickill wrote:
| Before attempting JS/Rust rewrite I tried using transients
| [0]. I converted small part of the vt code to use mutable
| data structures to see if it's giving any improvements. It
| barely did, the difference was negligible. I believe it was
| because I didn't go all the way, so the perf critical
| pieces deep down were still using immutable data
| structures. Maybe it would bring decent improvement if I
| converted most of the vt code to transients, but it would
| absolutely destroy the idiomatic aspect of the code, and
| even then it would never compete with Rust anyway.
|
| [0] https://clojure.org/reference/transients
| fnordsensei wrote:
| I get that. And then you'd have to find a way to get rid
| of React (and Reagent/whatever was used on top of it) to
| get it all the way to as lean as possible. At this point,
| you'd be leveraging almost nothing that ClojureScript
| brings to the table, while getting most of the cons.
| sickill wrote:
| Spot on.
| qwertygnu wrote:
| Went to https://asciinema.org/ and clicked the demo video. I'm a
| bit confused because it looks like future lines are being
| rendered after the cursor while lines are being typed. Is
| that...correct? It looks like either a blatant bug in their
| product (that they're displaying on their homescreen demo!) or on
| purpose for some reason I can't find.
| sickill wrote:
| Feel free to report a bug here
| https://github.com/asciinema/asciinema-player/issues/new
| (including browser version, OS would help a lot).
|
| Btw, it's not a product, just a side, hobby project of mine.
| nawgz wrote:
| You made me click through, and I could not recreate. Is this
| the new viral marketing? I truly just was reverse psychology'd
| moonchrome wrote:
| It's funny how it starts out with "immutability is really fast
| and GCs are soo good" and ends up with "rewriting everything in
| unmanaged code made it 50x faster".
|
| Similar how "Ruby and Python interpreters are slow but webapps
| are IO bound anyway so it doesn't matter" to "how can I get this
| to handle more than x req/sec, can we get a JIT to speed up our
| dog slow backend".
| smrtinsert wrote:
| It's almost like one side had the ability to say "we told you
| so" and they never bothered to :)
| aasasd wrote:
| > _" Ruby and Python interpreters are slow but webapps are IO
| bound anyway so it doesn't matter" to "how can I get this to
| handle more than x req/sec, can we get a JIT to speed up our
| dog slow backend"_
|
| Turns out that if you write business logic with abandon, you
| end up with a lot of business logic.
|
| Personally I wish that Python, Ruby and the ilk all get
| replaced with Lua, but also that Lua gets a proper `null`.
| seniorivn wrote:
| and array numbering from zero
| mmastrac wrote:
| This is why I've never been able to do anything serious
| with Lua. Small thing, but fatal for me.
| ryansolid wrote:
| It's awesome to see performance-oriented projects to find their
| way to SolidJS(https://www.solidjs.com). So satisfying to see
| success stories like this one. Great work.
| eatonphil wrote:
| Congrats! One nit I have about SolidJS documentation is that it
| doesn't have a clear path for "migrating from React" which I
| take it is probably actually important to you given how similar
| SolidJS looks to React and how much faster it claims to be.
| Also might be good to include a section on how to interop with
| existing React libraries -- even if the answer is that you
| can't.
|
| And it might be worth putting in your HN profile that you are
| the creator of SolidJS. :)
| ryansolid wrote:
| Yeah it is sort of buried and probably not very clear:
| https://www.solidjs.com/guide#react.
|
| And good point thank you about updating my profile.
| sickill wrote:
| Thanks Ryan! And thanks again for your work on Solid.js.
| aidos wrote:
| I've been keeping an eye on your work for a long time now.
| We're a mobx shop so I was hoping to see you explore the ideas
| you had around that a little more
| (https://github.com/ryansolid/mobx-jsx).
|
| I like and know where I'm at with React, but bringing a
| beginner through it recently definitely made me re-appreciate
| how nuanced it is. Also, you have to do a bit of voodoo to get
| good performance, and when you do the intention of the code
| vanishes pretty quickly.
|
| For someone using React on top and mobx stores in the
| background (say 50k LOC all in), how big of a task would you
| say it is to move to something like Solid?
| ano88888 wrote:
| congrats on the performance. But I just hope that React will
| quickly catch up and improve in terms of speed & performance.
| It is really tough to learn a new framework every few months.
| ryansolid wrote:
| It's unlikely. Solid has had this performance profile since
| 2017. React hasn't really budged. Fundamentally different
| approach. There are different types of performance to explore
| but raw performance for small things is not something React
| is going to "catch up" on. Might be worth a read:
| https://javascript.plainenglish.io/javascript-frameworks-
| per...
| austincheney wrote:
| Not going to happen. The key difference: virtual DOM.
| laurent92 wrote:
| I hope React won't have all of those gotchas which make a
| good year of experience necessary when training a junior,
| until he migrates to a job that pays for his upgraded
| skills... Cost of skills is a thing.
| skrebbel wrote:
| Wow, I just read about Solid for the first time, and I'm very
| impressed at the API design. I love how it's actually a fully
| reactive data flow thing, but it looks and feels like React
| Hooks.
|
| The other reactive/observable-based frameworks I've seen (eg
| Cycle) very much put the observable streams center piece, and I
| always felt that was distracting, and that nuances about how
| the underlying observable stream library worked quickly got in
| the way.
|
| Solid still puts the components firmly at the center, just like
| React, but replaces React's state concept by fully reactive
| observable state, called "signals". You use them pretty much
| like you useState in React, but deep inside it's an observable
| stream of changing data, and you get all the finegrained update
| control that comes with that.
|
| Also, I love how noun-heavy it is. Resources, tracking scopes,
| effects, signals. It's just like how React moved from "do this
| thing after the component updated" to "ok we have this concept
| called an effect", but extended to more topics such as dealing
| with async data loading, when exactly a signal is observable,
| etc.
| com2kid wrote:
| > but it looks and feels like React Hooks.
|
| I am confused about why this is a positive.
|
| React Hooks are the reason why I want to stop using React.
| They are confusing and seemingly magical, compared to
| lifecycle methods that make a ton of sense. While I agree
| they can make complex things easier, they are also incredibly
| easy to get wrong, as they are order dependent.
|
| Reading the Solid landing page, what I see is "Solid takes
| the most confusing part of React, and runs with it."
| kevincox wrote:
| I'm struggling to find out how it actually updates the DOM. The
| way that re-rendering happens is clear but it looks like the
| top-level function just returns a JSX.Element. There is no
| explanation how this is efficiently rendered.
|
| Also how are mid-level invalidations handled? For example if I
| update a list to remove one element do the other elements get
| re-rendered or are they cached?
|
| It might be because I am browsing the docs in mobile but I find
| them hard to navigate.
| lxe wrote:
| The immutable hype is finally fading. People starting to realize
| the drawbacks of treating hardware as an infinite resource.
| bsg75 wrote:
| What is the connection between mutability and excessive
| hardware usage?
| cjcampbell wrote:
| As an oversimplified example, in using an immutable screen
| buffer, a change between frames results in allocation of a
| full buffer rather than overwriting memory within the buffer
| (though one could probably think of ways to optimize this for
| the use case). Excess comes either in the form of unnecessary
| (relative to mutable) memory usage and/or CPU cycles
| necessary to support high-levels of garbage collection.
| knubie wrote:
| > in using an immutable screen buffer, a change between
| frames results in allocation of a _full buffer_ rather than
| overwriting memory within the buffer
|
| That's actually not how clojure's immutable data structures
| work. They use structural sharing, so only the portion that
| changes (roughly) needs new memory allocated, and only the
| parts that changed get garbage collected, so it is a bit
| more efficient than that.
| ben-schaaf wrote:
| You can't deallocate part of a frame buffer, it's a
| single allocation. Unless every pixel is individually
| allocated, which would clearly be insane.
| knubie wrote:
| I'm explaining how clojure's data structures are
| different from OP's screen buffer example.
| __s wrote:
| But if your frame buffer is text, you can store the text
| in a rope data structure like JS vms do
|
| So you don't necessarily have an allocation for every
| single character, but you're still able to share memory
| between buffers
|
| I've implemented a game engine with immutability (makes
| for fast cloning in AI search) where much of the game
| state is shared between clones. With reference counting
| it also means if there's a unique reference being
| modified then no copy is made. This same trick is used by
| Python to optimize string concatenation
| peoplefromibiza wrote:
| that's only because js is "stupid"
|
| if you have the string "hello" and somewhere else "hello
| world" you can retain only one copy of "hello" because it's
| guaranteed it won't change.
|
| but js vm it's not smart enough for that.
| __s wrote:
| You're wrong, JS has immutable strings & so VMs use ropes
| to make mutable usage & slicing fast
|
| https://gist.github.com/mraleph/3397008
| https://twitter.com/rauschma/status/1269964154275799041
| peoplefromibiza wrote:
| thanks
|
| my bad, I learned something new.
|
| anyway this proves that immutable data structures are not
| inherently slow, this is infact an optimization that
| makes things faster.
| rektide wrote:
| mutability is a data structuring virtualization but i'd just as
| much suspect the runtime virtualization.
|
| that the bundle used to be 570kB isnt an immutability issue.
| itcs that clojurescript drags in a whole clojure runtime, a new
| virtualization layer atop the js runtime. that, to me, is the
| most likely suspect.
|
| that said, for sure, short tbeow away high gc allocation
| patterns are generally not good. at work there's a lot of
| "functional" patterns, nary a for loop in sight. this endless
| .map() .filter() usage causes near exactly similar issues, with
| shortived objects. it seems ultra sad & silly to me. waste
| after waste. but i also think we have much more deeply rooted
| problems.
| jdlshore wrote:
| Are you sure about the short-lived allocations being a
| problem for the collector? My understanding of modern
| generational garbage collectors was that they performed quite
| well with short-lived garbage. Not as well as not creating
| the garbage in the first place, of course, but not so badly
| as to be a problem in most cases.
| meheleventyone wrote:
| This is true for small amounts of garbage but not for large
| amounts which is still slow and large is relative to the
| hardware your user is running on. It'll also cause a death
| by a thousand cuts where it's extremely difficult to dig
| yourself out of poor performance because the cause runs
| throughout the program.
|
| It's better to look at cheap short lived collection as a
| great way to get the thing you're making working but
| ultimately something that needs to be cleaned up to be
| production ready.
| ncmncm wrote:
| "Perform quite well" is always relative to some reference.
| The oldest trick in the book is comparing to something
| _even slower_ and saying "see? fast!".
|
| GC apologists seek to normalize this behavior. They often
| succeed, at that. Performing _quite well_ against actually
| fast things, less often.
| jdlshore wrote:
| You seem to have an axe to grind.
|
| Performance isn't black and white. Optimizing your memory
| usage isn't going to do you a whit of good if you're
| constrained by your database queries. Optimizing your DB
| queries isn't going to do you any good if you're
| constrained by a chatty microservice architecture.
| Optimizing your UI response time isn't going to do you
| any good if you're already below the threshold of
| perceived speed. Etc.
|
| GC performance on short-lived objects is quite good in
| enough situations to matter, such that optimizing for it,
| rather than your application architecture, is likely
| foolish outside of performance sensitive loops.
|
| Time is always limited. Spending your optimization budget
| on micro-optimizations is short-sighted.
| ncmncm wrote:
| Meaningless personal criticisms undermine your argument.
|
| Performance problems usually appear in places we prefer
| they would not, often runtime apparatus we poorly control
| such as GC. It is always preferable to try to ignore and
| discount those, as they may be arbitrarily hard to fix,
| so people do.
|
| Yet, actually not depending on such apparatus, where it
| is the problem, gets you free optimization.
|
| Performance doesn't care where it is found or lost.
| Micro-optimization is foundational; fail there, and there
| is often little else you can usefully do. The best
| optimizations are not doing the thing at all. GC is
| always strictly worse than no memory management.
|
| Fixing your chatty microservoices and your under- or
| over-indexed DB queries may do you no good if you have
| built in bottlenecks of your own.
|
| "Quite good" means nothing except in comparison to
| something else.
| nyanpasu64 wrote:
| I want a world without garbage collection. I don't think
| we can achieve a world without garbage collection while
| there are codebases based around aliased pointers (which
| makes lifetime reasoning difficult, and causes enough
| use-after-frees to make the Linux desktop apps I use
| unstable, unless you use refcounting) and circular
| references (which is difficult to refcount). Maybe I'll
| wait for Rust programmers to rewrite software around
| tree-based ownership (restrictive but immune to these
| problems) and ECS/arena indexes (can use-after-free but
| won't segfault).
|
| In the time being, while "spiderweb object graphs" are
| commonplace, perhaps Nim's memory management
| (https://nim-lang.org/docs/gc.html) can give us "non-GC
| by default, refcounting or GC when necessary". I want it
| to succeed. I hope it does.
| cryptonector wrote:
| Immutability is a drag if you create lots and lots of
| _referenced_ state because, e.g., you want to hold on to many
| snapshots of past state.
|
| Immutability done right need not be much worse than
| mutability.
|
| For example, jq's internal value representation is immutable
| in appearance:
|
| - mutations yield new values,
|
| - but when the value being "mutated" has only one extant
| reference then mutation is done in-place,
|
| - while when the value being "mutated" has more than one
| extant reference then mutation is done by copy-on-write.
|
| If you manage to always have extra references, then
| "immutable mutation" gets expensive.
|
| If you manage hold on to old references for a long time, then
| "immutable mutation" gets even more expensive.
|
| In a run-time with a GC not based on reference counting you
| do have to GC all the intermediate garbage.
|
| Immutable data structures really lend themselves well to
| reference counting GCs because you can't have cycles in
| immutable data.
| cryptonector wrote:
| I should add that reference counting GCs are nice because
| short-lived garbage is freed immediately and there's no
| need to look for garbage, so they're much faster than
| scanning GCs. Reference counting GCs can have GC-like
| pauses when releasing objects that have singular references
| to many many many other objects, but the same is true in
| manual memory management systems.
| fnordsensei wrote:
| > Immutability is a drag if you create lots and lots of
| referenced state because, e.g., you want to hold on to many
| snapshots of past state.
|
| Isn't it the opposite? If you want to hold on to many
| referenced states at the same time, an immutable data
| structure should provide less overhead than a mutable one,
| due to structural sharing.
| cryptonector wrote:
| A performance drag. Let's say you have an app that for N
| inputs creates N^2 state in memory...
|
| But now, if that's just what you must do for some reason,
| then, yes, immutability makes the task of taking all
| those snapshots real easy.
| casion wrote:
| Clojure solves these issues with unneeded garbage creation in
| algorithms with the transducers functions.
|
| And you can of course just use java objects whenever you
| want.
| rtpg wrote:
| What a boring takeaway from this. Beyond the fact that the
| immutable data structures proposed by Clojure/script tend to
| perform very well in a lot of "normal" cases (and in a lot of
| normal web-app workflows your stuff is immutable, like "query
| then display the result from an API"), at least to me it feels
| like asciinema is a very good example of a case where you have
| tougher-than-average performance requirements.
|
| Not to say that we shouldn't have "everything be performant"
| but drawing a bunch of stuff to screens is _the classic_
| performance question. Whereas most "business apps" people here
| work on to a day-to-day have different performance issues.
|
| Rewriting your CRUD frontend in Rust isn't going to make your
| DB queries faster
| ncmncm wrote:
| Won't make them slower, anyway.
|
| There are often performance bottlenecks you didn't know
| about, and had blamed on database (or whatever) interaction
| overhead. It will never feel worthwhile to dig into each
| candidate, because any payback seems too unlikely. Not having
| left scope for such bottlenecks means you can be confident
| they are not there. Re-implementing once is a lot less work
| than diving into each possible bottleneck. Improving your
| actual database operations, after, is more likely to have an
| effect when some other bottleneck doesn't mask the
| improvement.
|
| You don't have to do it in Rust. Any optimization you could
| do in Rust is probably easier in C++, and also easier to find
| maintainers for.
| Ar-Curunir wrote:
| > Any optimization you could do in Rust is probably easier
| in C++, and also easier to find maintainers for.
|
| At least the first part is not necessarily true. E.g., in
| C++, you might make defensive copies, whereas in Rust the
| lifetime system will track things for you.
| ncmncm wrote:
| Thus, "probably".
| paulgdp wrote:
| "Any optimization you could do in Rust is probably easier
| in C++"
|
| I think this feeling comes from the fact that it takes
| longer to learn the basics of Rust compared to C++.
|
| However, once one has learned C++ or Rust to a reasonable
| level, I would argue that Rust is actually easier to use.
|
| This is not the same thing but many people make this claim.
| ncmncm wrote:
| Each is easier than the other, depending on where you
| look and where you come from.
|
| But it is a fair bet that changes to C++ code to
| implement a point performance optimization will be
| smaller than the same sort of change would be for Rust
| code. For the latter, you are likely to need to re-
| architect that part of the system some to get your
| optimization and still satisfy the borrow checker. Having
| a borrow checker that demands satisfaction is a virtue,
| but there is no denying it adds cost in the small, where
| we're talking about, notwithstanding that such cost may
| be paid back at the system level.
| pohl wrote:
| > Any optimization you could do in Rust is probably easier
| in C++
|
| That's kind of funny in light of the history that certain
| optimizations in web layout engines were attempted,
| unsuccessfully, in C++ multiple times and ultimately they
| invented Rust to make them easier.
| ncmncm wrote:
| That is how the marketing goes, anyway.
|
| The facts on the ground probably have more to do with
| improvements to the C++ code being obliged work as deltas
| against existing C++ code, where the Rust code was a
| complete re-implementation, thus not constrained.
|
| Both C++ and Rust are today different languages from when
| that project ran.
| hedora wrote:
| > _Rewriting your CRUD frontend in Rust isn 't going to make
| your DB queries faster_
|
| A typical consumer disk can do 1,000,000 IOPS (enterprise is
| one generation behind, and slower at the moment), with
| millisecond read and write latencies.
|
| Are there any managed CRUD frontend languages that are fast
| enough to keep up with that?
|
| (By "keep up", I mean "be less than half the hardware I
| provision at scale")
| niels_bom wrote:
| This talk by Richard Feldman about Roc (a new language) goed
| into why immutable does not necessarily mean slow and given
| enough attention can mean higher performance in certain cases:
| https://youtu.be/vzfy4EKwG_Y
| legulere wrote:
| The benefits of immutability are still there though. You should
| generally design immutable by default and use mutability for
| performance where it matters.
|
| Rust which was used here also has immutability by default and
| mutability is an explicit opt-in.
| mping wrote:
| Well the immutability hype allowed the author to build the
| previous incantions of the library. At this point, I hoped
| everyone understood the tradeoffs of using abstractions.
| Otherwise we should all be programming on assembly.
| zupa-hu wrote:
| This. If the project was reimplemented in assembly, it would
| be faster and smaller and the same conclusion could be drawn:
| "finally the high level programming hype is over".
|
| come on..
| [deleted]
| azakai wrote:
| This article doesn't really support that. ClosureScript targets
| JavaScript, which is a platform that doesn't have special
| support for optimizing immutability.
| notacoward wrote:
| How would one optimize for immutability in this case, other
| than turning it back into mutability behind the scenes? I've
| certainly seem some code written in an "immutable" style
| where it was pretty clear that the intent was for one data
| structure to be a mutation of another, just called something
| else because the language required it. That case might be
| easy to optimize ... but the general case?
| kevin_thibedeau wrote:
| Pretty bog standard behavior for a compiler backend
| translating immutables in IR. Including a runtime compiler
| into app code is the next stage in the evolution of cycle
| burning leetness.
| azakai wrote:
| I'm not an expert on this, but one example is that
| immutability lets you operate safely on things in parallel.
| But JS VMs are not aware of objects that are immutable in
| Clojure's semantics, and in any case, do not operate on
| objects in parallel anyhow.
| fulafel wrote:
| Generally in compiler technology, immutability is an
| important tool in letting compilers reason about and make
| program transformations. See eg the "single static
| assignment" intermediate-representation form that is
| mainstream in low level language compilers. But SSA form
| isn't as good as having the original program expressed
| immutably, because you get false or incidental data
| dependencies if the compiler has to conservatively derive
| the optimization-friendly SSA representation out of the
| original non-immutable code.
|
| In practice a JS implementation that had special
| optimizations for code using immutability as a convention
| might for example auto-parallelize code.
|
| Also it by no means a bad thing if a compiler turns a piece
| of easy to reason about functional code "back" to generated
| code that exploits local mutability behind the scenes in
| some circumstances, that's exactly how we want it to work.
| We still get the robustness guarantees of semantics where
| our objects don't change from under us in programmer
| visible ways.
| gpderetta wrote:
| Talking about parallelization opportunities is a bit
| pointless when you need 50 cores to match the performance
| of the single threaded code (in the best case, assuming
| perfect scaling).
| hedora wrote:
| These techniques are also applied by compilers such as
| clang.
| azakai wrote:
| Fair enough, but parallelism isn't just about cores since
| SIMD can also help. Also, immutability doesn't just help
| through parallelism, it also allows other things (as
| another example, avoiding redundant work like loads of an
| immutable field and computations on them).
|
| Would that help with a huge 50x difference? Maybe not,
| but the point is that evaluating the benefits of
| immutability on a VM that does not optimize it - JS VMs -
| is not relevant. (And that 50x might also be caused by
| other limitations of JS VMs and not immutability at all,
| like say deopts.)
| fulafel wrote:
| I disagree - lots of compiler work is done on languages
| that aren't best in class for high performance work. Look
| at all the effort that people are putting into making
| Python faster. And indeed JS itself, it wasn't always
| this fast. High level language users live by "There's
| more to life than increasing its speed" and then if they
| take off, people come work on performance and make them
| faster.
|
| Also let's not forget that this was already "fast enough"
| for a long time before the 50x rewrite.
| gpderetta wrote:
| My issue was specifically with the claim that persistent
| data structures are great for parallelization.
|
| I have absolutely no issues with efforts to improve
| single threaded performance of programming languages (and
| indeed the advances made by JS are remarkable) and I
| don't believe any language needs to be "As Fast As Cee".
| But There are other perfectly reasonable languages that
| are within a small integer factor of C and C++. You do
| not need to pay a large penalty for ergonomics.
| memco wrote:
| > How would one optimize for immutability in this case,
| other than turning it back into mutability behind the
| scenes?
|
| Roc-lang, which is a functional, systems language in
| development uses something called opportunistic in-place
| mutation to do just that. Here's a video where the creator
| talks about it: https://youtu.be/vzfy4EKwG_Y?t=1276
| peoplefromibiza wrote:
| or maybe is JavaScript hype and the make concurrent programming
| impossible that it's finally dying.
|
| Immutability is alive and well, it's simply a matter of js
| runtime not supporting it, because the developers thought "one
| thread ought be enough for anybody".
| notacoward wrote:
| This part...
|
| > for the high frame-rate, heavy animations this puts a lot of
| pressure on CPU and memory
|
| ...does seem to suggest that the "garbage multiplier" effect of
| immutability is an ill fit for applications that also create a
| lot of garbage naturally. Note that this is about as close to
| an apples-to-apples comparison as we're likely to get - the
| _same application_ implemented two different ways - so it 's
| not the application's innate object-lifetime characteristics
| that are the problem. That's an implementation artifact.
|
| The question is: how many applications are likely to hit this
| same limit? Is this a rare case, or is it common? If it's
| common, it is indeed an indictment of the "immutable" approach.
| Otherwise, not so much.
| xyzzy123 wrote:
| I've always thought of immutability as great for situations
| where you want to "explore" (clone complex current state and
| go do some "what if"), need internal transactions, or allow
| time travel (snapshot/undo/redo) - situations where the state
| sharing is both efficient and feels "natural".
|
| Also if the data/history are relatively small compared to the
| available memory it's a fine default that generally leads to
| "nicer" code.
|
| Video doesn't seem at first glance like such a great fit.
| kccqzy wrote:
| Video can be played backwards and forwards, can be sought,
| or jumped to a particular point in time. It fits well with
| the "time travel" benefit of immutable data structure. The
| author mentioned it was extremely easy to implement some
| kind of a checkpoint or key framing with immutability.
| That's exactly using immutability to its strength.
| titzer wrote:
| The downside of immutability is the sheer volume of data
| (in the form of pixels) that needs to be pushed around. A
| single 4k frame is 8.3 million pixels, so you are looking
| at over 30MiB of data for 32-bit color, and you gotta
| push 30, maybe 60 of those a second. Maybe if you have a
| really good garbage collector (or a custom one, because
| frames are all the same size) you can get away with
| allocating that much data and freeing it every second.
| But that doesn't free you from the fact that you are not
| utilizing hardware caches well; you don't get good
| spatial locality at the hardware level unless you reuse
| the same physical pages of memory for every frame. And
| you can basically only do that if you have a mutable
| design.
| sickill wrote:
| That's not how asciinema-player works though. The player
| internally represents the terminal buffer as a grid of
| characters. So for 80x24 terminal you have 80*24=1920
| grid cells, each keeping a unicode char + color attrs.
| When rendering the adjecent cells of each line are
| grouped by their common color attrs, resulting in
| (usually) a small number of span elements with text and
| proper style/class. You can see this in action by going
| to asciinema.org, opening a random recording, pausing it,
| then inspecting the terminal with browser's DOM
| inspector.
| littlestymaar wrote:
| This comment is completely off: obviously asciinema
| didn't store each individual pixel in its data structure.
| That would be a completely stupid thing to do even for a
| regular data structure instead of an immutable one...
| merijnv wrote:
| > ...does seem to suggest that the "garbage multiplier"
| effect of immutability is an ill fit for applications that
| also create a lot of garbage naturally
|
| That actually depends on how your GC is implemented. For
| example, due to laziness+immutability, Haskell produces _a
| lot_ of garbage and _a lot_ of allocations. This is not a
| problem with the GHC compiler, as the GC design makes
| allocation cheap (effectively a bump pointer allocator) and
| GC cost scales with the amount of non-garbage (this is, like
| all GC design, is a trade-off that can get you into trouble
| with some workloads).
| fnordsensei wrote:
| Clojure developers are not unaware of the tradeoffs between
| immutable and mutable data structures. You'll see them use
| mutable data structures, particularly in tight loops inside
| functions that take immutable inputs, mutate them, and
| produce immutable outputs (thereby preserving the promise of
| immutability, while leveraging the performance of mutability
| internally).
|
| You'll rarely see apps designed like this up-front though.
| Most of the time, the surgical mutability will come as a
| performance optimization pass later on.
|
| As for the apples-to-apples part, I for one am unsurprised to
| see that WASM performs better than ClojureScript,
| particularly for an application like this.
| bachmeier wrote:
| This is an application where the goal is to squeeze every last
| drop of performance possible out of the processor. The "every
| last drop of performance" crowd has never been the source of
| the "immutability hype". Your comment is dismissive of many
| domains of programming - immutable didn't become a thing
| because others weren't as enlightened as you.
| [deleted]
| jcelerier wrote:
| > This is an application where the goal is to squeeze every
| last drop of performance possible out of the processor.
|
| I have a hard time thinking of an application for which this
| isn't the case. If my cooking recipe app / website is too
| slow and/or eats too much battery (and god fucking knows they
| are) I'll look for a competitor immediately.
| detaro wrote:
| not being too slow and "squeeze every last drop of
| performance possible" is not really the same, and the
| latter is an expensive tradeoff to make.
| slmjkdbtl wrote:
| I fantasize about a future where we have enough CPU and memory
| that we can waste them on nice stuff like immutable data
| structures and software rendering.
| gpderetta wrote:
| That future is our past. The era of free, continuous order-
| of-magnitude single threaded CPU improvements is well behind
| us. Performance is only growing very slowly. On the other
| hand ram, disk, and network bandwidth/latency is improving
| continuously, making the CPU even more of a bottleneck.
| zupa-hu wrote:
| Welcome to now. Totally works like 99.99% of the time.
| josephg wrote:
| I fantasize about a future in which buying a faster computer
| means my software runs faster.
|
| I don't spend thousands on computer hardware so that lazy
| devs can get lazier.
| hayley-patton wrote:
| The use of persistent data structures can make concurrent
| programming easier, which allows for better use of many
| cores. Functional programming can also scale to many
| computers in distributed systems, e.g. in Erlang.
| devwastaken wrote:
| You cannot physically click faster than about 100ms in
| reaction to a UI. A proper application that isn't 100x less
| efficient will never be noticed by you unless you go out of
| your way to measure it. Stable software is more important
| than unusable fast.
|
| "Lazy devs", Work on a team in C graphic code and watch
| nothing get done.
| ben-schaaf wrote:
| A 100ms delay is trivially noticeable - I suggest trying
| to type with that delay. In terms of video people
| reliably distinguish between a 144hz and 240hz refresh
| rate which is a difference if just ~3ms.
| ncmncm wrote:
| Comparing to C is always pointless. There is no
| environment constrained to using C for performance. There
| are only individuals who refuse to move on from C.
|
| It doesn't matter what language they move on to. Rust and
| C++ are both good.
| jacquesm wrote:
| That ship sailed three decades ago.
| slmjkdbtl wrote:
| I wouldn't characterize hoping to use immutable data
| structures and software rendering as trying to be lazy
| drenvuk wrote:
| I would.
|
| Instead of properly managing mutable state (which can be
| difficult in situations with growing teams and complex
| application logic) people are opting to just copy
| everything or copy a subset of the tree they need so they
| don't have to think about it.
|
| Immutability is bad for performance when the purpose is
| not recalculating a certain state after a certain number
| of operations(memoization). Many of the best practices
| that have cropped up in the past few years has been more
| for helping teams of people deal with growing code bases
| rather than helping programmers deal with limited
| hardware. In computer science this should be self
| explanatory. For optimal runtimes the act of making
| copies is avoided. Why people usually seem to ignore the
| fact that they're wasting cycles for the sake of the holy
| grail of clean, functional programming and immutability
| has eluded me.
|
| Typescript, focus on immutability, microservices even. I
| hate all of them but they have their purposes. They solve
| people problems. Maximizing hardware performance is not
| in the list though.
| rackjack wrote:
| Abstraction is at the core of programming... complaining
| about people not "properly managing mutable state" is
| like complaining about choosing Java over C because
| they're not "properly" managing memory and instead using
| a garbage collector. Maximizing hardware performance is,
| truth be told, largely irrelevant for the vast majority
| of applications. If they can meet their
| goals/deadlines/whatever, you can call them lazy, but I
| think most would call them efficient.
|
| Though I must admit, every time my browser lags when
| viewing what SHOULD be a static site, I do die a little
| inside.
| slmjkdbtl wrote:
| Yeah now I wouldn't use immutable structure in an
| performance intensive application, but I do _hope_ one
| day we have some cycles to spare and can use it without
| worrying too much. To me it's like garbage collection,
| it's nice to have if we can afford some performance cost.
| ncmncm wrote:
| Yet, we may characterize lazy programmers as hoping to
| use immutable data structures and pay no attention to
| performance.
|
| We all know that performance takes extra work to ensure,
| then, and is uncertain even with the extra work.
| askonomm wrote:
| You may call functional programmers who prefer immutable
| data structures lazy because we want to actually understand
| what we create, but I don't see how the 10 billion layers
| of abstractions and state duplications somehow end up
| making better software.
| josephg wrote:
| I agree - I think having 10 billon layers of abstraction
| is worse for everyone. It's buggier, more expensive to
| make and (ironically) often slower in practice anyway;
| because you can't optimize what you can't understand.
| Java style OO has a lot to answer for.
|
| Functional programming is great. What's not great is
| loading the entire closure VM environment into my browser
| - resulting in the software running (in this case) 50x
| slower. FP is no excuse for making my computer crawl to a
| halt.
|
| And there's no essential reason FP needs to be slow. For
| example, look at how well llvm optimizes map/filter/fold
| in rust. In many cases they're faster than their
| imperative counterparts! There are other ways to benefit
| from immutability that don't involve burying a garbage
| collector in useless work. For example, React is a lovely
| example of immutable ideas, and a fast runtime.
|
| I spent a few thousand dollars on a new Mac laptop
| recently. I wonder what percentage of my clock cycles are
| going to be wasted due to bad abstractions and
| inefficient code? Probably most of them. I wish I could
| take the money I spent on the machine and instead pay
| people to improve their software. I don't have billions
| of cycles per second of actual work to do.
| comma_at wrote:
| > What's not great is loading the entire closure VM
| environment into my browser
|
| There's no VM in clojurescript, it compiles to JS, it is
| tree-shaken and heavily optimized and minified through
| Google's Closure compiler.
|
| > resulting in the software running (in this case) 50x
| slower
|
| The speedup is not a result of abandoning clojurescript,
| it's from moving from immutable data structures to
| mutable arrays and primitives. The same can be done in
| clojurescript or javascript.
|
| I think this is a common misunderstanding, that's why I'm
| reacting. Nobody claims immutable data structures to be
| the silver bullet. Computation-heavy parts need to be
| done in low level code and with primitive types.
| sickill wrote:
| > The speedup is not a result of abandoning
| clojurescript, it's from moving from immutable data
| structures to mutable arrays and primitives. The same can
| be done in clojurescript or javascript.
|
| More or less, yes.
|
| The majority of the perf increase here came from two
| things: 1. going from immutable->mutable, 2. going from
| CLJS/JS->Rust in the perf critical part. Doing just 1.
| would likely improve the performance, but not as much as
| doing both 1. and 2.
|
| Doing just 1. while staying with ClojureScript could
| potentially be accomplished with transients [0] at the
| cost of making a major chunk of the code non-idiomatic
| Clojure. I actually played with transients here before
| attempting the rewrite, but haven't got too promising
| results though.
|
| [0] https://clojure.org/reference/transients
| nyanpasu64 wrote:
| To me, it _is_ lazy to use immutable data structures in
| situations where they generate large amounts of garbage
| and /or result in user-facing GC pauses. (In Firefox, I
| encounter many slow sites (with or without immutability)
| with multi-frame pauses, often GC pauses. I _think_ the
| slowdown is coming from the website and not my
| extensions.)
|
| I believe it's possible to understand the code you
| create, even in the presence of mutation (though you can
| no longer store old values for free, and need to use
| cloning or other approaches). You need to restrict
| _which_ code is responsible for mutating state (using
| careful program architecture), and restrict the ability
| to mutate data while other pointers to the data exist
| (Rust imposes these restrictions). Interestingly, the
| Relm architecture is a translation of the Elm
| architecture (Elm is an immutable language) to Rust code
| (Rust is a mutable language) which restricts _which_ code
| is responsible for mutating state, and Rust restricts the
| ability to mutate data while other pointers to the data
| exist.
|
| Interestingly, Rust unifies immutable and mutable data
| structures. The im library (https://docs.rs/im) uses the
| same tree-based immutable data structures as Clojure and
| such, but exposes an API closer to Rust's stdlib
| containers (including mutation). However im's performance
| characteristics are different from Rust's stdlib; clones
| are shallow and take O(1) time, while IndexMut is slower
| and copies tree nodes whenever that node's refcount is
| greater than 1. immer.js
| (https://github.com/immerjs/immer) has a somewhat similar
| API, but a different implementation (I think it uses
| standard JS arrays and copies the whole thing when you
| mutate one element).
| drenvuk wrote:
| I'm not sure if you feel attacked or not but you
| shouldn't. Being lazy is good for programming I think.
| You should keep in mind that your functional programming
| base is built on a figurative 10 billion layers of
| abstraction already. It's just that those abstractions
| are somewhat well made so you don't have to think about
| it.
|
| Proper abstractions aid in understanding and can ideally
| be optimized away. Poor abstractions hinder it and slow
| things down.
| eatonphil wrote:
| Historically asciinema was not easy to embed in React because you
| can't have multiple copies of React. So my team at the time wrote
| and open-sourced an embeddable alternative to it. Unfortunately
| that project seems to have disappeared by now.
|
| But now that asciinema is no longer in React maybe it will be
| possible to embed now. See
| https://github.com/asciinema/asciinema-player/issues/72#issu....
| sickill wrote:
| Yup. No more React.js conflict. That was caused by the way how
| ClojureScript bundle has been built (reagent's copy of React
| added to the bundle's global/window namespace).
|
| Also, the dependency on Solid.js is unlikely to cause any
| conflicts even if you used Solid.js yourself in your app given
| the new package doesn't globally export anything else other
| than the minimal public API for mounting the player in DOM.
| kazinator wrote:
| Historically, you could embed an animated .gif into a web page
| going back before Y2K, and there are tools to make such a thing
| from recording terminal sessions. No Javascript, no third party
| websites.
| Cthulhu_ wrote:
| If you want to go that way, prefer html5 videos, they are a
| lot more compact and have options to pause and navigate.
| sickill wrote:
| > no third party websites
|
| FYI you're not forced to use asciinema.org for hosting the
| recordings, it's fully self-hosting friendly:
| https://github.com/asciinema/asciinema-player/#quick-start
| kazinator wrote:
| I don't want to engage in anything by the name of "hosting"
| to convey an animation.
|
| Last time I made an animation, like this, over a year ago,
| I just pasted it into a team Slack channel.
| akavel wrote:
| Is there some tool like this that you could recommend? I
| tried searching for one at one time for my project, assuming
| someone must have written something like that for the
| _script_ command, but didn 't seem to be able to find a
| reasonable one (or any? I don't recall). I ended up writing
| an ad hoc single use tool for gif-izing an asciinema
| transcript... (https://github.com/akavel/asciinema2gif)
| codetrotter wrote:
| You can't pause and rewind or skip ahead in a gif in any of
| the major browsers.
| stjohnswarts wrote:
| 9 times out 10 if you need something to be shown in video
| it's better to use an mp4 and screen recorder rather than
| stick it in a gif. It's usually smaller too.
| kevin_thibedeau wrote:
| Or copy/paste text.
| unrealhoang wrote:
| Or render it beautifully for every future screen
| resolution.
| hedora wrote:
| FWIW, iOS 15 automatically OCR's screenshots, so now copy
| paste works again (even from non-selectable text in
| apps).
|
| However, most times I have problems with copy paste, it's
| not due to gif's. It's due to some BS framework thing
| rendering text in some non-standard way.
| kazinator wrote:
| If I had users who needed to be that engaged with the
| content, they would be the sort of target audience I
| could easily have run _scriptreplay_ in a terminal.
|
| (I see this more as a demo thing to show people what is
| possible than, say, documentation to crib from, but I can
| see the value in being able to do that.)
| 5e92cb50239222b wrote:
| Those are pretty heavy unless it's only a second or two (then
| why would you need a gif at all?) You'll be further cutting
| your target audience to the extremely privileged. I've had to
| suffer with dial-up (3-4 KB/s) until 2009, and with shitty
| ADSL (15-30 KB/s) until 2013. Many parts of the world are
| still like that.
| kazinator wrote:
| I have a here 90 second .gif I made a year ago (demo of a
| particular Vim syntax highlighting scheme for a commit
| message format). It contains 930 frames, 10 fps. The
| resolution is 1200x768. The .gif is 600.0 kilobytes, so the
| coding density is about 660 bytes per frame.
|
| Someone downloading at 3-4KB/s might find the download
| annoying; on the other hand, it could play back on a 66 MHz
| 486 DX they found in the dumpster. Good luck bringing up a
| modern browser with Javascript.
|
| 4KB/s second would be enough to get it to average around
| 6FPS in the first pass through the animation, if it were
| being rendered as it is being downloaded.
| com2kid wrote:
| > it could play back on a 66 MHz 486 DX they found in the
| dumpster.
|
| ooh actually, I got banned from the Ars-Technica forums
| way back in the day for posting a giant 800x600 animated
| GIF. It took browsers a few minutes to render! People
| thought I had crashed their browsers, but they just
| needed to be patient. ;)
|
| I think I had a Duron 700mhz back then, so a 486 would've
| been turned into toast.
|
| (Or, possibly, IE's GIF code was just really bad at that
| time! :) )
| JasonFruit wrote:
| You're clearly more careful with resource consumption
| than many, then. Many times I've had enough time to start
| coffee while waiting for a .gif to get through its first
| pass so I can usefully watch it, using rural satellite
| from Hughes. We're still using your stuff out here.
| hedora wrote:
| Hughes is latency-bound, not bandwidth bound. For it to
| take that long, they'd have to try really hard. For
| instance, the map could issue an http[s] request per
| frame.
| kazinator wrote:
| Was it a TTY animation with most frames changing very few
| pixels (like one character cell), often with quiescent
| periods when nothing changes due to nobody typing?
|
| Gifs can do silly things, like store a sequence of full
| frames.
| eatonphil wrote:
| I have no aversion to JavaScript. It's easier just to fetch
| the session as text and render it in the browser with
| JavaScript.
|
| If you're building gifs then you need additional file storage
| and an async job queue for generating the gif. I try to avoid
| image processing personally.
| unnouinceput wrote:
| I get it, Clojure bad, Rust good. Yeah, absolutely nothing to do
| with the brain in the chair.
| fnordsensei wrote:
| More like, know when to apply Clojure and when to apply Rust.
|
| Having written a ClojureScript app with a Rust/WASM component,
| for me it's very clear that they have different strengths that
| can be complementary.
|
| That the author dropped CLJS along with React is fair enough,
| in my opinion. The CLJS ecosystem is pretty React-centric.
| corn13read2 wrote:
| That's what she said
| agys wrote:
| For my own realtime browser based ASCII projects I update the DOM
| "manually": the biggest bottleneck is frequent -horizontal-
| changes in color as each character with a new color needs to be
| wrapped in its own <span> element. After all you can't avoid a
| DOM repaint.
|
| After several benchmarks I realized that the fastest way to
| update the entire window is to compose a string and assign it to
| each line/line-element via innerHTML. I usually get 60fps with
| 5-8k chars in fullscreen (browser text rendering has become
| really fast).
| stjohnswarts wrote:
| Maybe you could benchmark it against this. It would make an
| interest HN followup post.
| sickill wrote:
| It's not the rendering / DOM part that got 50x faster though,
| so that would be apples to oranges.
___________________________________________________________________
(page generated 2021-11-30 23:03 UTC)