Reduced Spread

Reduced Spread




๐Ÿ”ž ALL INFORMATION CLICK HERE ๐Ÿ‘ˆ๐Ÿป๐Ÿ‘ˆ๐Ÿป๐Ÿ‘ˆ๐Ÿป

































Reduced Spread

Was this page helpful?
Yes
No


Performance & security by Cloudflare


You cannot access betterprogramming.pub. Refresh the page or contact the site owner to request access.
Copy and paste the Ray ID when you contact the site owner.

Ray ID:

7471b7900de47a64


7471b7900de47a64 Copy



For help visit Troubleshooting guide



We welcome feedback: you can select the flag against a sentence to report it.
Why have you flagged this sentence?
Read more on how we generate our sentences.
Spread is a soft food which is put on bread . [...]

Collins COBUILD Advanced Learnerโ€™s Dictionary . Copyright ยฉ HarperCollins Publishers

( rษชdj uห s
, US -d uห s
) Explore 'reduce' in the dictionary

If you reduce something, you make it smaller in size or amount, or less in degree . [...]

Collins COBUILD Advanced Learnerโ€™s Dictionary . Copyright ยฉ HarperCollins Publishers


Definition of reduce the spread of from the Collins English Dictionary

Drag the correct answer into the box.
This disease causesย , strokes and heart attacks.
Drag the correct answer into the box.
Just a few early nights can transform yourย of the world.
Drag the correct answer into the box.
Toย to patients with mild Alzheimer's disease is disgraceful.
Check See the answer Next Next quiz Review

a building, such as a summerhouse or roofed gallery , sited to command a fine view

Whatโ€™s the difference between anniversary and birthday?

This week we are looking at two words which are sometimes confused: anniversary and birthday. Improve your English with Collins.
Read more

Divining the hallmarks of Gothic literature

With spooky season rapidly approaching, nothing marks the turn of the seasons better than Frankenstein Day on 30th August.
Read more

Whatโ€™s the difference between boot and trunk?

In today's Learning English post we are looking at some words which can be used differently in British and American English: boot and trunk. Improve your English with Collins.
Read more


Download our English Dictionary apps - available for both iOS and Android.
Read more


Our new online dictionaries for schools provide a safe and appropriate environment for children. And best of all it's ad free, so sign up now and start using at home or in the classroom.
Read more


We have almost 200 lists of words from topics as varied as types of butterflies, jackets, currencies, vegetables and knots!
Amaze your friends with your new-found knowledge!
Read more

Stuck at Wordle? Try our helper to maintain your current streak!
Drag the correct answer into the box.
Overallย is weak and it is expected to remain weak in the near term.
Check See the answer Next Next quiz Review
Whatโ€™s the difference between announcement and advertisement?

This week we are looking at two words which are sometimes confused: announcement and advertisement. Improve your English with Collins.

September 5, 2022
Read more


Create an account and sign in to access this FREE content


English
Italiano
American
Portuguรชs
ํ•œ๊ตญ์–ด
็ฎ€ไฝ“ไธญๆ–‡
Deutsch
Espaรฑol
เคนเคฟเค‚เคฆเฅ€
ๆ—ฅๆœฌ่ชž


Cookies Settings Accept All Cookies
environmental damage
or
nerve damage ?
slurred speech
or
victory speech ?
deny treatment
or
improve treatments ?
face the danger
or
spell danger ?
criminal activity
or
economic activity ?
fantastic atmosphere
or
poisonous atmosphere ?
field questions
or
raise questions ?
environmental damage
or
nerve damage ?
By clicking โ€œAccept All Cookiesโ€, you agree to the storing of cookies on your device to enhance site navigation, analyze site usage, and assist in our marketing efforts.

tl;dr reduce ...spread belongs to a different complexity class than the optimal solutions, which is bad javascript engines will probably never optimize this code if you're using reduce ...spread for reasons of immutability, you should copy once or use immutable helper libraries
// bytecode
StackCheck
CreateObjectLiteral [0], [0], #41, r0
Mov r0, r1
Mov a0, r2
CallRuntime [CopyDataProperties], r1-r2
LdaNamedProperty a1, [1], [1]
ToName r1
LdaNamedProperty a1, [2], [3]
StaDataPropertyInLiteral r0, r1, #0, [5]
Ldar r0
Return // builtin code generation
SetOrCopyDataProperties( /* ... */ ) {
// ...
ForEachEnumerableOwnProperty (
context, source_map, CAST(source), kEnumerationOrder,
[=](TNode key, TNode value) {
CallBuiltin(Builtins::kSetPropertyInLiteral , context, target, key, value);
},
if_runtime);
// ...
}
Note: The above assumes no duplicate keys are generated in your target object. For most example I've
seen of mapping an array of objects to object key->values that holds true and I think is a fair assumption.
However, there are situations where that's obviously not true , like with a solution
specifically meant for counting duplicates (think word count). In those situations using the reduce...spread
pattern would still be classified as ๐‘‚(๐‘› 2 ) (as big O notation is an approximation of the upper bound)
but actual run times would probably be more accurately reflected by also considering best-case (all duplicates) and
average-case complexity as well.

Created with Highcharts 7.1.2 n (item count) ops/sec Chart context menu reset Operations per second reduce spread O(n^2) reduce object.assign O(n^2) reduce mutate O(n) object.assign ...map O(n) object.fromEntries ...map O(n) reduce immutable.js O(n) reduce immutable.js withMutations O(n) reduce immer.js O(n) for..of O(n) 10 20 30 40 50 60 70 80 90 100 0 250k 500k 750k 1 000k Highcharts.com
Performance is a common topic in computing, but it is especially common in the frontend world as the latest Javascript
technologies battle for the frontend throne. Some may say React has already won (and the usage numbers seem to agree)
so in this blog post I wanted to talk about a piece of problematic code I'm seeing more frequently in the frontend
world as Javascript syntax is evolving and components are taking over.
You've probably been in a situation where you wanted to merge an array of object maps into a singular object. Here's
two common solutions to the problem.
While the later "for loop" is arguably easier to read, the former "reduce" is fine and becoming more common as the React community
increasingly adopts a more functional programming style, often eschewing iterative statements in favor of function
expressions which can be easily inlined into components .
I personally like them both.
I'm not so much a fan of this latest emerging style.
For those unfamiliar with spread syntax ( ... ) in object literals ,
it behaves very similarly to Object.assign
in that you can use it for iterating over a source object's properties to copy them into a target object. In this case
we're copying to a newly created object. Can you see the problem? I'm not referring to the object initialization,
that's only slightly problematic.
One functional downside: hidden iteration. Seems some coders
would balk at for;for;for; but have no qualms with .map.filter.reduce.
Hidden iteration! When Array#Map and the crew were newer it wasn't uncommon to see coders using them excessively,
(often sequentially and multiple times over the same data set). Now with the spread operator in its honeymoon
phase developers are back to experimenting with new and exciting programming patterns; some good
( ... is great with configuration objects), and some bad. Unfortunately the magic nature of the spread operator has
been somewhat troublesome when it comes to reviewing code that includes reduce...spread . Convincing people to avoid that
pattern because of the nested looping is often met with "what loops?", "premature optimization!", or "that's mutation!"
So below we're going take a quick dive into engine internals to find the missing loops, talk a bit about optimization
and computational complexity, and finally will talk a bit about functional programming.
When Javascript code is encountered in something like a browser, the execution of that code is handled by a Javascript engine.
Several engines exist, but we're going to specifically talk about Chrome and Node's default engine: v8 .
How the v8 engine works is a complex topic, but the basics are covered in this excellent presentation .
Currently, there are three components that constitute the compilation layers performed by the v8 engine: the parser, which
generates an abstract syntax tree (AST) ; an interpreter, which
generates bytecode ; and an optimized compiler, which generates
machine code .
All of this is performed at run time (rather than during a separate compilation step) in a process known as
just-in-time (JIT) compilation.
By looking at the bytecode generated by v8's interpreter, Ignition , we can get a more
accurate picture of what our Javascript code will actually be doing.
The following bytecode is generated from reduce ...spread with the important bits highlighted
in yellow.
The bytecode will generate code that makes a runtime call which maps to an inlined builtin generated with the loop
we were looking for. I guess we were performing nested iteration after all...
Discussing the complexity of a piece of code requires an understanding on the amount of resources that said code will use
when ran. Specifically, when comparing our reduce mutate solution to reduce ...spread , we'll be talking about
their respective time complexities ; in other words, how long each
solution takes to run given a certain input size. These time approximations are usually denoted in
Big ๐‘‚ notation , for example: ๐‘‚(1) for
constant time or ๐‘‚(n) for
linear time .
Figuring out the time complexity of code that iterates over a set of data (in our case, with reduce ) of
size n involves finding the constant time operation we're concerned about in our solution and determining
how many times that operation will be executed. For us, the base operation we're interested in is the insertion of data
into our objects, which in general is a constant time operation .
We can see this represented in one solution as Javascript with acc[item.name] = item.value; and in the other solution with
the machine code generated by Builtins::kSetPropertyInLiteral . The fact that these code paths likely have different
implementations isn't important, only that they're both constant time.
We can see in reduce mutate that our base operation is only happening once for each iteration of reduce; in other
words, it's happening n times for an input array of size n so we can classify it as linear time: ๐‘‚(n). However,
with reduce...spread it's actually performing a few other operations, specifically the creation of a new object
literal and then again iterating (nested iteration in this case, since it's inside our previous iteration) over the
existing property keys and then performing our base operation for each nested iteration. How many times is our base
operation happening then? Well, it's complicated. It doesn't exactly execute the inner loop n times since
the inner loop is limited by the amount of keys it needs to copy. However, for our purposes it's good enough to say it's in the same
class of solutions that execute n * n or n 2
times and call it ๐‘‚(n 2 ) since it trends that way anyways as n goes towards infinity, but for a more accurate
description we could notate it as ๐œƒ(๐‘› 2 ) โ‰ก ๐‘‚(๐‘› 2 ) ๐‘Ž๐‘›๐‘‘ ฮฉ(๐‘› 2 ) .
We can see on the provided diagram how different classifications of algorithms perform for different input sizes.
The class groupings represent comparable runtime characteristics for different algorithms, i.e. two different algorithms
that are ๐‘‚(n) may have different execution times, but their run time will grow comparably to each other as the
input size they operate on grows. Understanding how code will generally perform helps to write appropriate solutions
to the problems we are trying to solve and help us know certain performance characteristics of the code without even
running it!
Okay, so one of our solutions is ๐‘‚(n) and the other is ๐‘‚(n 2 )... big whoop! Is that really so bad? Isn't
worrying about this just a case of premature optimization? Won't the optimizing compiler save us anyways? Well, looking
at our informative diagram seems to demonstrate that ๐‘‚(n) and ๐‘‚(n 2 ) have very different performance
characteristics. Let's see how they pan out in actual benchmarks.
I've included our two discussed solutions reduce mutate and reduce...spread in these tests as well as some
additional benchmarks including the for..of , referenced above, and some solutions using immutable data
structures for our later talk on functional programming. You can
see the code that was used to run these benchmarks here .
One thing immediately noticeable is how much faster reduce mutate and for..of are than the competition when
it comes to a small amount of items. Why that is, I'm not quite sure; I thought it might have something to do with the
optimizer but I was unable to normalize the spikes with benchmark warmups (to ensure JIT optimizations in all our
results) or by limiting test cycles.
That's not super important though as we're here to see what different time complexities means for our code; the real
problem can be seen when we click reduce...spread ๐‘‚(n^2) on the chart above and adjust the data so we can see how it compares
to the other solutions over time. Then we can click on reduce mutate ๐‘‚(n) and see how it compares. Did you see the difference?
If we compare any of the ๐‘‚(n) solutions to the others, we'll see that they basically perform at some consistent time multiple of
the other ๐‘‚(n) solutions. Example: clicking for..of ๐‘‚(n) will show that reduce mutate ๐‘‚(n) is 3/4 the speed, but it's pretty
much always 3/4 the speed no matter the size of our data set. However, if we click reduce...spread ๐‘‚(n^2) and compare it
to reduce mutate ๐‘‚(n) , first it's 20 times slower, then 40, then 80. It's growing steadily slower! That's bad news.
The reason I consider reduce...spread an anti-pattern is because of its growing popularity combined with its
non-obvious performance issue; non-obvious because most would expect directly mapping an array of objects to a
similar number of object properties to require a linear amount of work: 10 items will take ~10ms, 20 items will take
~20ms, etc. However, that is not the case. This thing will kill your application's performance quickly if you follow
such a sane assumption.
Most of us have heard part of that quote, but usually not the whole thing. There is such thing as premature
optimization, however this is not one. If anything, I'd suggest that reduce...spread is a premature de-optimization.
Premature optimizations are things such as choosing to use the fastest ๐‘‚(n) solution provided in my benchmarks
over the other ๐‘‚(n) solutions because it is the fastest . Which ๐‘‚(n) solution you choose is probably inconsequential from a
performance standpoint; it's entirely possible that you'd see different results in different Javascript engines and
that advancements in v8's optimizing compiler could change these results tomorrow.
Could the same be said for reduce...spread and its ๐‘‚(n 2 ) time? Probably not. Here's a relevant point on
optimizing compilers (emphasis added):
Now that's not saying it can't be optimized; obviously it can, because we did it by utilizing mutation. But looking at
our benchmarks it's obvious that it is not currently optimized and it's unlikely it ever will be. You can see a few
discussions around this exact pattern on this tweet asking
for potential optimizations to spreading inside object literals, if you're interested.
Finally, let's talk a bit about functional programming. The final argument I hear in favor of reduce...spread is for
reasons of functional purity , in that our reduce function is mutating
one of its parameters (the accumulator), and that's bad. But what potential bugs are we preventing by avoiding
mutation in this case?
Let's look at the code again, this time highlighting an important part.
The object we're avoiding mutation on is a reference that we created ; in other words, mutating this parameter is
not dangerous and worrying about mutating it is in-fact a case of premature de-optimization.
Is your linter complaining? If so, that's exactly why linters give us the ability to ignore certain lines. Linters are
useful in alerting us to potential trade-offs, but in this case (with our new found wisdom) we can
decide to ignore it and avoid a potential pitfall .
You could also use the for loop instead and avoid reduce (and linting errors) altogether.
If you would like to generalize the reduce mutate code to work in situations where you may be working with data that doesn't
belong to you, I suggest either making a copy of that data before iterating or using immutable data structures
(as that is what they are created for). In the benchmarks
I've included some examples of using
immutable.js with and without mutations (that's right, an
immutable library provides helpers for mutating data) and immer.js . Immutable
data structures provide the benefit of allowing destructive operations without modifying the original
source object you are operating on. They also do this with the added benefit of sharing the underlying data
to prevent waste like in reduce...spread . If you want to code with immutability in mind then I suggest using the right
tools for the job. You also might be interested in
this proposal of a const value type .
Please avoid this pattern in your code! If you are reviewing code that contains this pattern, feel free to reference
this blog post.


Clipboard, Search History, and several other advanced features are temporarily unavailable.



Dashboard
Publications
Account settings
Log out



Advanced



Clipboard




Format


Abstract

PubMed

PMID





Format:


Summary (text)
PubMed
PMID
Abstract (text)
CSV




Subject:

1 selected item: 35476785 - PubMed





Format:


Summary
Summary (text)
Abstract
Abstract (text)







Create a new collection



Add to an existing collection




Name must be less than 100 characters


Unable to load your collection due to an error
Please try again


Unable to load your delegates due to an error
Please try again



Would you like email updates of new search results?


Saved Search Alert Radio Buttons



Yes



No






Softcore Hentai Boner Raiser Edited
Gorgeous Sensual
Overwatch Sex Porn

Report Page