From 0cc73350fa9f27b223bb635118f85c19bfd59947 Mon Sep 17 00:00:00 2001 From: Stanislav Dolgachov Date: Thu, 15 Jul 2021 23:58:38 +0300 Subject: [PATCH 1/5] 1-04-03: Garbage collection part 1 --- .../03-garbage-collection/article.md | 32 +++++++++---------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 72e30469c..14b81f380 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -1,31 +1,31 @@ -# Garbage collection +# Збирання сміття -Memory management in JavaScript is performed automatically and invisibly to us. We create primitives, objects, functions... All that takes memory. +Управління пам’яттю в JavaScript виконується автоматично і непомітно. Ми створюємо примітиви, об’єкти, функції... Все це займає пам’ять. -What happens when something is not needed any more? How does the JavaScript engine discover it and clean it up? +Але що відбувається, коли щось більше не потрібно? Як JavaScript розуміє, що потрібно звільняти пам’ять? -## Reachability +## Досяжність -The main concept of memory management in JavaScript is *reachability*. +Основна концепція управління пам’яттю в JavaScript -- це *досяжність*. -Simply put, "reachable" values are those that are accessible or usable somehow. They are guaranteed to be stored in memory. +Простіше кажучи, "досяжні" значення -- це ті, які якимось чином доступні або придатні для використання. Вони гарантовано зберігаються в пам’яті. -1. There's a base set of inherently reachable values, that cannot be deleted for obvious reasons. +1. Існує базовий набір досяжних за своєю суттю значень, які неможливо видалити із зрозумілих причин. - For instance: + Наприклад: - - The currently executing function, its local variables and parameters. - - Other functions on the current chain of nested calls, their local variables and parameters. - - Global variables. - - (there are some other, internal ones as well) + - Функція, що виконується зараз, її локальні змінні та параметри. + - Інші функції поточного ланцюжка вкладених викликів, їх локальні змінні та параметри. + - Глобальні змінні. + - (є й деякі інші, внутрішні) - These values are called *roots*. + Ці значення ми будемо називати *корені*. -2. Any other value is considered reachable if it's reachable from a root by a reference or by a chain of references. +2. Будь-яке інше значення вважається досяжним, якщо воно доступне з кореня за допомогою посилання або ланцюжка посилань. - For instance, if there's an object in a global variable, and that object has a property referencing another object, *that* object is considered reachable. And those that it references are also reachable. Detailed examples to follow. + Наприклад, якщо в глобальній змінній є об’єкт, і цей об’єкт має властивість, що посилається на інший об’єкт, *цей* об’єкт вважається досяжним. І ті, на які він посилається, також досяжні. Далі ви познайомитеся з докладними прикладами на цю тему. -There's a background process in the JavaScript engine that is called [garbage collector](https://en.wikipedia.org/wiki/Garbage_collection_(computer_science)). It monitors all objects and removes those that have become unreachable. +У рушію JavaScript є фоновий процес, який називається [збирання сміття](https://uk.wikipedia.org/wiki/%D0%97%D0%B1%D0%B8%D1%80%D0%B0%D0%BD%D0%BD%D1%8F_%D1%81%D0%BC%D1%96%D1%82%D1%82%D1%8F). Воно контролює всі об’єкти та видаляє ті, які стали недосяжними. ## A simple example From 9becadbb88eb0a661df43d49a548f560606a917a Mon Sep 17 00:00:00 2001 From: Stanislav Dolgachov Date: Thu, 2 Sep 2021 13:27:04 +0300 Subject: [PATCH 2/5] 1-04-03: Garbage Collection part 2 --- .../03-garbage-collection/article.md | 98 +++++++++---------- 1 file changed, 49 insertions(+), 49 deletions(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 14b81f380..f8b1a91dc 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -25,24 +25,24 @@ Наприклад, якщо в глобальній змінній є об’єкт, і цей об’єкт має властивість, що посилається на інший об’єкт, *цей* об’єкт вважається досяжним. І ті, на які він посилається, також досяжні. Далі ви познайомитеся з докладними прикладами на цю тему. -У рушію JavaScript є фоновий процес, який називається [збирання сміття](https://uk.wikipedia.org/wiki/%D0%97%D0%B1%D0%B8%D1%80%D0%B0%D0%BD%D0%BD%D1%8F_%D1%81%D0%BC%D1%96%D1%82%D1%82%D1%8F). Воно контролює всі об’єкти та видаляє ті, які стали недосяжними. +У рушію JavaScript є фоновий процес, який називається [збирання сміття](https://uk.wikipedia.org/wiki/%D0%97%D0%B1%D0%B8%D1%80%D0%B0%D0%BD%D0%BD%D1%8F_%D1%81%D0%BC%D1%96%D1%82%D1%82%D1%8F). Він контролює всі об’єкти та видаляє ті, які стали недосяжними. -## A simple example +## Простий приклад -Here's the simplest example: +Ось найпростіший приклад: ```js -// user has a reference to the object +// user має посилання на об’єкт let user = { - name: "John" + name: "Іван" }; ``` ![](memory-user-john.svg) -Here the arrow depicts an object reference. The global variable `"user"` references the object `{name: "John"}` (we'll call it John for brevity). The `"name"` property of John stores a primitive, so it's painted inside the object. +Тут стрілка зображує посилання на об’єкт. Глобальна змінна `"user"` посилається на об’єкт `{name: "Іван"}` (ми будемо називати його Іван для стислості). Властивість `"name"` Івана зберігає примітив, тому він зображений всередині об’єкта. -If the value of `user` is overwritten, the reference is lost: +Якщо значення в змінній `user` переписується, посилання втрачається: ```js user = null; @@ -50,16 +50,16 @@ user = null; ![](memory-user-john-lost.svg) -Now John becomes unreachable. There's no way to access it, no references to it. Garbage collector will junk the data and free the memory. +Тепер Іван стає недосяжним. Немає доступу до нього, немає посилань на нього. Процес збирання сміття видалить дані і звільнить пам’ять. -## Two references +## Два посилання -Now let's imagine we copied the reference from `user` to `admin`: +Тепер уявімо, що ми скопіювали посилання зі змінної `user` у змінну `admin`: ```js -// user has a reference to the object +// user має посилання на об’єкт let user = { - name: "John" + name: "Іван" }; *!* @@ -69,16 +69,16 @@ let admin = user; ![](memory-user-john-admin.svg) -Now if we do the same: +Тепер, якщо ми зробимо те саме: ```js user = null; ``` -...Then the object is still reachable via `admin` global variable, so it's in memory. If we overwrite `admin` too, then it can be removed. +...Тепер об’єкт все ще є досяжним через глобальну змінну `admin`, таким чином він залишається у пам’яті. Якщо переписати змінну `admin` також, його можна буде видалити. -## Interlinked objects +## Взаємозв’язані об’єкти -Now a more complex example. The family: +Тепер більш складний приклад. Сім’я: ```js function marry(man, woman) { @@ -92,21 +92,21 @@ function marry(man, woman) { } let family = marry({ - name: "John" + name: "Іван" }, { - name: "Ann" + name: "Анна" }); ``` -Function `marry` "marries" two objects by giving them references to each other and returns a new object that contains them both. +Функція `marry` "одружує" два об’єкти, даючи їм посилання один на одного та повертаючи новий об’єкт, що містить їх обох. -The resulting memory structure: +Отримана структура даних: ![](family.svg) -As of now, all objects are reachable. +Наразі всі об’єкти досяжні. -Now let's remove two references: +Тепер видалимо два посилання: ```js delete family.father; @@ -115,75 +115,75 @@ delete family.mother.husband; ![](family-delete-refs.svg) -It's not enough to delete only one of these two references, because all objects would still be reachable. +Недостатньо видалити лише одне з цих двох посилань, оскільки всі об’єкти все одно будуть досяжними. -But if we delete both, then we can see that John has no incoming reference any more: +Але якщо видалити обидва, то можна побачити, що Іван більше не має посилань на себе: ![](family-no-father.svg) -Outgoing references do not matter. Only incoming ones can make an object reachable. So, John is now unreachable and will be removed from the memory with all its data that also became unaccessible. +Вихідні посилання не мають значення. Тільки вхідні можуть зробити об’єкт досяжним. Отже, Іван зараз недосяжний і буде видалений з пам’яті з усіма його даними, які також стали недосяжними. -After garbage collection: +Після збирання сміття: ![](family-no-father-2.svg) -## Unreachable island +## Недосяжний "острів" -It is possible that the whole island of interlinked objects becomes unreachable and is removed from the memory. +Можливо, що весь "острів" взаємопов’язаних об’єктів стане недосяжним і видалиться з пам’яті. -The source object is the same as above. Then: +Якщо об’єкт такий самий, як і вище, тоді: ```js family = null; ``` -The in-memory picture becomes: +Подання в пам'яті стає таким: ![](family-no-family.svg) -This example demonstrates how important the concept of reachability is. +Цей приклад демонструє, наскільки важливою є концепція досяжності. -It's obvious that John and Ann are still linked, both have incoming references. But that's not enough. +Очевидно, що Іван і Анна все ще пов’язані, обидва мають вхідні посилання. Але цього недостатньо. -The former `"family"` object has been unlinked from the root, there's no reference to it any more, so the whole island becomes unreachable and will be removed. +Колишній об’єкт `"family"` було від’єднано від кореня, більше на нього немає посилання, тому весь "острів" стає недосяжним і буде видалений. -## Internal algorithms +## Внутрішні алгоритми -The basic garbage collection algorithm is called "mark-and-sweep". +Основний алгоритм збирання сміття називається "позначення і видалення" (англ. "mark-and-sweep"). -The following "garbage collection" steps are regularly performed: +Зазвичай виконуються такі етапи "збирання сміття": -- The garbage collector takes roots and "marks" (remembers) them. -- Then it visits and "marks" all references from them. -- Then it visits marked objects and marks *their* references. All visited objects are remembered, so as not to visit the same object twice in the future. -- ...And so on until every reachable (from the roots) references are visited. -- All objects except marked ones are removed. +- Збирання сміття розпочинається з коренів, які позначаються (запам'ятовуються) особливим чином. +- Потім позначаються всі посилання від них. +- Потім він відвідує позначені об’єкти та позначає інші об’єкти на які є посилання від них. Усі відвідані об’єкти запам’ятовуються, щоб у майбутньому не відвідувати один і той же об’єкт двічі. +- ...І так до тих пір, поки не будуть відвідані усі досяжні (з коренів) посилання. +- Усі об’єкти, крім позначених, видаляються. -For instance, let our object structure look like this: +Наприклад, нехай наша структура об’єктів виглядатиме так: ![](garbage-collection-1.svg) -We can clearly see an "unreachable island" to the right side. Now let's see how "mark-and-sweep" garbage collector deals with it. +З правого боку ми чітко бачимо "недосяжний острів". Тепер давайте подивимося, як збирання сміття "позначає і видаляє". -The first step marks the roots: +Перший крок позначає корені: ![](garbage-collection-2.svg) -Then their references are marked: +Потім позначаються посилання від них: ![](garbage-collection-3.svg) -...And their references, while possible: +...І посилання від них, поки це можливо: ![](garbage-collection-4.svg) -Now the objects that could not be visited in the process are considered unreachable and will be removed: +Тепер об’єкти, які не вдалося відвідати в процесі, вважаються недосяжними і будуть видалені: ![](garbage-collection-5.svg) -We can also imagine the process as spilling a huge bucket of paint from the roots, that flows through all references and marks all reachable objects. The unmarked ones are then removed. +Ми також можемо уявити собі цей процес, як виливання великого відра фарби починаючи з коренів, фарба протікає через усі посилання і позначає всі об’єкти, до яких можна дістатися. Потім непозначені об’єкти видаляються. -That's the concept of how garbage collection works. JavaScript engines apply many optimizations to make it run faster and not affect the execution. +Це концепція того, як працює збирання сміття. Рушій JavaScript застосовує багато оптимізацій, щоб прискорити це та не вплинути на виконання. Some of the optimizations: From 6b2daeb0e0e6afdff7cd1c035bcaa6c0d2841ad4 Mon Sep 17 00:00:00 2001 From: Stanislav Dolgachov Date: Mon, 6 Sep 2021 12:36:37 +0300 Subject: [PATCH 3/5] 1-04-03: Garbage Collection part 3 --- .../03-garbage-collection/article.md | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index f8b1a91dc..92535b889 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -187,26 +187,26 @@ family = null; Some of the optimizations: -- **Generational collection** -- objects are split into two sets: "new ones" and "old ones". Many objects appear, do their job and die fast, they can be cleaned up aggressively. Those that survive for long enough, become "old" and are examined less often. -- **Incremental collection** -- if there are many objects, and we try to walk and mark the whole object set at once, it may take some time and introduce visible delays in the execution. So the engine tries to split the garbage collection into pieces. Then the pieces are executed one by one, separately. That requires some extra bookkeeping between them to track changes, but we have many tiny delays instead of a big one. -- **Idle-time collection** -- the garbage collector tries to run only while the CPU is idle, to reduce the possible effect on the execution. +- **Збірка поколінь (Generational collection)** -- об’єкти поділяються на два набори: "нові" та "старі". Багато об’єктів з’являється, виконує свою роботу і швидко гине, їх можна агресивно прибирати. Ті, що виживають досить довго, стають "старими" і оглядаються рідше. +- **Інкрементний збір (Incremental collection)** -- якщо об’єктів багато, і ми намагаємось пройтися і позначити весь набір об’єктів одночасно, це може зайняти деякий час і ввести видимі затримки у виконанні. Тому рушій намагається розділити збирання сміття на частини. Потім частини виконуються по одній, окремо. Це вимагає додаткового обліку між ними для відстеження змін, але ми маємо багато маленьких затримок замість великих. +- **Збір під час простою (Idle-time collection)** -- завзвичай збирання сміття працює лише під час простою процесора, щоб зменшити можливий вплив на виконання. -There exist other optimizations and flavours of garbage collection algorithms. As much as I'd like to describe them here, I have to hold off, because different engines implement different tweaks and techniques. And, what's even more important, things change as engines develop, so studying deeper "in advance", without a real need is probably not worth that. Unless, of course, it is a matter of pure interest, then there will be some links for you below. +Існують й інші оптимізації та варіанти алгоритмів збирання сміття. Але як би нам не хотілося описати їх тут, ми повинні утриматися від цього, тому що різні інтерпретатори JavaScript застосовують різні прийоми і хитрощі. І, що ще важливіше, все змінюється в міру розвитку інтерпретаторів, тому глибше вивчення "заздалегідь" без реальної потреби, ймовірно, не варто того. Якщо, звичайно, це не питання чистого інтересу, нижче для вас будуть деякі посилання. -## Summary +## Підсумки -The main things to know: +Основне, що потрібно знати: -- Garbage collection is performed automatically. We cannot force or prevent it. -- Objects are retained in memory while they are reachable. -- Being referenced is not the same as being reachable (from a root): a pack of interlinked objects can become unreachable as a whole. +- Збирання сміття здійснюється автоматично. Ми не можемо примусити або запобігти цьому. +- Об’єкти зберігаються в пам’яті, поки вони досяжні. +- Посилання -- це не те ж саме, що бути досяжним (з кореня): декілька взаємопов’язаних об’єктів можуть стати недосяжними усі разом. -Modern engines implement advanced algorithms of garbage collection. +Сучасні рушії реалізують передові алгоритми збирання сміття. -A general book "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al) covers some of them. +Деякі з них висвітлені в книзі "The Garbage Collection Handbook: The Art of Automatic Memory Management" (R. Jones et al). -If you are familiar with low-level programming, the more detailed information about V8 garbage collector is in the article [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). +Якщо ви знайомі з низькорівневим програмуванням, більш детальна інформація про збирання сміття у рушії V8 міститься у статті [A tour of V8: Garbage Collection](http://jayconrod.com/posts/55/a-tour-of-v8-garbage-collection). -[V8 blog](https://v8.dev/) also publishes articles about changes in memory management from time to time. Naturally, to learn the garbage collection, you'd better prepare by learning about V8 internals in general and read the blog of [Vyacheslav Egorov](http://mrale.ph) who worked as one of V8 engineers. I'm saying: "V8", because it is best covered with articles in the internet. For other engines, many approaches are similar, but garbage collection differs in many aspects. +[V8 blog](https://v8.dev/) також час від часу публікує статті про зміни в управлінні пам’яттю. Зрозуміло, вам необхідно розуміти, як влаштований всередині рущія V8 в цілому. Про це ви можете прочитати у блозі [Вячеслава Єгорова](http://mrale.ph) який працював одним з інженерів V8. Я кажу: "V8", тому що він найкраще висвітлений статтями в Інтернеті. Для інших інтерпретаторів деякі підходи схожі, але збирання сміття відрізняється в багатьох аспектах. -In-depth knowledge of engines is good when you need low-level optimizations. It would be wise to plan that as the next step after you're familiar with the language. +Глибоке розуміння роботи інтерпретаторів необхідно, коли вам потрібні низькорівневі оптимізації. Було б розумно планувати їх вивчення тільки як наступний крок після вивчення мови JavaScript. From 9ad7406503b8a59c94e809038968fc3db8c594f9 Mon Sep 17 00:00:00 2001 From: Taras Date: Mon, 6 Sep 2021 13:56:26 +0300 Subject: [PATCH 4/5] Update 1-js/04-object-basics/03-garbage-collection/article.md --- 1-js/04-object-basics/03-garbage-collection/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 92535b889..05718737d 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -2,7 +2,7 @@ Управління пам’яттю в JavaScript виконується автоматично і непомітно. Ми створюємо примітиви, об’єкти, функції... Все це займає пам’ять. -Але що відбувається, коли щось більше не потрібно? Як JavaScript розуміє, що потрібно звільняти пам’ять? +Але що відбувається, коли змінна або якийсь об’єкт більше не потрібні? Як JavaScript розуміє, коли потрібно звільняти пам’ять? ## Досяжність From 9ce1a9525c7ecf3c175214d641c92c6d47395dca Mon Sep 17 00:00:00 2001 From: Taras Date: Mon, 6 Sep 2021 13:58:41 +0300 Subject: [PATCH 5/5] Update 1-js/04-object-basics/03-garbage-collection/article.md --- 1-js/04-object-basics/03-garbage-collection/article.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/1-js/04-object-basics/03-garbage-collection/article.md b/1-js/04-object-basics/03-garbage-collection/article.md index 05718737d..921447187 100644 --- a/1-js/04-object-basics/03-garbage-collection/article.md +++ b/1-js/04-object-basics/03-garbage-collection/article.md @@ -25,7 +25,7 @@ Наприклад, якщо в глобальній змінній є об’єкт, і цей об’єкт має властивість, що посилається на інший об’єкт, *цей* об’єкт вважається досяжним. І ті, на які він посилається, також досяжні. Далі ви познайомитеся з докладними прикладами на цю тему. -У рушію JavaScript є фоновий процес, який називається [збирання сміття](https://uk.wikipedia.org/wiki/%D0%97%D0%B1%D0%B8%D1%80%D0%B0%D0%BD%D0%BD%D1%8F_%D1%81%D0%BC%D1%96%D1%82%D1%82%D1%8F). Він контролює всі об’єкти та видаляє ті, які стали недосяжними. +У рушію JavaScript є фоновий процес, який називається [збирання сміття](https://uk.wikipedia.org/wiki/Збирання_сміття). Він контролює всі об’єкти та видаляє ті, які стали недосяжними. ## Простий приклад