{"id":334428,"date":"2022-06-14T03:00:47","date_gmt":"2022-06-14T03:00:47","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=334428"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=334428","title":{"rendered":"<span>WebAssembly \u043e\u0431\u044a\u0435\u0434\u0438\u043d\u0438\u0442 \u0438\u0445 \u0432\u0441\u0435\u0445<\/span>"},"content":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/9a8\/032\/cd3\/9a8032cd363d25d1fe9f1ed5245850cf.png\" width=\"1056\" height=\"203\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/9a8\/032\/cd3\/9a8032cd363d25d1fe9f1ed5245850cf.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u0431\u044b \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043a \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u043d\u0430 WebAssembly. \u042d\u0442\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 Go, C++, Rust, \u0435\u0441\u043b\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043e\u043d \u0435\u0441\u0442\u044c. \u0410 \u0442\u0430\u043a \u0436\u0435 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u0441\u044f \u043e\u0442 so\/dll, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 Windows, OSX, GNU\/Linux. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0448\u0435\u043b \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 Envoy.<\/p>\n<h3>\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f Envoy<\/h3>\n<p>\u041d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e 2019 Envoy \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a, \u0432\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438 \u043d\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 Envoy. \u0414\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u044e\u0442 \u0441\u0432\u043e\u0438 \u0434\u0435\u043f\u043b\u043e\u0439, \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u0432\u0441\u0435\u0433\u043e Envoy.   <\/p>\n<h3>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/h3>\n<ul>\n<li>\n<p><strong>\u0413\u0438\u0431\u043a\u043e\u0441\u0442\u044c<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041b\u044e\u0431\u044b\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0440\u0435\u0434\u0438\u043f\u043b\u043e\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0438 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044f. <\/strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u043f\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044e CPU \u0438 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u0441 \u0447\u0435\u0442\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c API \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 \u043f\u0440\u043e\u043a\u0441\u0438(envoy, <a href=\"https:\/\/github.com\/api7\/wasm-nginx-module\" rel=\"noopener noreferrer nofollow\">nginx<\/a> \u0438 \u0442.\u0434.). \u0418\u043c\u0435\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435.<\/strong> \u0411\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u044b\u0431\u043e\u0440 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 WebAssembly, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0441 \u043b\u044e\u0431\u044b\u043c \u043e\u043f\u044b\u0442\u043e\u043c(C, Go, Rust, Java, TypeScript, \u0438 \u0442.\u0434.) \u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u043e\u0441\u0442\u044c<\/strong>. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u0435\u0436\u0434\u0443 \u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u043e\u0439 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Proxy-Wasm, \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/github.com\/proxy-wasm\/spec#servers\" rel=\"noopener noreferrer nofollow\">Envoy, NGINX, ATS<\/a>  \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 gRPC (\u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442).<\/p>\n<\/li>\n<\/ul>\n<h3>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/h3>\n<ul>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d, \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 \u0438 \u0438\u0437 \u043d\u0435\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f CPU-bound \u0437\u0430\u0434\u0430\u0447. \u041e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u0434\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c \u0432 2 \u0440\u0430\u0437\u0430 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f Wasm. \u042d\u0442\u043e ~20 MB \u0434\u043b\u044f WAVM \u0438 ~10 MB \u0434\u043b\u044f V8.<\/p>\n<\/li>\n<li>\n<p>\u042d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 WebAssembly \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u043b\u043e\u0434\u0430, \u0438 \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0435\u043d\u0430 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0433\u0434\u0435 JavaScript \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<h2>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/h2>\n<p>\u0412 Envoy \u0432\u0437\u044f\u043b\u0438 C++ API, \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 Wasm VM \u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u044b\u0437\u043e\u0432\u044b \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u044c. <\/p>\n<figure class=\"bordered full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/bfc\/351\/26c\/bfc35126cc5398d8adeaf06e0dc8328d.png\" width=\"1024\" height=\"768\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/bfc\/351\/26c\/bfc35126cc5398d8adeaf06e0dc8328d.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043e\u0434\u043d\u043e\u043c wasm \u043c\u043e\u0434\u0443\u043b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b Wasm VM \u0440\u0430\u0437\u043c\u043d\u043e\u0436\u0435\u043d\u044b \u0438 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u044b \u0432 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Thread-local_storage\" rel=\"noopener noreferrer nofollow\">thread-local storage<\/a><\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/7f3\/953\/a19\/7f3953a191107282a389977cbfc7df61.png\" width=\"2321\" height=\"1190\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/7f3\/953\/a19\/7f3953a191107282a389977cbfc7df61.png\"\/><figcaption><\/figcaption><\/figure>\n<p>\u041a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c\u0438 Wasm VM \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430\u043c\u0438 shared data \u0438 message queue. \u0421\u043b\u0443\u0436\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f singleton \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 Envoy. \u041e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c \u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u043b\u043e\u0433\u0438, \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0438 \u0442.\u0434.<\/p>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/r\/w1560\/getpro\/habr\/upload_files\/1a1\/532\/48b\/1a153248b9c4d6064decdf55b1e99f4d.png\" width=\"1278\" height=\"609\" data-src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/1a1\/532\/48b\/1a153248b9c4d6064decdf55b1e99f4d.png\"\/><figcaption><\/figcaption><\/figure>\n<h3>\u0420\u0430\u043d\u0442\u0430\u0439\u043c<\/h3>\n<p>Wasm VM \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u0432<\/p>\n<ul>\n<li>\n<p>V8<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/bytecodealliance\/wasm-micro-runtime\" rel=\"noopener noreferrer nofollow\">WAMR<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/bytecodealliance\/wasmtime\" rel=\"noopener noreferrer nofollow\">Wasmtime<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/WAVM\/WAVM\" rel=\"noopener noreferrer nofollow\">WAVM<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f ABI \u0440\u0430\u0437\u0431\u0438\u0442\u0430 \u043d\u0430 \u0434\u0432\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u043b\u043e\u043a\u0430: \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 <a href=\"https:\/\/github.com\/proxy-wasm\/spec\/blob\/master\/abi-versions\/vNEXT\/README.md#functions-implemented-in-the-wasm-module\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0434\u0443\u043b\u0435<\/a> \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 <a href=\"https:\/\/github.com\/proxy-wasm\/spec\/blob\/master\/abi-versions\/vNEXT\/README.md#functions-implemented-in-the-host-environment\" rel=\"noopener noreferrer nofollow\">\u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u0435<\/a>. \u0412\u044b\u0434\u0435\u043b\u044e \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 <code>proxy_on_memory_allocate<\/code>, \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 <code>_start<\/code>.<\/p>\n<p>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>proxy_log<\/code><\/p>\n<p> \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>i32 (proxy_log_level_t) log_level<\/code><\/p>\n<\/li>\n<li>\n<p><code>i32 (const char*) message_data<\/code><\/p>\n<\/li>\n<li>\n<p><code>i32 (size_t) message_size<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p><code>i32 (proxy_result_t) call_result<\/code><\/p>\n<\/li>\n<\/ul>\n<p>i32 \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439 <a href=\"https:\/\/webassembly.github.io\/spec\/core\/bikeshed\/#types\" rel=\"noopener noreferrer nofollow\">\u0442\u0438\u043f \u0432 wasm<\/a>, \u0430 \u0442\u0430\u043a \u043e\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 SDK<\/p>\n<pre><code class=\"cpp\">extern \"C\" WasmResult proxy_log(LogLevel level,                                 const char *logMessage,                                 size_t messageSize);<\/code><\/pre>\n<pre><code class=\"go\">package internal  \/\/export proxy_log func ProxyLog(logLevel LogLevel,               messageData *byte,               messageSize int) Status<\/code><\/pre>\n<pre><code class=\"coffeescript\">\/\/ @ts-ignore: decorator @external(\"env\", \"proxy_log\") export declare function proxy_log(level: LogLevel,                                   logMessage: ptr&lt;char>,                                   messageSize: size_t): WasmResult;<\/code><\/pre>\n<h3>\u0412\u043b\u0430\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u044c\u044e<\/h3>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0442\u0435\u043c \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0445\u043e\u0441\u0442\u0430 \u0438 \u043f\u0430\u043c\u044f\u0442\u044c \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u0435. \u041d\u0438\u043a\u0430\u043a\u0430\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e wasm \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u0430\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435.  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>proxy_on_http_request_body<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432 \u0432 \u0442\u0435\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>proxy_get_buffer<\/code>. \u041a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u0445\u043e\u0441\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u043e\u043c\u044f\u0442\u044c \u0443 wasm \u043c\u043e\u0434\u0443\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>proxy_on_memory_allocate<\/code>, <strong><em>\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442<\/em><\/strong> \u0442\u0443\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 <strong><em>\u043e\u0442\u0434\u0430\u0435\u0442<\/em><\/strong> \u043f\u0430\u043c\u044f\u0442\u044c \u0432\u043e \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u0435 wasm \u043c\u043e\u0434\u0443\u043b\u044e, \u0432 \u043d\u0430\u0434\u0435\u0436\u0434\u0435, \u0447\u0442\u043e \u043e\u043d \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442 \u0435\u0435. <\/p>\n<h3>proxy_on_memory_allocate<\/h3>\n<p>\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>i32 (size_t) memory_size<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p><code>i32 (void*) allocated_ptr<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 AssemblyScript <a href=\"https:\/\/github.com\/solo-io\/proxy-runtime\/blob\/master\/assembly\/malloc.ts\" rel=\"noopener noreferrer nofollow\">malloc.ts<\/a><\/p>\n<pre><code class=\"javascript\">import {   __pin,   __unpin, } from \"rt\/itcms\";  \/\/\/ Allow host to allocate memory. export function malloc(size: i32): usize {   let buffer = new ArrayBuffer(size);   let ptr = changetype&lt;usize>(buffer);   return __pin(ptr); }  \/\/\/ Allow host to free memory. export function free(ptr: usize): void {   __unpin(ptr); }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<pre><code class=\"javascript\">class ArrayBufferReference {   private buffer: usize;   private size: usize;    constructor() {   }    sizePtr(): usize {     return changetype&lt;usize>(this) + offsetof&lt;ArrayBufferReference>(\"size\");   }   bufferPtr(): usize {     return changetype&lt;usize>(this) + offsetof&lt;ArrayBufferReference>(\"buffer\");   }    \/\/ Before calling toArrayBuffer below, you must call out to the host to fill in the values.   \/\/ toArrayBuffer below **must** be called once and only once.   toArrayBuffer(): ArrayBuffer {     if (this.size == 0) {       return new ArrayBuffer(0);     }      let array = changetype&lt;ArrayBuffer>(this.buffer);     \/\/ host code used malloc to allocate this buffer.     \/\/ release the allocated ptr. array variable will retain it, so it won't be actually free (as it is ref counted).     free(this.buffer);     \/\/ should we return a this sliced up to size?     return array;   } }<\/code><\/pre>\n<p>\u0412 AssemblyScript \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u044e\u044e \u0441\u0440\u0435\u0434\u0443(\u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432 JS). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/www.assemblyscript.org\/runtime.html#interface\" rel=\"noopener noreferrer nofollow\">__pin\/__unpin<\/a>, \u0447\u0442\u043e \u0431\u044b \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043d\u0435 \u0441\u043e\u0431\u0440\u0430\u043b \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0436\u0435 \u043d\u0435\u0442 \u0441\u0441\u044b\u043b\u043e\u043a. \u0412 Go<\/p>\n<pre><code class=\"go\">\/\/nolint \/\/export proxy_on_memory_allocate func proxyOnMemoryAllocate(size uint) *byte { buf := make([]byte, size) return &amp;buf[0] }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<pre><code class=\"go\">import ( \"reflect\" \"unsafe\" )  func RawBytePtrToString(raw *byte, size int) string { \/\/nolint return *(*string)(unsafe.Pointer(&amp;reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(raw)), Len:  size, Cap:  size, })) }  func RawBytePtrToByteSlice(raw *byte, size int) []byte { \/\/nolint return *(*[]byte)(unsafe.Pointer(&amp;reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(raw)), Len:  size, Cap:  size, })) }<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c? \u0412 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/go.dev\/ref\/spec\" rel=\"noopener noreferrer nofollow\">Go<\/a> \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u043c\u0443\u0441\u043e\u0440\u0430. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441 <a href=\"https:\/\/go.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/go.dev\/<\/a> \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043d\u0430 \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 Go \u0432 \u0421\u0438. \u0415\u0441\u0442\u044c \u043f\u0430\u043a\u0435\u0442<a href=\"https:\/\/github.com\/mattn\/go-pointer\" rel=\"noopener noreferrer nofollow\"> go-pointer<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 pin\/unpin \u0438\u0437 AssemblyScript.<\/p>\n<pre><code class=\"go\">C.pass_pointer(pointer.Save(&amp;s)) v := *(pointer.Restore(C.get_from_pointer()).(*string))<\/code><\/pre>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439<\/p>\n<pre><code class=\"go\">package pointer  \/\/ #include &lt;stdlib.h> import \"C\" import ( \"sync\" \"unsafe\" )  var ( mutex sync.RWMutex store = map[unsafe.Pointer]interface{}{} )  func Save(v interface{}) unsafe.Pointer { if v == nil { return nil }  \/\/ Generate real fake C pointer. \/\/ This pointer will not store any data, but will bi used for indexing purposes. \/\/ Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte. \/\/ Why we need indexing, because Go doest allow C code to store pointers to Go data. var ptr unsafe.Pointer = C.malloc(C.size_t(1)) if ptr == nil { panic(\"can't allocate 'cgo-pointer hack index pointer': ptr == nil\") }  mutex.Lock() store[ptr] = v mutex.Unlock()  return ptr }<\/code><\/pre>\n<p><strong>\u041d\u041e<\/strong> \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <strong>TinyGo<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043f\u043e\u043f\u0440\u043e\u0449\u0435 \u0438 <a href=\"https:\/\/tinygo.org\/docs\/reference\/lang-support\/#garbage-collection\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f<\/a> \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u043a\u0443\u0447\u0435. \u0415\u0441\u043b\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>proxy_on_memory_allocate<\/code> \u0438 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u044f \u0432 Go \u043d\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438, \u0442\u043e \u044d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e.<\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0432 C++ SDK <code>proxy_on_memory_allocate<\/code> \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435. \u0418\u0434\u0435\u0442 \u043f\u043e\u0438\u0441\u043a malloc, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440<\/p>\n<pre><code class=\"bash\">$ em++ --no-entry -s EXPORTED_FUNCTIONS=['_malloc'] ... <\/code><\/pre>\n<p>\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0445\u043e\u0441\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a <code>malloc<\/code>, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u0438\u0449\u0435\u0442\u0441\u044f <code>proxy_on_memory_allocate<\/code><\/p>\n<pre><code class=\"cpp\">void WasmBase::getFunctions() { #define _GET(_fn) wasm_vm_->getFunction(#_fn, &amp;_fn##_); #define _GET_ALIAS(_fn, _alias) wasm_vm_->getFunction(#_alias, &amp;_fn##_);   _GET(_initialize);   if (_initialize_) {     _GET(main);   } else {     _GET(_start);   }    _GET(malloc);   if (!malloc_) {     _GET_ALIAS(malloc, proxy_on_memory_allocate);   }   if (!malloc_) {     fail(FailState::MissingFunction, \"Wasm module is missing malloc function.\");   } #undef _GET_ALIAS #undef _GET    \/\/ Try to point the capability to one of the module exports, if the capability has been allowed. #define _GET_PROXY(_fn)                                                                            \\   if (capabilityAllowed(\"proxy_\" #_fn)) {                                                          \\     wasm_vm_->getFunction(\"proxy_\" #_fn, &amp;_fn##_);                                                 \\   } else {                                                                                         \\     _fn##_ = nullptr;                                                                              \\   } #define _GET_PROXY_ABI(_fn, _abi)                                                                  \\   if (capabilityAllowed(\"proxy_\" #_fn)) {                                                          \\     wasm_vm_->getFunction(\"proxy_\" #_fn, &amp;_fn##_abi##_);                                           \\   } else {                                                                                         \\     _fn##_abi##_ = nullptr;                                                                        \\   }    FOR_ALL_MODULE_FUNCTIONS(_GET_PROXY);    if (abiVersion() == AbiVersion::ProxyWasm_0_1_0) {     _GET_PROXY_ABI(on_request_headers, _abi_01);     _GET_PROXY_ABI(on_response_headers, _abi_01);   } else if (abiVersion() == AbiVersion::ProxyWasm_0_2_0 ||              abiVersion() == AbiVersion::ProxyWasm_0_2_1) {     _GET_PROXY_ABI(on_request_headers, _abi_02);     _GET_PROXY_ABI(on_response_headers, _abi_02);     _GET_PROXY(on_foreign_function);   } #undef _GET_PROXY_ABI #undef _GET_PROXY }<\/code><\/pre>\n<h3>\u0422\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 _start<\/h3>\n<p>\u041d\u0430\u043f\u0438\u0441\u0430\u0432 \u0432 Go<\/p>\n<pre><code class=\"go\">package main  import ( \"math\/rand\" \"time\"  \"github.com\/tetratelabs\/proxy-wasm-go-sdk\/proxywasm\" \"github.com\/tetratelabs\/proxy-wasm-go-sdk\/proxywasm\/types\" )  const tickMilliseconds uint32 = 1000  func main() { proxywasm.SetVMContext(&amp;vmContext{}) }  type vmContext struct { \/\/ Embed the default VM context here, \/\/ so that we don't need to reimplement all the methods. types.DefaultVMContext }<\/code><\/pre>\n<p>AssemblyScript<\/p>\n<pre><code class=\"javascript\">export * from \"@solo-io\/proxy-runtime\/proxy\"; \/\/ this exports the required functions for the proxy to interact with us. import { RootContext, Context, registerRootContext, FilterHeadersStatusValues, stream_context } from \"@solo-io\/proxy-runtime\";  class AddHeaderRoot extends RootContext {   createContext(context_id: u32): Context {     return new AddHeader(context_id, this);   } }  class AddHeader extends Context {   constructor(context_id: u32, root_context: AddHeaderRoot) {     super(context_id, root_context);   }   onResponseHeaders(a: u32, end_of_stream: bool): FilterHeadersStatusValues {     const root_context = this.root_context;     if (root_context.getConfiguration() == \"\") {       stream_context.headers.response.add(\"hello\", \"world!\");     } else {       stream_context.headers.response.add(\"hello\", root_context.getConfiguration());     }     return FilterHeadersStatusValues.Continue;   } }  registerRootContext((context_id: u32) => { return new AddHeaderRoot(context_id); }, \"add_header\");<\/code><\/pre>\n<p>C++<\/p>\n<pre><code class=\"cpp\">#include &lt;string> #include &lt;string_view> #include &lt;stdlib.h>  #include \"proxy_wasm_intrinsics.h\"  class ExampleContext : public Context { public:   explicit ExampleContext(uint32_t id, RootContext *root) : Context(id, root) {}    FilterHeadersStatus onRequestHeaders(uint32_t headers, bool end_of_stream) override; };  static RegisterContextFactory register_ExampleContext(CONTEXT_FACTORY(ExampleContext));   FilterHeadersStatus ExampleContext::onRequestHeaders(uint32_t, bool) {   LOG_DEBUG(std::string(\"print from wasm, onRequestHeaders, context id: \") + std::to_string(id()));    auto result = getRequestHeaderPairs();   auto pairs = result->pairs();   for (auto &amp;p : pairs) {     LOG_INFO(std::string(\"print from wasm, \") + std::string(p.first) + std::string(\" -> \") + std::string(p.second));   }    return FilterHeadersStatus::Continue; }<\/code><\/pre>\n<p>\u041d\u0443\u0436\u043d\u0430 \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430, \u043a\u043e\u0442\u043e\u0440\u0430\u044f \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u0435\u0442 \u0440\u0430\u043d\u0442\u0430\u0439\u043c C++\/Go\/AssemblyScript \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u0438\u0442 \u0447\u0442\u043e-\u043d\u0438\u0431\u0443\u0434\u044c \u0432\u0438\u0434\u0430 main<abbr title=\"WebAssembly System Interface\" type=\"abbr\">.<\/abbr> <abbr title=\"WebAssembly System Interface\" type=\"abbr\">WASI<\/abbr> \u0434\u043b\u044f \u0442\u0430\u043a\u0438\u0445 \u0446\u0435\u043b\u0435\u0439 \u043f\u0440\u0435\u0434\u043b\u0430\u0433\u0430\u0435\u0442<a href=\"https:\/\/nodejs.org\/api\/wasi.html\" rel=\"noopener noreferrer nofollow\"> _start \u0438 _initialize<\/a>. \u0425\u043e\u0442\u044f \u0432 \u0441\u043f\u0435\u043a\u0435 \u0435\u0441\u0442\u044c \u0442\u043e\u043b\u044c\u043a\u043e _start, \u043d\u043e \u043d\u0430 \u0445\u043e\u0441\u0442\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b \u043e\u0431\u0430 \u0432\u0430\u0440\u0438\u0430\u043d\u0442\u0430<\/p>\n<pre><code class=\"cpp\">class WasmBase : public std::enable_shared_from_this&lt;WasmBase> {  \/\/s.. protected:   \/\/...   WasmCallVoid&lt;0> _initialize_; \/* WASI reactor (Emscripten v1.39.17+, Rust nightly) *\/   WasmCallVoid&lt;0> _start_;      \/* WASI command (Emscripten v1.39.0+, TinyGo) *\/    WasmCallWord&lt;2> main_;   WasmCallWord&lt;1> malloc_;   \/\/... };<\/code><\/pre>\n<h3>\u0421\u0442\u0440\u043e\u043a\u0438 \u0438 \u0430\u0441\u0441\u043e\u0446\u0438\u0430\u0442\u0438\u0432\u043d\u044b\u0439 \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u044b<\/h3>\n<p>\u041e\u0434\u0438\u043d \u0438\u0437 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u043e\u0432 \u044d\u0442\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438. \u041c\u043e\u0436\u0435\u0442 \u043f\u043e\u0442\u0440\u0435\u0431\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u043d\u0435 \u0442\u043e\u043b\u044c\u043a\u043e \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u0435, \u043d\u043e \u0438 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435. \u0412 Go \u0441\u0442\u0440\u043e\u043a\u0438 \u044d\u0442\u043e \u043f\u0440\u043e\u0441\u0442\u043e <a href=\"https:\/\/go.dev\/ref\/spec#String_types\" rel=\"noopener noreferrer nofollow\">\u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0431\u0430\u0439\u0442<\/a>, \u043d\u043e \u043e\u0431\u044b\u0447\u043d\u043e \u0442\u0430\u043c UTF-8. \u0412 AssemblyScript\u044d\u0442\u043e \u043f\u043e\u0441\u043b\u0435\u0434\u043e\u0432\u0430\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c UCS-2 \u0438 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u044f.<\/p>\n<pre><code class=\"javascript\">export function log(level: LogLevelValues, logMessage: string): void {   \/\/ from the docs:   \/\/ Like JavaScript, AssemblyScript stores strings in UTF-16 encoding represented by the API as UCS-2,    let buffer = String.UTF8.encode(logMessage);   imports.proxy_log(level as imports.LogLevel, changetype&lt;usize>(buffer), buffer.byteLength); }<\/code><\/pre>\n<p>\u0410 \u043f\u0435\u0440\u0435\u0434\u0430\u0447\u0430 \u043f\u0440\u0438\u0432\u044b\u0447\u043d\u043e\u0433\u043e \u043a\u043e\u043d\u0442\u0435\u0439\u043d\u0435\u0440\u0430 map \u043f\u043e\u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u0434\u043e\u043f\u043e\u043b\u043d\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0439 \u0443\u043f\u0430\u043a\u043e\u0432\u043a\u0438\/\u0440\u0430\u0441\u043f\u0430\u043a\u043e\u0432\u043a\u0438<\/p>\n<pre><code class=\"go\">func DeserializeMap(bs []byte) [][2]string { numHeaders := binary.LittleEndian.Uint32(bs[0:4]) var sizeIndex = 4 var dataIndex = 4 + 4*2*int(numHeaders) ret := make([][2]string, numHeaders) for i := 0; i &lt; int(numHeaders); i++ { keySize := int(binary.LittleEndian.Uint32(bs[sizeIndex : sizeIndex+4])) sizeIndex += 4 keyPtr := bs[dataIndex : dataIndex+keySize] key := *(*string)(unsafe.Pointer(&amp;keyPtr)) dataIndex += keySize + 1  valueSize := int(binary.LittleEndian.Uint32(bs[sizeIndex : sizeIndex+4])) sizeIndex += 4 valuePtr := bs[dataIndex : dataIndex+valueSize] value := *(*string)(unsafe.Pointer(&amp;valuePtr)) dataIndex += valueSize + 1 ret[i] = [2]string{key, value} } return ret }  func SerializeMap(ms [][2]string) []byte { size := 4 for _, m := range ms { \/\/ key\/value's bytes + len * 2 (8 bytes) + nil * 2 (2 bytes) size += len(m[0]) + len(m[1]) + 10 }  ret := make([]byte, size) binary.LittleEndian.PutUint32(ret[0:4], uint32(len(ms)))  var base = 4 for _, m := range ms { binary.LittleEndian.PutUint32(ret[base:base+4], uint32(len(m[0]))) base += 4 binary.LittleEndian.PutUint32(ret[base:base+4], uint32(len(m[1]))) base += 4 }  for _, m := range ms { for i := 0; i &lt; len(m[0]); i++ { ret[base] = m[0][i] base++ } base++ \/\/ nil  for i := 0; i &lt; len(m[1]); i++ { ret[base] = m[1][i] base++ } base++ \/\/ nil } return ret }<\/code><\/pre>\n<pre><code class=\"javascript\">function serializeHeaders(headers: Headers): ArrayBuffer {   let result = new ArrayBuffer(pairsSize(headers));   let sizes = Uint32Array.wrap(result, 0, 1 + 2 * headers.length);   sizes[0] = headers.length;    \/\/ header sizes:   let index = 1;    \/\/ for in loop doesn't seem to be supported..   for (let i = 0; i &lt; headers.length; i++) {     let header = headers[i];     sizes[index] = header.key.byteLength;     index++;     sizes[index] = header.value.byteLength;     index++;   }    let data = Uint8Array.wrap(result, sizes.byteLength);    let currentOffset = 0;   \/\/ for in loop doesn't seem to be supported..   for (let i = 0; i &lt; headers.length; i++) {     let header = headers[i];     \/\/ i'm sure there's a better way to copy, i just don't know what it is :\/     let wrappedKey = Uint8Array.wrap(header.key);     let keyData = data.subarray(currentOffset, currentOffset + wrappedKey.byteLength);     for (let i = 0; i &lt; wrappedKey.byteLength; i++) {       keyData[i] = wrappedKey[i];     }     currentOffset += wrappedKey.byteLength + 1; \/\/ + 1 for terminating nil      let wrappedValue = Uint8Array.wrap(header.value);     let valueData = data.subarray(currentOffset, currentOffset + wrappedValue.byteLength);     for (let i = 0; i &lt; wrappedValue.byteLength; i++) {       valueData[i] = wrappedValue[i];     }     currentOffset += wrappedValue.byteLength + 1; \/\/ + 1 for terminating nil   }   return result; }  function deserializeHeaders(headers: ArrayBuffer): Headers {   if (headers.byteLength == 0) {     return [];   }   let numheaders = Uint32Array.wrap(headers, 0, 1)[0];   let sizes = Uint32Array.wrap(headers, sizeof&lt;u32>(), 2 * numheaders);   let data = headers.slice(sizeof&lt;u32>() * (1 + 2 * numheaders));   let result: Headers = [];   let sizeIndex = 0;   let dataIndex = 0;   \/\/ for in loop doesn't seem to be supported..   for (let i: u32 = 0; i &lt; numheaders; i++) {     let keySize = sizes[sizeIndex];     sizeIndex++;     let header_key_data = data.slice(dataIndex, dataIndex + keySize);     dataIndex += keySize + 1; \/\/ +1 for nil termination.      let valueSize = sizes[sizeIndex];     sizeIndex++;     let header_value_data = data.slice(dataIndex, dataIndex + valueSize);     dataIndex += valueSize + 1; \/\/ +1 for nil termination.      let pair = new HeaderPair(header_key_data, header_value_data);     result.push(pair);   }    return result; }<\/code><\/pre>\n<p>\u041d\u0430 \u044d\u0442\u043e\u043c \u0432\u0441\u0435. \u041f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0441\u0441\u044b\u043b\u043a\u0438<\/p>\n<ul>\n<li>\n<p><a href=\"https:\/\/github.com\/proxy-wasm\/spec\" rel=\"noopener noreferrer nofollow\">WebAssembly for Proxies (ABI specification)<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/youtu.be\/XdWmm_mtVXI\" rel=\"noopener noreferrer nofollow\">Extending Envoy with WebAssembly &#8212; John Plevyak &amp; Dhi Aurrahman, Tetrate<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/solo-io\/proxy-runtime\" rel=\"noopener noreferrer nofollow\">AssemblyScript SDK<\/a>, <a href=\"https:\/\/github.com\/proxy-wasm\/proxy-wasm-cpp-sdk\" rel=\"noopener noreferrer nofollow\">C++ SDK<\/a>, <a href=\"https:\/\/github.com\/tetratelabs\/proxy-wasm-go-sdk\" rel=\"noopener noreferrer nofollow\">Go (TinyGo) SDK<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/proxy-wasm\/proxy-wasm-cpp-host\" rel=\"noopener noreferrer nofollow\">C++ Host<\/a>, <a href=\"https:\/\/github.com\/mosn\/proxy-wasm-go-host\" rel=\"noopener noreferrer nofollow\">Go Host<\/a><\/p>\n<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<div class=\"v-portal\" style=\"display:none;\"><\/div>\n<\/div>\n<p> <!----> <!----><br \/> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/post\/671048\/\"> https:\/\/habr.com\/ru\/post\/671048\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<div><\/div>\n<div id=\"post-content-body\">\n<div>\n<div class=\"article-formatted-body article-formatted-body article-formatted-body_version-2\">\n<div xmlns=\"http:\/\/www.w3.org\/1999\/xhtml\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0417\u0430\u0434\u0443\u043c\u0430\u043b\u0441\u044f \u043e \u0442\u043e\u043c \u0447\u0442\u043e \u0431\u044b \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u0442\u044c \u043a \u0441\u0432\u043e\u0435\u043c\u0443 \u043f\u0435\u0442 \u043f\u0440\u043e\u0435\u043a\u0442\u0443 \u0441\u0438\u0441\u0442\u0435\u043c\u0443 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432 \u043d\u0430 WebAssembly. \u042d\u0442\u043e \u043f\u043e\u0442\u0435\u043d\u0446\u0438\u0430\u043b\u044c\u043d\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u0438\u0442 \u043f\u0435\u0440\u0435\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c \u0441\u0443\u0449\u0435\u0441\u0442\u0432\u0443\u044e\u0449\u0438\u0439 \u043a\u043e\u0434 \u043d\u0430 Go, C++, Rust, \u0435\u0441\u043b\u0438 \u043a\u043e\u043d\u0435\u0447\u043d\u043e \u0436\u0435 \u043e\u043d \u0435\u0441\u0442\u044c. \u0410 \u0442\u0430\u043a \u0436\u0435 \u0438\u0437\u0431\u0430\u0432\u0438\u0442\u0441\u044f \u043e\u0442 so\/dll, \u0447\u0442\u043e \u0443\u0434\u043e\u0431\u043d\u043e \u043f\u0440\u0438 \u0440\u0430\u0441\u043f\u0440\u043e\u0441\u0442\u0440\u0430\u043d\u0435\u043d\u0438\u0438 \u043f\u043b\u0430\u0433\u0438\u043d\u043e\u0432, \u043a\u043e\u0433\u0434\u0430 \u043f\u0440\u043e\u0435\u043a\u0442 \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0434\u0435\u0441\u043a\u0442\u043e\u043f\u043d\u043e\u0435 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0435 \u0438 \u0441\u043e\u0431\u0438\u0440\u0430\u0435\u0442\u0441\u044f \u043f\u043e\u0434 Windows, OSX, GNU\/Linux. \u041f\u043e\u044d\u0442\u043e\u043c\u0443 \u043f\u043e\u0448\u0435\u043b \u0441\u043c\u043e\u0442\u0440\u0435\u0442\u044c \u043a\u0430\u043a \u044d\u0442\u043e \u0441\u0434\u0435\u043b\u0430\u043d\u043e \u0432 Envoy.<\/p>\n<h3>\u041f\u0440\u0435\u0434\u044b\u0441\u0442\u043e\u0440\u0438\u044f Envoy<\/h3>\n<p>\u041d\u0430 \u043d\u0430\u0447\u0430\u043b\u043e 2019 Envoy \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u0441\u043e\u0431\u043e\u0439 \u0441\u0442\u0430\u0442\u0438\u0447\u0435\u0441\u043a\u0438\u0439 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a \u0441\u043e \u0432\u0441\u0435\u043c\u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u044b\u043c\u0438 \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0441\u0431\u043e\u0440\u043a\u0438, \u043f\u043e\u044d\u0442\u043e\u043c\u0443 \u043d\u0443\u0436\u043d\u043e \u043f\u043e\u0434\u0434\u0435\u0440\u0436\u0438\u0432\u0430\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u044b\u0445 \u0441\u0431\u043e\u0440\u043e\u043a, \u0432\u043c\u0435\u0441\u0442\u043e \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u044f \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0433\u043e \u0438 \u043d\u0435 \u043c\u043e\u0434\u0438\u0444\u0438\u0446\u0438\u0440\u043e\u0432\u0430\u043d\u043d\u043e\u0433\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u043e\u0433\u043e \u0444\u0430\u0439\u043b\u0430 Envoy. \u0414\u043b\u044f \u043f\u0440\u043e\u0435\u043a\u0442\u043e\u0432, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043d\u0435 \u043a\u043e\u043d\u0442\u0440\u043e\u043b\u0438\u0440\u0443\u044e\u0442 \u0441\u0432\u043e\u0438 \u0434\u0435\u043f\u043b\u043e\u0439, \u0435\u0449\u0435 \u0431\u043e\u043b\u0435\u0435 \u043f\u0440\u043e\u0431\u043b\u0435\u043c\u0430\u0442\u0438\u0447\u043d\u043e, \u043f\u043e\u0442\u043e\u043c\u0443 \u0447\u0442\u043e \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u0435 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439 \u0442\u0440\u0435\u0431\u0443\u0435\u0442 \u043f\u0435\u0440\u0435\u0441\u0431\u043e\u0440\u043a\u0438 \u0438 \u0434\u0435\u043f\u043b\u043e\u044f \u0432\u0441\u0435\u0433\u043e Envoy.   <\/p>\n<h3>\u041f\u0440\u0435\u0438\u043c\u0443\u0449\u0435\u0441\u0442\u0432\u0430<\/h3>\n<ul>\n<li>\n<p><strong>\u0413\u0438\u0431\u043a\u043e\u0441\u0442\u044c<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u043c\u043e\u0436\u043d\u043e \u0434\u043e\u0441\u0442\u0430\u0432\u043b\u044f\u0442\u044c \u0438 \u043f\u0435\u0440\u0435\u0437\u0430\u0433\u0440\u0443\u0436\u0430\u0442\u044c \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f. \u041b\u044e\u0431\u044b\u0439 \u0438\u0437\u043c\u0435\u043d\u0435\u043d\u0438\u044f \u0438\u043b\u0438 \u0438\u0441\u043f\u0440\u0430\u0432\u043b\u0435\u043d\u0438\u044f \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043f\u0440\u043e\u0442\u0435\u0441\u0442\u0438\u0440\u043e\u0432\u0430\u043d\u044b \u0432\u043e \u0432\u0440\u0435\u043c\u044f \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f, \u0431\u0435\u0437 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043e\u0431\u043d\u043e\u0432\u043b\u0435\u043d\u0438\u044f \u0438 \u0440\u0435\u0434\u0438\u043f\u043b\u043e\u044f \u043d\u043e\u0432\u043e\u0433\u043e \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430.<\/p>\n<\/li>\n<li>\n<p><strong>\u041d\u0430\u0434\u0435\u0436\u043d\u043e\u0441\u0442\u044c \u0438 \u0438\u0437\u043e\u043b\u044f\u0446\u0438\u044f. <\/strong>\u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u0438 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u044b \u043f\u043e \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044e CPU \u0438 \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p><strong>\u0411\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e\u0441\u0442\u044c<\/strong>. \u0420\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430\u044e\u0442\u0441\u044f \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0435 \u0441 \u0447\u0435\u0442\u043a\u043e \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u043d\u044b\u043c API \u0434\u043b\u044f \u0441\u0432\u044f\u0437\u0438 \u0441 \u043f\u0440\u043e\u043a\u0441\u0438(envoy, <a href=\"https:\/\/github.com\/api7\/wasm-nginx-module\" rel=\"noopener noreferrer nofollow\">nginx<\/a> \u0438 \u0442.\u0434.). \u0418\u043c\u0435\u044e\u0442 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0434\u043e\u0441\u0442\u0443\u043f \u043a \u0441\u0432\u043e\u0439\u0441\u0442\u0432\u0430\u043c, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u043c\u0435\u043d\u044f\u0442\u044c.<\/p>\n<\/li>\n<li>\n<p><strong>\u0420\u0430\u0437\u043d\u043e\u043e\u0431\u0440\u0430\u0437\u0438\u0435.<\/strong> \u0411\u043e\u043b\u044c\u0448\u043e\u0439 \u0432\u044b\u0431\u043e\u0440 \u044f\u0437\u044b\u043a\u043e\u0432 \u043f\u0440\u043e\u0433\u0440\u0430\u043c\u043c\u0438\u0440\u043e\u0432\u0430\u043d\u0438\u044f, \u043a\u043e\u0442\u043e\u0440\u044b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0441\u043a\u043e\u043c\u043f\u0438\u043b\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0432 WebAssembly, \u0447\u0442\u043e \u043f\u043e\u0437\u0432\u043e\u043b\u044f\u0435\u0442 \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0430\u043c \u0441 \u043b\u044e\u0431\u044b\u043c \u043e\u043f\u044b\u0442\u043e\u043c(C, Go, Rust, Java, TypeScript, \u0438 \u0442.\u0434.) \u043f\u0438\u0441\u0430\u0442\u044c \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f.<\/p>\n<\/li>\n<li>\n<p><strong>\u041f\u0435\u0440\u0435\u043d\u043e\u0441\u0438\u043c\u043e\u0441\u0442\u044c<\/strong>. \u041f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 \u0438\u043d\u0442\u0435\u0440\u0444\u0435\u0439\u0441 \u043c\u0435\u0436\u0434\u0443 \u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u043e\u0439 \u0438 \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f\u043c\u0438 \u043d\u0435 \u0437\u0430\u0432\u0438\u0441\u0438\u0442 \u043e\u0442 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440\u0430, \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u044f, \u043d\u0430\u043f\u0438\u0441\u0430\u043d\u043d\u044b\u0435 \u0441 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0435\u043c Proxy-Wasm, \u043c\u043e\u0433\u0443\u0442 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0442\u044c\u0441\u044f \u0432 \u0440\u0430\u0437\u043b\u0438\u0447\u043d\u044b\u0445 \u043f\u0440\u043e\u043a\u0441\u0438-\u0441\u0435\u0440\u0432\u0435\u0440\u0430\u0445, \u043d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <a href=\"https:\/\/github.com\/proxy-wasm\/spec#servers\" rel=\"noopener noreferrer nofollow\">Envoy, NGINX, ATS<\/a>  \u0438\u043b\u0438 \u0434\u0430\u0436\u0435 \u0432\u043d\u0443\u0442\u0440\u0438 \u0431\u0438\u0431\u043b\u0438\u043e\u0442\u0435\u043a\u0438 gRPC (\u043f\u0440\u0438 \u0443\u0441\u043b\u043e\u0432\u0438\u0438, \u0447\u0442\u043e \u0432\u0441\u0435 \u043e\u043d\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u0443\u044e\u0442 \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442).<\/p>\n<\/li>\n<\/ul>\n<h3>\u041d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043a\u0438<\/h3>\n<ul>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u0432\u044b\u0441\u043e\u043a\u043e\u0435 \u043f\u043e\u0442\u0440\u0435\u0431\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0437\u0430\u043f\u0443\u0441\u043a\u0430 \u043c\u043d\u043e\u0436\u0435\u0441\u0442\u0432\u0430 \u0432\u0438\u0440\u0442\u0443\u0430\u043b\u044c\u043d\u044b\u0445 \u043c\u0430\u0448\u0438\u043d, \u043a\u0430\u0436\u0434\u0430\u044f \u0441\u043e \u0441\u0432\u043e\u0438\u043c \u0431\u043b\u043e\u043a\u043e\u043c \u043f\u0430\u043c\u044f\u0442\u0438.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f \u0440\u0430\u0441\u0448\u0438\u0440\u0435\u043d\u0438\u0439, \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u0443\u044e\u0449\u0438\u0439 \u043f\u043e\u043b\u0435\u0437\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435, \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u043a\u043e\u043f\u0438\u0440\u043e\u0432\u0430\u0442\u044c \u0437\u043d\u0430\u0447\u0438\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u043e\u0431\u044a\u0435\u043c\u044b \u0434\u0430\u043d\u043d\u044b\u0445 \u0432 \u043f\u0435\u0441\u043e\u0447\u043d\u0438\u0446\u0443 \u0438 \u0438\u0437 \u043d\u0435\u0435.<\/p>\n<\/li>\n<li>\n<p>\u0411\u043e\u043b\u0435\u0435 \u043d\u0438\u0437\u043a\u0430\u044f \u043f\u0440\u043e\u0438\u0437\u0432\u043e\u0434\u0438\u0442\u0435\u043b\u044c\u043d\u043e\u0441\u0442\u044c \u0434\u043b\u044f CPU-bound \u0437\u0430\u0434\u0430\u0447. \u041e\u0436\u0438\u0434\u0430\u0435\u0442\u0441\u044f, \u0447\u0442\u043e \u0437\u0430\u043c\u0435\u0434\u043b\u0435\u043d\u0438\u0435 \u0431\u0443\u0434\u0435\u0442 \u043c\u0435\u043d\u0435\u0435 \u0447\u0435\u043c \u0432 2 \u0440\u0430\u0437\u0430 \u043f\u043e \u0441\u0440\u0430\u0432\u043d\u0435\u043d\u0438\u044e \u0441 \u043d\u0430\u0442\u0438\u0432\u043d\u044b\u043c \u043a\u043e\u0434\u043e\u043c.<\/p>\n<\/li>\n<li>\n<p>\u0423\u0432\u0435\u043b\u0438\u0447\u0435\u043d\u043d\u044b\u0439 \u0440\u0430\u0437\u043c\u0435\u0440 \u0431\u0438\u043d\u0430\u0440\u043d\u0438\u043a\u0430 \u0438\u0437-\u0437\u0430 \u043d\u0435\u043e\u0431\u0445\u043e\u0434\u0438\u043c\u043e\u0441\u0442\u0438 \u0432\u043a\u043b\u044e\u0447\u0430\u0442\u044c \u0441\u0440\u0435\u0434\u0443 \u0432\u044b\u043f\u043e\u043b\u043d\u0435\u043d\u0438\u044f Wasm. \u042d\u0442\u043e ~20 MB \u0434\u043b\u044f WAVM \u0438 ~10 MB \u0434\u043b\u044f V8.<\/p>\n<\/li>\n<li>\n<p>\u042d\u043a\u043e\u0441\u0438\u0441\u0442\u0435\u043c\u0430 WebAssembly \u0432\u0441\u0435 \u0435\u0449\u0435 \u043c\u043e\u043b\u043e\u0434\u0430, \u0438 \u0432 \u043d\u0430\u0441\u0442\u043e\u044f\u0449\u0435\u0435 \u0432\u0440\u0435\u043c\u044f \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u043a\u0430 \u0441\u043e\u0441\u0440\u0435\u0434\u043e\u0442\u043e\u0447\u0435\u043d\u0430 \u043d\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u043d\u0438\u0438 \u0432 \u0431\u0440\u0430\u0443\u0437\u0435\u0440\u0435, \u0433\u0434\u0435 JavaScript \u0441\u0447\u0438\u0442\u0430\u0435\u0442\u0441\u044f \u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u043e\u0439.<\/p>\n<\/li>\n<\/ul>\n<h2>\u041e\u0431\u0449\u0430\u044f \u0441\u0445\u0435\u043c\u0430<\/h2>\n<p>\u0412 Envoy \u0432\u0437\u044f\u043b\u0438 C++ API, \u043f\u0440\u0438\u043a\u0440\u0443\u0442\u0438\u043b\u0438 Wasm VM \u0438 \u043f\u0435\u0440\u0435\u043d\u0430\u043f\u0440\u0430\u0432\u043b\u044f\u044e\u0442 \u0432\u044b\u0437\u043e\u0432\u044b \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u044c. <\/p>\n<figure class=\"bordered full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u0412 \u043e\u0434\u043d\u043e\u043c wasm \u043c\u043e\u0434\u0443\u043b\u0435 \u043c\u043e\u0433\u0443\u0442 \u0431\u044b\u0442\u044c \u043d\u0435\u0441\u043a\u043e\u043b\u044c\u043a\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u043e\u0432. \u042d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u044b Wasm VM \u0440\u0430\u0437\u043c\u043d\u043e\u0436\u0435\u043d\u044b \u0438 \u0440\u0430\u0437\u043c\u0435\u0449\u0435\u043d\u044b \u0432 <a href=\"https:\/\/en.wikipedia.org\/wiki\/Thread-local_storage\" rel=\"noopener noreferrer nofollow\">thread-local storage<\/a><\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041a\u043e\u043c\u043c\u0443\u043d\u0438\u043a\u0430\u0446\u0438\u044f \u043c\u0435\u0436\u0434\u0443 \u044d\u043a\u0437\u0435\u043c\u043f\u043b\u044f\u0440\u0430\u043c\u0438 Wasm VM \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u0435\u0442\u0441\u044f \u043f\u0440\u0438\u043c\u0438\u0442\u0438\u0432\u0430\u043c\u0438 shared data \u0438 message queue. \u0421\u043b\u0443\u0436\u0431\u044b \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u044e\u0442 \u0438\u0437 \u0441\u0435\u0431\u044f singleton \u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u0432 \u043e\u0441\u043d\u043e\u0432\u043d\u043e\u043c \u043f\u043e\u0442\u043e\u043a\u0435 Envoy. \u041e\u043d\u0438 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u044e\u0442\u0441\u044f \u043f\u0430\u0440\u0430\u043b\u043b\u0435\u043b\u044c\u043d\u043e \u0444\u0438\u043b\u044c\u0442\u0440\u0430\u043c \u0438 \u043e\u0441\u0443\u0449\u0435\u0441\u0442\u0432\u043b\u044f\u044e\u0442 \u0432\u0441\u043f\u043e\u043c\u043e\u0433\u0430\u0442\u0435\u043b\u044c\u043d\u044b\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u043b\u043e\u0433\u0438, \u0441\u0442\u0430\u0442\u0438\u0441\u0442\u0438\u043a\u0430 \u0438 \u0442.\u0434.<\/p>\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<h3>\u0420\u0430\u043d\u0442\u0430\u0439\u043c<\/h3>\n<p>Wasm VM \u044d\u0442\u043e \u043e\u0434\u0438\u043d \u0438\u0437 \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0440\u0430\u043d\u0442\u0430\u0439\u043c\u043e\u0432<\/p>\n<ul>\n<li>\n<p>V8<\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/bytecodealliance\/wasm-micro-runtime\" rel=\"noopener noreferrer nofollow\">WAMR<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/bytecodealliance\/wasmtime\" rel=\"noopener noreferrer nofollow\">Wasmtime<\/a><\/p>\n<\/li>\n<li>\n<p><a href=\"https:\/\/github.com\/WAVM\/WAVM\" rel=\"noopener noreferrer nofollow\">WAVM<\/a><\/p>\n<\/li>\n<\/ul>\n<h3>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f<\/h3>\n<p>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f ABI \u0440\u0430\u0437\u0431\u0438\u0442\u0430 \u043d\u0430 \u0434\u0432\u0430 \u0431\u043e\u043b\u044c\u0448\u0438\u0445 \u0431\u043b\u043e\u043a\u0430: \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 <a href=\"https:\/\/github.com\/proxy-wasm\/spec\/blob\/master\/abi-versions\/vNEXT\/README.md#functions-implemented-in-the-wasm-module\" rel=\"noopener noreferrer nofollow\">\u043c\u043e\u0434\u0443\u043b\u0435<\/a> \u0438 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 \u0440\u0435\u0430\u043b\u0438\u0437\u043e\u0432\u0430\u043d\u043d\u044b\u0435 \u0432 <a href=\"https:\/\/github.com\/proxy-wasm\/spec\/blob\/master\/abi-versions\/vNEXT\/README.md#functions-implemented-in-the-host-environment\" rel=\"noopener noreferrer nofollow\">\u0445\u043e\u0441\u0442-\u0441\u0440\u0435\u0434\u0435<\/a>. \u0412\u044b\u0434\u0435\u043b\u044e \u0434\u0432\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438: \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u0438 <code>proxy_on_memory_allocate<\/code>, \u0442\u043e\u0447\u043a\u0430 \u0432\u0445\u043e\u0434\u0430 <code>_start<\/code>.<\/p>\n<p>\u0421\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u044f \u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u044f\u0435\u0442 \u043d\u0430\u0431\u043e\u0440 \u0444\u0443\u043d\u043a\u0446\u0438\u0439 \u0432 \u0444\u043e\u0440\u043c\u0430\u0442\u0435 <code>proxy_log<\/code><\/p>\n<p> \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>i32 (proxy_log_level_t) log_level<\/code><\/p>\n<\/li>\n<li>\n<p><code>i32 (const char*) message_data<\/code><\/p>\n<\/li>\n<li>\n<p><code>i32 (size_t) message_size<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p><code>i32 (proxy_result_t) call_result<\/code><\/p>\n<\/li>\n<\/ul>\n<p>i32 \u044d\u0442\u043e \u0447\u0438\u0441\u043b\u043e\u0432\u043e\u0439 <a href=\"https:\/\/webassembly.github.io\/spec\/core\/bikeshed\/#types\" rel=\"noopener noreferrer nofollow\">\u0442\u0438\u043f \u0432 wasm<\/a>, \u0430 \u0442\u0430\u043a \u043e\u043d\u0430 \u0432\u044b\u0433\u043b\u044f\u0434\u0438\u0442 \u0432 \u0440\u0430\u0437\u043d\u044b\u0445 SDK<\/p>\n<pre><code class=\"cpp\">extern \"C\" WasmResult proxy_log(LogLevel level,                                 const char *logMessage,                                 size_t messageSize);<\/code><\/pre>\n<pre><code class=\"go\">package internal  \/\/export proxy_log func ProxyLog(logLevel LogLevel,               messageData *byte,               messageSize int) Status<\/code><\/pre>\n<pre><code class=\"coffeescript\">\/\/ @ts-ignore: decorator @external(\"env\", \"proxy_log\") export declare function proxy_log(level: LogLevel,                                   logMessage: ptr&lt;char>,                                   messageSize: size_t): WasmResult;<\/code><\/pre>\n<h3>\u0412\u043b\u0430\u0434\u0435\u043d\u0438\u0435 \u043f\u0430\u043c\u044f\u0442\u044c\u044e<\/h3>\n<p>\u041d\u0430\u0432\u0435\u0440\u043d\u043e\u0435 \u044d\u0442\u043e \u043e\u0434\u043d\u0430 \u0438\u0437 \u0441\u0430\u043c\u044b\u0445 \u0432\u0430\u0436\u043d\u044b\u0445 \u0442\u0435\u043c \u043f\u0440\u0438 \u043f\u043e\u0441\u0442\u0440\u043e\u0435\u043d\u0438\u0438 \u0442\u0430\u043a\u043e\u0439 \u0441\u0438\u0441\u0442\u0435\u043c\u043e\u0439, \u0433\u0434\u0435 \u0435\u0441\u0442\u044c \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0445\u043e\u0441\u0442\u0430 \u0438 \u043f\u0430\u043c\u044f\u0442\u044c \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u0435. \u041d\u0438\u043a\u0430\u043a\u0430\u044f \u0443\u043f\u0440\u0430\u0432\u043b\u044f\u0435\u043c\u0430\u044f \u043f\u0430\u043c\u044f\u0442\u044c \u043d\u0435 \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442\u0441\u044f \u0432 wasm \u043c\u043e\u0434\u0443\u043b\u044c \u043f\u0440\u0438 \u0432\u044b\u0437\u043e\u0432\u0435 \u043e\u0431\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u043e\u0432. \u0412\u043c\u0435\u0441\u0442\u043e \u044d\u0442\u043e\u0433\u043e wasm \u043c\u043e\u0434\u0443\u043b\u044c \u0441\u0430\u043c \u0437\u0430\u043f\u0440\u0430\u0448\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0435.  \u041d\u0430\u043f\u0440\u0438\u043c\u0435\u0440 <code>proxy_on_http_request_body<\/code> \u043f\u0435\u0440\u0435\u0434\u0430\u0435\u0442 \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u044e \u043e \u043a\u043e\u043b\u0438\u0447\u0435\u0441\u0442\u0432\u0435 \u0434\u043e\u0441\u0442\u0443\u043f\u043d\u044b\u0445 \u0431\u0430\u0439\u0442\u043e\u0432 \u0432 \u0442\u0435\u043b\u0435 \u0437\u0430\u043f\u0440\u043e\u0441\u0430, \u043c\u043e\u0434\u0443\u043b\u044c \u0434\u043e\u043b\u0436\u0435\u043d \u0437\u0430\u043f\u0440\u043e\u0441\u0438\u0442\u044c \u044d\u0442\u0438 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044f <code>proxy_get_buffer<\/code>. \u041a\u043e\u0433\u0434\u0430 \u044d\u0442\u043e \u043f\u0440\u043e\u0438\u0441\u0445\u043e\u0434\u0438\u0442, \u0445\u043e\u0441\u0442 \u0432\u044b\u0434\u0435\u043b\u044f\u0435\u0442 \u043f\u043e\u043c\u044f\u0442\u044c \u0443 wasm \u043c\u043e\u0434\u0443\u043b\u044f \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>proxy_on_memory_allocate<\/code>, <strong><em>\u043a\u043e\u043f\u0438\u0440\u0443\u0435\u0442<\/em><\/strong> \u0442\u0443\u0434\u0430 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438 <strong><em>\u043e\u0442\u0434\u0430\u0435\u0442<\/em><\/strong> \u043f\u0430\u043c\u044f\u0442\u044c \u0432\u043e \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u0435 wasm \u043c\u043e\u0434\u0443\u043b\u044e, \u0432 \u043d\u0430\u0434\u0435\u0436\u0434\u0435, \u0447\u0442\u043e \u043e\u043d \u043e\u0441\u0432\u043e\u0431\u043e\u0434\u0438\u0442 \u0435\u0435. <\/p>\n<h3>proxy_on_memory_allocate<\/h3>\n<p>\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u044b:<\/p>\n<ul>\n<li>\n<p><code>i32 (size_t) memory_size<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u043c\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435:<\/p>\n<ul>\n<li>\n<p><code>i32 (void*) allocated_ptr<\/code><\/p>\n<\/li>\n<\/ul>\n<p>\u0420\u0435\u0430\u043b\u0438\u0437\u0430\u0446\u0438\u044f \u043d\u0430 AssemblyScript <a href=\"https:\/\/github.com\/solo-io\/proxy-runtime\/blob\/master\/assembly\/malloc.ts\" rel=\"noopener noreferrer nofollow\">malloc.ts<\/a><\/p>\n<pre><code class=\"javascript\">import {   __pin,   __unpin, } from \"rt\/itcms\";  \/\/\/ Allow host to allocate memory. export function malloc(size: i32): usize {   let buffer = new ArrayBuffer(size);   let ptr = changetype&lt;usize>(buffer);   return __pin(ptr); }  \/\/\/ Allow host to free memory. export function free(ptr: usize): void {   __unpin(ptr); }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<pre><code class=\"javascript\">class ArrayBufferReference {   private buffer: usize;   private size: usize;    constructor() {   }    sizePtr(): usize {     return changetype&lt;usize>(this) + offsetof&lt;ArrayBufferReference>(\"size\");   }   bufferPtr(): usize {     return changetype&lt;usize>(this) + offsetof&lt;ArrayBufferReference>(\"buffer\");   }    \/\/ Before calling toArrayBuffer below, you must call out to the host to fill in the values.   \/\/ toArrayBuffer below **must** be called once and only once.   toArrayBuffer(): ArrayBuffer {     if (this.size == 0) {       return new ArrayBuffer(0);     }      let array = changetype&lt;ArrayBuffer>(this.buffer);     \/\/ host code used malloc to allocate this buffer.     \/\/ release the allocated ptr. array variable will retain it, so it won't be actually free (as it is ref counted).     free(this.buffer);     \/\/ should we return a this sliced up to size?     return array;   } }<\/code><\/pre>\n<p>\u0412 AssemblyScript \u0437\u0430\u043b\u043e\u0436\u0438\u043b\u0438 \u043f\u043e\u0432\u0435\u0434\u0435\u043d\u0438\u0435 \u043f\u0440\u0438 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043c\u043e\u0436\u043d\u043e \u043e\u0442\u0434\u0430\u0432\u0430\u0442\u044c \u0432\u043e \u0432\u043d\u0435\u0448\u043d\u044e\u044e \u0441\u0440\u0435\u0434\u0443(\u0432 \u043f\u0435\u0440\u0432\u0443\u044e \u043e\u0447\u0435\u0440\u0435\u0434\u044c \u0432 JS). \u0414\u043b\u044f \u044d\u0442\u043e\u0433\u043e \u0435\u0441\u0442\u044c <a href=\"https:\/\/www.assemblyscript.org\/runtime.html#interface\" rel=\"noopener noreferrer nofollow\">__pin\/__unpin<\/a>, \u0447\u0442\u043e \u0431\u044b \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043d\u0435 \u0441\u043e\u0431\u0440\u0430\u043b \u043e\u0431\u044a\u0435\u043a\u0442\u044b \u043d\u0430 \u043a\u043e\u0442\u043e\u0440\u044b\u0445 \u0443\u0436\u0435 \u043d\u0435\u0442 \u0441\u0441\u044b\u043b\u043e\u043a. \u0412 Go<\/p>\n<pre><code class=\"go\">\/\/nolint \/\/export proxy_on_memory_allocate func proxyOnMemoryAllocate(size uint) *byte { buf := make([]byte, size) return &amp;buf[0] }<\/code><\/pre>\n<p>\u041e\u0431\u0440\u0430\u0442\u043d\u043e\u0435 \u043f\u0440\u0435\u043e\u0431\u0440\u0430\u0437\u043e\u0432\u0430\u043d\u0438\u0435<\/p>\n<pre><code class=\"go\">import ( \"reflect\" \"unsafe\" )  func RawBytePtrToString(raw *byte, size int) string { \/\/nolint return *(*string)(unsafe.Pointer(&amp;reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(raw)), Len:  size, Cap:  size, })) }  func RawBytePtrToByteSlice(raw *byte, size int) []byte { \/\/nolint return *(*[]byte)(unsafe.Pointer(&amp;reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(raw)), Len:  size, Cap:  size, })) }<\/code><\/pre>\n<p>\u0427\u0442\u043e \u0442\u0443\u0442 \u043c\u043e\u0436\u043d\u043e \u0441\u043a\u0430\u0437\u0430\u0442\u044c? \u0412 \u0441\u043f\u0435\u0446\u0438\u0444\u0438\u043a\u0430\u0446\u0438\u0438 <a href=\"https:\/\/go.dev\/ref\/spec\" rel=\"noopener noreferrer nofollow\">Go<\/a> \u043d\u0438\u0447\u0435\u0433\u043e \u043d\u0435 \u0441\u043a\u0430\u0437\u0430\u043d\u043e \u043f\u0440\u043e \u0440\u0430\u0431\u043e\u0442\u0443 \u0441\u0431\u043e\u0440\u0449\u0438\u043a\u0430 \u043c\u0443\u0441\u043e\u0440\u0430. \u041a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440 \u0441 <a href=\"https:\/\/go.dev\/\" rel=\"noopener noreferrer nofollow\">https:\/\/go.dev\/<\/a> \u0437\u0430\u043f\u0440\u0435\u0449\u0430\u0435\u0442 \u043f\u0435\u0440\u0435\u0434\u0430\u0432\u0430\u0442\u044c \u0443\u043a\u0430\u0437\u0430\u0442\u0435\u043b\u0438 \u043d\u0430 \u043f\u0430\u043c\u044f\u0442\u044c \u0438\u0437 Go \u0432 \u0421\u0438. \u0415\u0441\u0442\u044c \u043f\u0430\u043a\u0435\u0442<a href=\"https:\/\/github.com\/mattn\/go-pointer\" rel=\"noopener noreferrer nofollow\"> go-pointer<\/a>, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u043d\u0430\u043f\u043e\u043c\u0438\u043d\u0430\u0435\u0442 pin\/unpin \u0438\u0437 AssemblyScript.<\/p>\n<pre><code class=\"go\">C.pass_pointer(pointer.Save(&amp;s)) v := *(pointer.Restore(C.get_from_pointer()).(*string))<\/code><\/pre>\n<p>\u0412\u043d\u0443\u0442\u0440\u0438 \u0434\u043e\u0432\u043e\u043b\u044c\u043d\u043e \u043f\u0440\u043e\u0441\u0442\u043e\u0439<\/p>\n<pre><code class=\"go\">package pointer  \/\/ #include &lt;stdlib.h> import \"C\" import ( \"sync\" \"unsafe\" )  var ( mutex sync.RWMutex store = map[unsafe.Pointer]interface{}{} )  func Save(v interface{}) unsafe.Pointer { if v == nil { return nil }  \/\/ Generate real fake C pointer. \/\/ This pointer will not store any data, but will bi used for indexing purposes. \/\/ Since Go doest allow to cast dangling pointer to unsafe.Pointer, we do rally allocate one byte. \/\/ Why we need indexing, because Go doest allow C code to store pointers to Go data. var ptr unsafe.Pointer = C.malloc(C.size_t(1)) if ptr == nil { panic(\"can't allocate 'cgo-pointer hack index pointer': ptr == nil\") }  mutex.Lock() store[ptr] = v mutex.Unlock()  return ptr }<\/code><\/pre>\n<p><strong>\u041d\u041e<\/strong> \u0440\u0430\u0437\u0440\u0430\u0431\u043e\u0442\u0447\u0438\u043a\u0438 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442 <strong>TinyGo<\/strong>, \u0432 \u043a\u043e\u0442\u043e\u0440\u043e\u043c \u0441\u0431\u043e\u0440\u0449\u0438\u043a \u043c\u0443\u0441\u043e\u0440\u0430 \u043f\u043e\u043f\u0440\u043e\u0449\u0435 \u0438 <a href=\"https:\/\/tinygo.org\/docs\/reference\/lang-support\/#garbage-collection\" rel=\"noopener noreferrer nofollow\">\u0437\u0430\u043f\u0443\u0441\u043a\u0430\u0435\u0442\u0441\u044f<\/a> \u043a\u043e\u0433\u0434\u0430 \u043d\u0435\u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043c\u0435\u0441\u0442\u0430 \u0432 \u043a\u0443\u0447\u0435. \u0415\u0441\u043b\u0438 \u043c\u0435\u0436\u0434\u0443 \u0432\u044b\u0437\u043e\u0432\u043e\u043c <code>proxy_on_memory_allocate<\/code> \u0438 \u043c\u043e\u043c\u0435\u043d\u0442\u043e\u043c \u0432\u043e\u0437\u0432\u0440\u0430\u0442\u0430 \u0432\u043b\u0430\u0434\u0435\u043d\u0438\u044f \u0432 Go \u043d\u0435\u0442 \u0432\u044b\u0434\u0435\u043b\u0435\u043d\u0438\u044f \u043f\u0430\u043c\u044f\u0442\u0438, \u0442\u043e \u044d\u0442\u043e \u0443\u0441\u043b\u043e\u0432\u043d\u043e \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u043e.<\/p>\n<p>\u0410 \u0432\u043e\u0442 \u0432 C++ SDK <code>proxy_on_memory_allocate<\/code> \u043d\u0435 \u0443\u0432\u0438\u0434\u0438\u0442\u0435. \u0418\u0434\u0435\u0442 \u043f\u043e\u0438\u0441\u043a malloc, \u043a\u043e\u0442\u043e\u0440\u044b\u0439 \u044d\u043a\u0441\u043f\u043e\u0440\u0442\u0438\u0440\u0443\u0435\u0442 \u043a\u043e\u043c\u043f\u0438\u043b\u044f\u0442\u043e\u0440<\/p>\n<pre><code class=\"bash\">$ em++ --no-entry -s EXPORTED_FUNCTIONS=['_malloc'] ... <\/code><\/pre>\n<p>\u041d\u0430 \u0441\u0442\u043e\u0440\u043e\u043d\u0435 \u0445\u043e\u0441\u0442\u0430 \u0432\u044b\u043f\u043e\u043b\u043d\u044f\u0435\u0442\u0441\u044f \u043f\u043e\u0438\u0441\u043a <code>malloc<\/code>, \u0435\u0441\u043b\u0438 \u043d\u0435\u0442, \u0442\u043e \u0438\u0449\u0435\u0442\u0441\u044f <code>proxy_on_memory_allocate<\/code><\/p>\n<pre><code class=\"cpp\">void WasmBase::getFunctions() { #define _GET(_fn) wasm_vm_->getFunction(#_fn, &amp;_fn##_); #define _GET_ALIAS(_fn, _alias) wasm_vm_->getFunction(#_alias, &amp;_fn##_);   _GET(_initialize);   if (_initialize_) {     _GET(main);   } else {     _GET(_start);   }    _GET(malloc);   if (!malloc_) {     _GET_ALIAS(malloc, proxy_on_memory_allocate);   }   if (!malloc_) {     fail(FailState::MissingFunction, \"Wasm module is missing malloc function.\");   } #undef _GET_ALIAS #undef _GET    \/\/ Try to point the capability to one of the module exports, if the capability has been allowed. #define _GET_PROXY(_fn)                                                                            \\   if (capabilityAllowed(\"proxy_\" #_fn)) {                                                          \\     wasm_vm_->getFunction(\"proxy_\" #_fn, &amp;_fn##_);                                                 \\   } else {                                                                                         \\     _fn##_ = nullptr;                                                                              \\   } #define _GET_PROXY_ABI(_fn, _abi)                                                                  \\   if (capabilityAllowed(\"proxy_\" #_fn)) {                                                          \\     wasm_vm_->getFunction(\"proxy_\" #_fn, &amp;_fn##_abi##_);                                           \\   } else {                                                                                         \\     _fn##_abi##_ = nullptr;                                                                        \\   }<\/code><\/pre>\n<\/div>\n<\/div>\n<\/div>\n<\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-334428","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334428","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=334428"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/334428\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=334428"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=334428"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=334428"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}