› Choose one word to make the sticker set your own › e.g. your Name › Anytime you want, change the text on the whole sticker set › Product Story: https://engineering.linecorp.com/ ja/blog/product-story-01-custom- sticker/
on all stickers at the same time › Users want to change the text more easily during the conversation › Users want to add more than a name or single word to the sticker à The personalized content becomes more directly part of the conversation
per message › Allows for multiple lines of text › Text edit flow integrated into the chat room › Text content is fully part of the conversation › Check out the video! https://www.youtube.com/watch?v=YtP1Xr4SWiY
from server, Then renders locally PRO CON › Faster and more scalable as each client renders it’s own sticker › Each client should have all the fonts, or use webfonts on demand › Develop and test on multiple platforms/devices › More complex app release process › support multiple versions of client › Inconsistent quality
style from server, Then renders locally Client sends text content to the server, Server returns PNG PRO CON › Faster and more scalable as each client renders it’s own sticker › Rendering engine is independent from the device › Easier to deploy new feature/fixes/fonts › Each client should have all the fonts, or use webfonts on demand › Develop and test on multiple platforms/devices › More complex app release process › support multiple versions of client › Inconsistent quality
style from server, Then renders locally Client sends text content to the server, Server returns PNG PRO CON › Faster and more scalable as each client renders it’s own sticker › Rendering engine is independent from the device › Easier to deploy new feature/fixes/fonts › Each client should have all the fonts, or use webfonts on demand › Develop and test on multiple platforms/devices › More complex app release process › support multiple versions of client › Inconsistent quality
style from server, Then renders locally Client sends text content to the server, Server returns PNG PRO CON › Faster and more scalable as each client renders it’s own sticker › Rendering engine is independent from the device › Easier to deploy new feature/fixes/fonts › Each client should have all the fonts, or use webfonts on demand › Develop and test on multiple platforms/devices › More complex app release process › support multiple versions of client › Inconsistent quality › Server Capacity planning is difficult › Scale out/in operations › Some limitations in rendering libraries
rendered image is part of the context of a secure conversation › By context we mean for example who is the sender and receiver/group › The text content should be shared between clients securely › The rendering server doesn’t need the context › Rendering server is user and conversation agnostic › Each client fetches the rendered overlay for itself, opening an encryption session with the server
the area where the user-given message will be rendered. Other attributes include: Text style, alignment, direction, Maximum Font size, interline and letter spacing Custom Sticker An SVG Path defines the coordinates and transformations where the user-given word will be rendered. Other attributes include: Text style, alignment and direction, character limit
› Moving towards CSS Properties rather then attributes › Feature compatibility depends on the interpreter/engine used › Rendering Tools › Java Libraries › Apache Batik › External Tools › Headless Chrome/Firefox › Inkscape / ImageMagick
faster than any other external tool… › Parses SVG Elements into AWT (Abstract Window Toolkit) components › Renders via Java graphics environment › …but it has some drawbacks: › NO browser environment, which means: › Limited CSS/JavaScript inside the SVG file › Alignment of vertical punctuation based on country › Incomplete SVG implementation › https://xmlgraphics.apache.org/batik/status.html JP Top-right-aligned TW center-aligned
“The text area will wrap and resize the text automatically, like powerpoint!” › Problem: › SVG does not natively support multi-line text › It only allows for absolute or relative positioning of single-line text elements › Solution: › Implement our own wrapping/resizing and positioning algorithm!
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。。。たとえば。。。面白い物語 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。。。面白い物語 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物語 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。。。たとえば。。。ほんとに長い決して終わらない退屈な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。。。ほんとに長い決して終わらない退屈な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに長い決して終わらない退屈な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに 長い決して終わらない退屈な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに 長い決して終 わらない退屈な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに 長い決して終 わらない退屈 な物話 Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに長 い決して終わら ない退屈な物話 Font Size: 29 Re-execute wrap at lower size!
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに長 い決して終わら ない退屈な物話 Font Size: 29 Re-execute wrap at lower size! あ。。。たぶん。。。 うーん。。。 分かった! じゃね! Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに長 い決して終わら ない退屈な物話 Font Size: 29 Re-execute wrap at lower size! あ。。。たぶ ん。。。 うーん。。。 分かった! じゃね! Font Size: 32
size, given the upper limit by the style creator › Prefer wrapping over resizing › Preserve new-line characters given by the user 短いテキスト Font Size: 32 長いテキスト。 。。たとえば。 。。面白い物 語 Font Size: 32 長いテキスト。 。。たとえば。 。。ほんとに長 い決して終わら ない退屈な物話 Font Size: 29 Re-execute wrap at lower size! あ。。。たぶん。。 。 うーん。。。 分かった! じゃね! Font Size: 24 Re-execute wrap at lower size! Keep the original new lines!
in lines › Calculate the Pixel dimensions of each line using FontMetrics › consider interline-spacing and letter-spacing › If a single line is too long, wrap into a new line › If the summed heights of the lines is too high, reduce the font size › Iterate until it fits both horizontally and vertically
120ms) › Lower RPS (120-150 req/s) › The results themselves were not bad, but less than we were expecting from the initial test › The initial test data was not good enough!
the input affects the resize/wrap algorithm execution › The font, the language and the complexity of the characters affects: › The drawing of the characters (rendering of SVG into PNG) › The size calculation of each character (resize/wrap algorithm)
a tolerable CPU Usage › combined (Message + Custom) 150 rps peak traffic at about 40% CPU usage › Assumptions: › Handle as much traffic for Message Sticker as current custom sticker product › Message Sticker overlay cannot be cached › Due to average group size, 5 rendering calls for each Message sticker sent › …and given a peak of 5K RPS at New Year’s Eve for Custom Sticker, › it could mean 25K RPS for Message Sticker › 200 rendering servers to handle the peak traffic!
servers › … it was over-provisioned, at least for the season › … scaled down to 100 servers: › Cost effectiveness: it’s not worth it to keep so many servers running the whole year › Most of the peaks are seasonal and/or predictable › More resources for other projects › and… Memory leaks!
Max heap size: 8Gb › Some Font related classes allocate Native Memory for caching purposes, and due to a loop of Hard/SoftReferences (ref: JDK-8209113) , this memory is not freed correctly
each render request and every resize › Static caching of metrics and glyphs/strikes › Hoping for GC to dispose the objects correctly › The testing data was STILL not stressing the system enough: › limited amount of unique characters › Only 1 font family per language › limited string length, leading to less resize operations › … so less Native memory was used for caching
the full Unicode space of characters, and very long strings of random characters › Using all available fonts › Fixing the Issue › Option 1: Patching the JVM, replacing the SoftReference with a WeakReference › Managing a custom patched JVM is complicated › Increased garbage collection activity › Option 2: caching the Font objects ourselves › limited amount of FontFamilies and allowed Font sizes, so the cache is also limited
Rendering Server 2 Rendering Server N Connection Pool › DB Access Control Layer with IP Whitelisting à slows down an emergency scale out operation › Limited number of connections to DB à limits scaling out capacity › DB access is a minor part of the task of this server, it shouldn’t be a bottle neck for scaling! Access Control Layer
Rendering Server 2 Rendering Server N Connection Pool LB DB Api Server 1 DB Api Server 2 DB Api Server M N > M Access Control Layer › DB API servers hold the connection pool to database and use caching for faster access to the data › Scaling out Rendering servers is now independent from ACL › Scaling out Rendering servers is not limited by maximum open connections on DB › DB API servers have a simple task, can be fewer and lower spec VMs
the needs of the business side › Real-world data (or as close to it as possible) is fundamental for stress/load testing › Be aware of the traffic patterns of your service › Keep in mind scalability when thinking about service architecture › Refactoring or architecture changes are not only for legacy code!