portaldacalheta.pt
  • Основен
  • Управление На Проекти
  • Дизайн На Марката
  • Процес На Проектиране
  • Начин На Живот
Технология

Сериализиране на сложни обекти в JavaScript



Ефективност на уебсайта и кеширане на данни

Съвременните уебсайтове обикновено извличат данни от редица различни местоположения, включително бази данни и API на трети страни. Например, когато удостоверява потребител, уебсайт може да търси потребителския запис от базата данни, след което да го украси с данни от някои външни услуги чрез API повиквания. Минимизирането на скъпите обаждания към тези източници на данни, като достъп до диск за заявки към база данни и обратни пътувания до интернет за API повиквания, е от съществено значение за поддържането на бърз, отзивчив сайт. Кеширането на данни е често срещана техника за оптимизация, използвана за постигане на това.

Процесите съхраняват работните си данни в паметта. Ако уеб сървърът се изпълнява в един процес (като Node.js / Express), тогава тези данни могат лесно да бъдат кеширани с помощта на кеш памет, работещ в същия процес. Уеб сървърите с балансирано натоварване обаче обхващат множество процеси и дори когато работите с един процес, може да искате кешът да продължи, когато сървърът се рестартира. Това изисква решение за кеширане извън процеса, като Redis, което означава, че данните трябва да бъдат сериализирани по някакъв начин и десериализирани, когато се четат от кеша.



Сериализацията и десериализацията са относително лесни за постигане в статично типизирани езици като C #. Динамичното естество на JavaScript обаче прави проблема малко по-сложен. Докато ECMAScript 6 (ES6) въведе класове, полетата в тези класове (и техните типове) не се дефинират, докато не бъдат инициализирани - което може да не е, когато класът е инстанциран - и върнатите типове полета и функции не са дефинирани изобщо в схемата. Нещо повече, структурата на класа може лесно да се променя по време на изпълнение - полетата могат да се добавят или премахват, типовете могат да се променят и т.н. Въпреки че това е възможно с помощта на отражение в C #, отражението представлява „тъмните изкуства“ на този език и разработчиците очакват да наруши функционалността.



Този проблем ми беше представен по време на работа преди няколко години, когато работех в основния екип на ApeeScape. Изграждахме пъргаво табло за управление на нашите отбори, което трябваше да бъде бързо; в противен случай разработчиците и собствениците на продукти не биха го използвали. Извличахме данни от редица източници: нашата система за проследяване на работата, нашият инструмент за управление на проекти и база данни. Сайтът е изграден в Node.js / Express и имаме кеш памет, за да сведем до минимум обажданията към тези източници на данни. Нашият бърз, итеративен процес на разработка означаваше, че ние разполагахме (и следователно рестартирахме) няколко пъти на ден, като обезсилвахме кеша и по този начин загубихме много от предимствата му.



Очевидно решение беше кеш паметта извън процеса като Редис . След някои изследвания обаче установих, че не съществува добра библиотека за сериализация за JavaScript. Вградените методи JSON.stringify / JSON.parse връщат данни от типа обект, като губят всякакви функции върху прототипите на оригиналните класове. Това означаваше, че десериализираните обекти не могат просто да бъдат използвани „на място“ в нашето приложение, което следователно ще изисква значително рефакторинг, за да работи с алтернативен дизайн.

на какъв език са програмирани роботите

Изисквания към библиотеката

За да подпомогнем сериализацията и десериализацията на произволни данни в JavaScript, с десериализираните представяния и оригинали, използваеми като взаимозаменяеми, ни трябваше библиотека за сериализация със следните свойства:



  • Десериализираните представления трябва да имат същия прототип (функции, гетери, сетери) като оригиналните обекти.
  • Библиотеката трябва да поддържа вложени типове сложност (включително масиви и карти), като прототипите на вложените обекти са зададени правилно.
  • Трябва да е възможно да сериализира и десериализира едни и същи обекти няколко пъти - процесът трябва да бъде идемпотентен.
  • Форматът за сериализация трябва лесно да се предава през TCP и да се съхранява с помощта на Redis или подобна услуга.
  • Трябва да се изискват минимални промени в кода, за да се отбележи клас като сериализуем.
  • Процедурите в библиотеката трябва да са бързи.
  • В идеалния случай трябва да има някакъв начин да се поддържа десериализация на стари версии на клас чрез някакво картографиране / версиране.

Изпълнение

За да запълня тази празнина, реших да напиша Tanagra.js , библиотека за сериализация с общо предназначение за JavaScript. Името на библиотеката е препратка към един от любимите ми епизоди на Стар Трек: Следващото поколение , където екипажът на Предприятие трябва да се научи да общува с мистериозна извънземна раса, чийто език е неразбираем. Тази библиотека за сериализация поддържа общи формати за данни, за да се избегнат подобни проблеми.

Tanagra.js е проектиран да бъде опростен и лек и понастоящем поддържа Node.js (не е тестван в браузър, но на теория би трябвало да работи) и класове ES6 (включително Maps). Основната реализация поддържа JSON, а експерименталната версия поддържа буфери на Google Protocol. Библиотеката изисква само стандартен JavaScript (понастоящем тестван с ES6 и Node.js), без зависимост от експериментални функции, Бабел транспилиране, или TypeScript .



Сериализуемите класове се маркират като такива с извикване на метод, когато класът се експортира:

module.exports = serializable(Foo, myUniqueSerialisationKey)



Методът връща a пълномощник към класа, който прихваща конструктора и инжектира уникален идентификатор. (Ако не е посочено, това по подразбиране е името на класа.) Този ключ е сериализиран с останалите данни и класът също го излага като статично поле. Ако класът съдържа някакви вложени типове (т.е. членове с типове, които се нуждаят от сериализиране), те също са посочени в извикването на метод:

module.exports = serializable(Foo, [Bar, Baz], myUniqueSerialisationKey)



(Вложените типове за предишни версии на класа също могат да бъдат посочени по подобен начин, така че, например, ако сериализирате Foo1, той може да бъде десериализиран във Foo2.)

как да заобиколите проверката на възрастта с кредитна карта

По време на сериализацията библиотеката рекурсивно изгражда глобална карта на ключовете към класовете и използва това по време на десериализацията. (Не забравяйте, че ключът е сериализиран с останалите данни.) За да се знае типа на класа „най-високо ниво“, библиотеката изисква това да бъде посочено в извикването за десериализация:



const foo = decodeEntity(serializedFoo, Foo)

Експериментална библиотека за автоматично картографиране обикаля дървото на модула и генерира съпоставянията от имената на класове, но това работи само за класове с уникално име.

Оформление на проекта

Проектът е разделен на няколко модула:

как да стартирате частен фонд за недвижими имоти
  • танагра-ядро - обща функционалност, изисквана от различните сериализационни формати, включително функцията за маркиране на класове като сериализуем
  • tanagra-json - сериализира данните в JSON формат
  • tanagra-protobuf - сериализира данните във формат протобуфери на Google (експериментално)
  • tanagra-protobuf-redis-cache - помощна библиотека за съхраняване на сериализирани протобуфи в Редис
  • tanagra-auto-mapper - разхожда дървото на модула в Node.js за изграждане на карта на класове, което означава, че потребителят не трябва да посочва типа, към който да десериализира (експериментално).

Имайте предвид, че библиотеката използва правопис в САЩ.

Пример за използване

Следващият пример декларира сериализуем клас и използва модула tanagra-json, за да го сериализира / десериализира:

const serializable = require('tanagra-core').serializable class Foo { constructor(bar, baz1, baz2, fooBar1, fooBar2) { this.someNumber = 123 this.someString = 'hello, world!' this.bar = bar // a complex object with a prototype this.bazArray = [baz1, baz2] this.fooBarMap = new Map([ ['a', fooBar1], ['b', fooBar2] ]) } } // Mark class `Foo` as serializable and containing sub-types `Bar`, `Baz` and `FooBar` module.exports = serializable(Foo, [Bar, Baz, FooBar]) ... const json = require('tanagra-json') json.init() // or: // require('tanagra-protobuf') // await json.init() const foo = new Foo(bar, baz) const encoded = json.encodeEntity(foo) ... const decoded = json.decodeEntity(encoded, Foo)

производителност

Сравних производителността на двата сериализатора ( JSON сериализатор и експериментален protobufs сериализатор) с контрола (роден JSON.parse и JSON.stringify). Проведох общо 10 опита с всеки.

Тествах това на моята 2017 година Dell XPS15 лаптоп с 32Gb памет, работещ с Ubuntu 17.10.

Сериализирах следния вложен обект:

foo: { 'string': 'Hello foo', 'number': 123123, 'bars': [ { 'string': 'Complex Bar 1', 'date': '2019-01-09T18:22:25.663Z', 'baz': { 'string': 'Simple Baz', 'number': 456456, 'map': Map { 'a' => 1, 'b' => 2, 'c' => 2 } } }, { 'string': 'Complex Bar 2', 'date': '2019-01-09T18:22:25.663Z', 'baz': { 'string': 'Simple Baz', 'number': 456456, 'map': Map { 'a' => 1, 'b' => 2, 'c' => 2 } } } ], 'bazs': Map { 'baz1' => Baz { string: 'baz1', number: 111, map: Map { 'a' => 1, 'b' => 2, 'c' => 2 } }, 'baz2' => Baz { string: 'baz2', number: 222, map: Map { 'a' => 1, 'b' => 2, 'c' => 2 } }, 'baz3' => Baz { string: 'baz3', number: 333, map: Map { 'a' => 1, 'b' => 2, 'c' => 2 } } }, }

Пишете изпълнение

Метод на сериализиране Ave. inc. първо изпитание (ms) StDev. вкл. първо изпитание (ms) Пр. Напр. първо изпитание (ms) StDev. напр. първо изпитание (ms)
JSON 0,115 0,0903 0,0879 0,0256
Google Protobufs 2.00 2,748 1.13 0,278
Контролна група 0,0155 0,00726 0,0139 0,00570

Прочети

node js връща стойност от функцията
Метод на сериализиране Ave. inc. първо изпитание (ms) StDev. вкл. първо изпитание (ms) Пр. Напр. първо изпитание (ms) StDev. напр. първо изпитание (ms)
JSON 0,133 0.102 0.104 0,0429
Google Protobufs 2.62 1.12 2.28 0,364
Контролна група 0,0135 0,00729 0,0115 0,00390

Обобщение

The JSON сериализаторът е около 6-7 пъти по-бавен от родната сериализация. Експерименталният protobufs сериализаторът е около 13 пъти по-бавен от JSON сериализатор или 100 пъти по-бавно от естествената сериализация.

Освен това, вътрешното кеширане на схема / структурна информация във всеки сериализатор очевидно има ефект върху производителността. За сериализатора JSON първото записване е около четири пъти по-бавно от средното. За сериализатора protobuf е девет пъти по-бавен. Така че писането на обекти, чиито метаданни вече са кеширани, е много по-бързо във всяка една библиотека.

Същият ефект се наблюдава и при четене. За библиотеката JSON първото четене е около четири пъти по-бавно от средното, а за библиотеката protobuf е около два пъти и половина по-бавно.

Проблемите с производителността на сериализатора protobuf означават, че той все още е в експериментален етап и бих го препоръчал само ако имате нужда от формата по някаква причина. Струва си обаче да инвестирате известно време, тъй като форматът е много по-строг от JSON и следователно е по-добър за изпращане по кабела. Stack Exchange използва формата за своето вътрешно кеширане.

JSON сериализаторът очевидно е много по-ефективен, но все пак значително по-бавен от родната реализация. За малки обектни дървета тази разлика не е значителна (няколко милисекунди на върха на заявка от 50 ms няма да унищожат ефективността на вашия сайт), но това може да се превърне в проблем за изключително големи дървета на обекти и е един от приоритетите ми за развитие.

Пътна карта

Библиотеката все още е в бета фаза. JSON сериализаторът е сравнително добре тестван и стабилен. Ето пътната карта за следващите няколко месеца:

  • Подобрения в производителността и на двата сериализатора
  • По-добра поддръжка за JavaScript преди ES6
  • Поддръжка за декоратори ES-Next

Не знам за друга библиотека на JavaScript, която да поддържа сериализиране на сложни, вложени обектни данни и десериализиране до първоначалния си тип. Ако внедрявате функционалност, която би се възползвала от библиотеката, моля, опитайте, свържете се с отзивите си и помислете за принос.

как да кодирам c++

Начална страница на проекта
Хранилище на GitHub

Разбиране на основите

Как се съхраняват обектите в JavaScript?

Като цяло обектите не се съхраняват. Те се инстанцират, когато е необходимо, използват се при обработка, след което се премахват от паметта, когато вече не са необходими. Ако трябва да използваме временно данни на друго място, ние сериализираме и десериализираме тези данни в друга структура.

Какво представлява JavaScript обектът?

Обектът е парче код, което капсулира структура, заедно с операции, които могат да бъдат изпълнени върху тази структура. Като цяло той е същият като обект във всеки обектно-ориентиран език за програмиране.

Какво е обект на данни?

Обектът от данни е код, който временно съдържа данни от хранилище за данни, така че да може да бъде прочетен или обработен в приложение. Освен ако няма начин тези данни да се запазят в паметта, те се записват обратно или по друг начин не се задържат, когато обектът излезе извън обхвата или по друг начин не е необходим.

Защо се нуждаем от сериализация и десериализация?

Сериализацията ни позволява да съхраняваме данни за използване в текущия процес или други процеси, ако е необходимо. Съхраняваме данните, след което десериализираме, когато се използват другаде.

Рационализирайте софтуерната интеграция: Урок за Apache Camel

Back-End

Рационализирайте софтуерната интеграция: Урок за Apache Camel
eCommerce UX - основни стратегии и принципи на дизайна

eCommerce UX - основни стратегии и принципи на дизайна

Дизайн На Марката

Популярни Публикации
Изцеление на скъсани вериги за доставки: производство извън Китай
Изцеление на скъсани вериги за доставки: производство извън Китай
Включете Angular 2: Надстройка от 1.5
Включете Angular 2: Надстройка от 1.5
Урок за работен поток за проектиране за разработчици: Осигурете по-добър UI / UX навреме
Урок за работен поток за проектиране за разработчици: Осигурете по-добър UI / UX навреме
PHP Frameworks: Избор между Symfony и Laravel
PHP Frameworks: Избор между Symfony и Laravel
Шевморфизъм, плосък дизайн и възходът на типографския дизайн
Шевморфизъм, плосък дизайн и възходът на типографския дизайн
 
.NET Core - да станем диви и с отворен код. Microsoft, какво ти отне толкова време ?!
.NET Core - да станем диви и с отворен код. Microsoft, какво ти отне толкова време ?!
Крайно ръководство за езика за обработка, част I: Основите
Крайно ръководство за езика за обработка, част I: Основите
Ractive.js - Уеб приложения, направени лесно
Ractive.js - Уеб приложения, направени лесно
Защо има толкова много Pythons?
Защо има толкова много Pythons?
Съвети и инструменти за оптимизиране на приложения за Android
Съвети и инструменти за оптимизиране на приложения за Android
Популярни Публикации
  • http //api.streamin.to/pair
  • как да намеря някой номер на кредитна карта
  • как се прави физически двигател
  • най-добрите ресурси за изучаване на C++
  • как да стартирате фонд за търсене
  • каква корпорация е ООД
Категории
  • Управление На Проекти
  • Дизайн На Марката
  • Процес На Проектиране
  • Начин На Живот
  • © 2022 | Всички Права Запазени

    portaldacalheta.pt