gears.color: Add a pattern cache

This makes gears.color() cache patterns in a weak table and returns that cached
pattern when we get called with the same argument again.

To benchmark this change, the following code was used:

local time = require("socket").gettime

function benchmark(func)
   local begin = time()
   local iter = 0
   while time() - begin < 1 do
      func()
      iter = iter + 1
   end
   return iter
end

for _, arg in pairs({
   "#00aa00",
   "solid:#00aa00",
   "radial:50,50,10:55,55,30:0,#ff0000:0.5,#00ff00:1,#0000ff",
   "linear:1,2:3,4:0,#000000:1,#ffffff",
   "png:/home/psychon/Wallpaper/Bars.png",
   { type = "solid", color = "#00aa00" },
   { type = "radial", from = { 50, 50, 10 }, to = { 55, 55, 30 }, stops = { { 0, "#ff0000" }, { 0.5, "#00ff00" }, { 1, "#0000ff" } } },
   { type = "linear", from = { 1, 2 }, to = { 3, 4 }, stops = { { 0, "#000000" }, { 1, "#ffffff" } } },
   { type = "png", file = "/home/psychon/Wallpaper/Bars.png" },
}) do
   collectgarbage("collect")
   print(benchmark(function() gears.color.create_pattern(arg) end), arg)
end

Before this change (larger numbers are better, this measures how many times we
can create the given pattern per second):

29525   #00aa00
29344   solid:#00aa00
3446    radial:50,50,10:55,55,30:0,#ff0000:0.5,#00ff00:1,#0000ff
4845    linear:1,2:3,4:0,#000000:1,#ffffff
32855   png:/home/psychon/Wallpaper/Bars.png
29883   table: 0x1bb67e0
3868    table: 0x1bb6830
5339    table: 0x1bb6c60
32772   table: 0x1bb6fe0

After this change:

126188  #00aa00
125962  solid:#00aa00
125125  radial:50,50,10:55,55,30:0,#ff0000:0.5,#00ff00:1,#0000ff
125213  linear:1,2:3,4:0,#000000:1,#ffffff
113659  png:/home/psychon/Wallpaper/Bars.png
125586  table: 0x1232680
125249  table: 0x12326d0
125468  table: 0x1232b00
113711  table: 0x1232e80

As you see, this makes some cases about 35 times faster (although I have to
admit that something like this can be expected from such a synthetic benchmark).

Signed-off-by: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Uli Schlachter 2014-03-29 22:52:04 +01:00
parent 79ad0d3e6e
commit b9361d54c6
1 changed files with 12 additions and 3 deletions

View File

@ -16,6 +16,7 @@ local cairo = require("lgi").cairo
local surface = require("gears.surface") local surface = require("gears.surface")
local color = { mt = {} } local color = { mt = {} }
local pattern_cache = setmetatable({}, { __mode = 'v' })
--- Parse a HTML-color. --- Parse a HTML-color.
-- This function can parse colors like #rrggbb and #rrggbbaa. -- This function can parse colors like #rrggbb and #rrggbbaa.
@ -186,20 +187,28 @@ function color.create_pattern(col)
if cairo.Pattern:is_type_of(col) then if cairo.Pattern:is_type_of(col) then
return col return col
end end
local result = col and pattern_cache[col]
if result then
return result
end
if type(col) == "string" then if type(col) == "string" then
local t = string.match(col, "[^:]+") local t = string.match(col, "[^:]+")
if color.types[t] then if color.types[t] then
local pos = string.len(t) local pos = string.len(t)
local arg = string.sub(col, pos + 2) local arg = string.sub(col, pos + 2)
return color.types[t](arg) result = color.types[t](arg)
end end
elseif type(col) == "table" then elseif type(col) == "table" then
local t = col.type local t = col.type
if color.types[t] then if color.types[t] then
return color.types[t](col) result = color.types[t](col)
end end
end end
return color.create_solid_pattern(col) if not result then
result = color.create_solid_pattern(col)
end
pattern_cache[col] = result
return result
end end
--- Check if a pattern is opaque. --- Check if a pattern is opaque.