Optimize social plugin: parallelize image saving

This commit is contained in:
Oleh Prypin 2022-10-17 15:13:12 +02:00
parent 38aca1e206
commit 09580da963
No known key found for this signature in database
GPG Key ID: A93637E52C2AD3F5
2 changed files with 42 additions and 12 deletions

View File

@ -115,6 +115,8 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config) self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config)
self.font = self._load_font(config) self.font = self._load_font(config)
self._image_promises = []
# Create social cards # Create social cards
def on_page_markdown(self, markdown, page, config, files): def on_page_markdown(self, markdown, page, config, files):
if not self.config.cards: if not self.config.cards:
@ -152,19 +154,32 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
description description
]).encode("utf-8")) ]).encode("utf-8"))
file = os.path.join(self.cache, f"{hash.hexdigest()}.png") file = os.path.join(self.cache, f"{hash.hexdigest()}.png")
if not os.path.isfile(file): self._image_promises.append(self._executor.submit(
image = self._render_card(site_name, title, description) self._cache_image,
image.save(file) cache_path = file, dest_path = path,
render_function = lambda: self._render_card(site_name, title, description)
# Copy file from cache ))
copyfile(file, path)
# Inject meta tags into page # Inject meta tags into page
meta = page.meta.get("meta", []) meta = page.meta.get("meta", [])
page.meta["meta"] = meta + self._generate_meta(page, config) page.meta["meta"] = meta + self._generate_meta(page, config)
def on_post_build(self, config):
# Check for exceptions
for promise in self._image_promises:
promise.result()
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Render image to cache (if not present), then copy from cache to site
def _cache_image(self, cache_path, dest_path, render_function):
if not os.path.isfile(cache_path):
image = render_function()
image.save(cache_path)
# Copy file from cache
copyfile(cache_path, dest_path)
@functools.lru_cache(maxsize=None) @functools.lru_cache(maxsize=None)
def _get_font(self, kind, size): def _get_font(self, kind, size):
return ImageFont.truetype(self.font[kind], size) return ImageFont.truetype(self.font[kind], size)

View File

@ -115,6 +115,8 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config) self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config)
self.font = self._load_font(config) self.font = self._load_font(config)
self._image_promises = []
# Create social cards # Create social cards
def on_page_markdown(self, markdown, page, config, files): def on_page_markdown(self, markdown, page, config, files):
if not self.config.cards: if not self.config.cards:
@ -152,19 +154,32 @@ class SocialPlugin(BasePlugin[SocialPluginConfig]):
description description
]).encode("utf-8")) ]).encode("utf-8"))
file = os.path.join(self.cache, f"{hash.hexdigest()}.png") file = os.path.join(self.cache, f"{hash.hexdigest()}.png")
if not os.path.isfile(file): self._image_promises.append(self._executor.submit(
image = self._render_card(site_name, title, description) self._cache_image,
image.save(file) cache_path = file, dest_path = path,
render_function = lambda: self._render_card(site_name, title, description)
# Copy file from cache ))
copyfile(file, path)
# Inject meta tags into page # Inject meta tags into page
meta = page.meta.get("meta", []) meta = page.meta.get("meta", [])
page.meta["meta"] = meta + self._generate_meta(page, config) page.meta["meta"] = meta + self._generate_meta(page, config)
def on_post_build(self, config):
# Check for exceptions
for promise in self._image_promises:
promise.result()
# ------------------------------------------------------------------------- # -------------------------------------------------------------------------
# Render image to cache (if not present), then copy from cache to site
def _cache_image(self, cache_path, dest_path, render_function):
if not os.path.isfile(cache_path):
image = render_function()
image.save(cache_path)
# Copy file from cache
copyfile(cache_path, dest_path)
@functools.lru_cache(maxsize=None) @functools.lru_cache(maxsize=None)
def _get_font(self, kind, size): def _get_font(self, kind, size):
return ImageFont.truetype(self.font[kind], size) return ImageFont.truetype(self.font[kind], size)