Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using System;
using System.IO;
using System.Collections.Generic;
using BenchmarkDotNet.Attributes;
using TextTemplate;
using TTTemplate = TextTemplate.Template;
using TextTemplate.Tests;
using HandlebarsDotNet;
using Scriban;
using DotLiquid;
using ScribanTemplateClass = Scriban.Template;
using DotLiquidTemplateClass = DotLiquid.Template;
using Hbs = HandlebarsDotNet.Handlebars;

public class ComplexNestedTemplateBenchmarks
{
private TTTemplate _tmpl = null!;
private string _hbText = null!;
private string _scribanText = null!;
private string _liquidText = null!;
private Dictionary<string, object> _values = null!;

[GlobalSetup]
public void Setup()
{
string baseDir = AppContext.BaseDirectory;
string depPath = Path.Combine(baseDir, "TestData", "complex-template-deployment.yml");
string svcPath = Path.Combine(baseDir, "TestData", "complex-template-service.yml");
string ingPath = Path.Combine(baseDir, "TestData", "complex-template-ingress.yml");
string rootPath = Path.Combine(baseDir, "TestData", "complex-template-data.yml");
string hbPath = Path.Combine(baseDir, "TestData", "complex-template.hbs");
string scribanPath = Path.Combine(baseDir, "TestData", "complex-template.scriban");
string liquidPath = Path.Combine(baseDir, "TestData", "complex-template.liquid");

_tmpl = TTTemplate.New("complex").ParseFiles(depPath, svcPath, ingPath, rootPath);
_hbText = File.ReadAllText(hbPath);
_scribanText = File.ReadAllText(scribanPath);
_liquidText = File.ReadAllText(liquidPath);
DotLiquidTemplateClass.NamingConvention = new DotLiquid.NamingConventions.CSharpNamingConvention();
_values = ComplexNestedTemplateData.Create();
}

[Benchmark]
public string GoTextTemplate_NET() => _tmpl.Execute(_values);

[Benchmark]
public string Handlebars()
{
var compiled = Hbs.Compile(_hbText);
return compiled(_values);
}

[Benchmark]
public string Scriban()
{
var tmpl = ScribanTemplateClass.Parse(_scribanText);
return tmpl.Render(_values);
}

[Benchmark]
public string DotLiquid()
{
var tmpl = DotLiquidTemplateClass.Parse(_liquidText);
return tmpl.Render(Hash.FromDictionary(_values));
}
}

5 changes: 4 additions & 1 deletion benchmarks/TextTemplate.Benchmarks/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,8 @@ public void Setup()

public class Program
{
public static void Main(string[] args) => BenchmarkRunner.Run<TemplateBenchmarks>();
public static void Main(string[] args)
{
BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
}
}
159 changes: 159 additions & 0 deletions benchmarks/TextTemplate.Benchmarks/TestData/complex-template.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{Values.appName}}-deployment
namespace: {{Values.namespace}}
labels:
app: {{Values.appName}}
version: {{Values.version}}
{{#if Values.environment}}
environment: {{Values.environment}}
{{/if}}
{{#each Values.customLabels}}
{{@key}}: {{this}}
{{/each}}
spec:
replicas: {{Values.replicaCount}}
selector:
matchLabels:
app: {{Values.appName}}
template:
metadata:
labels:
app: {{Values.appName}}
version: {{Values.version}}
spec:
containers:
- name: {{Values.appName}}
image: {{Values.image.repository}}:{{Values.image.tag}}
ports:
- containerPort: {{Values.service.port}}
{{#if Values.env}}
env:
{{#each Values.env}}
- name: {{name}}
value: "{{value}}"
{{/each}}
{{/if}}
{{#if Values.resources}}
resources:
{{#if Values.resources.limits}}
limits:
{{#each Values.resources.limits}}
{{@key}}: {{this}}
{{/each}}
{{/if}}
{{#if Values.resources.requests}}
requests:
{{#each Values.resources.requests}}
{{@key}}: {{this}}
{{/each}}
{{/if}}
{{/if}}
{{#if Values.volumeMounts}}
volumeMounts:
{{#each Values.volumeMounts}}
- name: {{name}}
mountPath: {{mountPath}}
{{#if readOnly}}
readOnly: {{readOnly}}
{{/if}}
{{/each}}
{{/if}}
{{#if Values.volumes}}
volumes:
{{#each Values.volumes}}
- name: {{name}}
{{#if configMap}}
configMap:
name: {{configMap.name}}
{{/if}}
{{#if secret}}
secret:
secretName: {{secret.secretName}}
{{/if}}
{{#if persistentVolumeClaim}}
persistentVolumeClaim:
claimName: {{persistentVolumeClaim.claimName}}
{{/if}}
{{/each}}
{{/if}}
{{#if Values.nodeSelector}}
nodeSelector:
{{#each Values.nodeSelector}}
{{@key}}: {{this}}
{{/each}}
{{/if}}
{{#if Values.tolerations}}
tolerations:
{{#each Values.tolerations}}
- key: {{key}}
operator: {{operator}}
{{#if value}}
value: {{value}}
{{/if}}
effect: {{effect}}
{{/each}}
{{/if}}
---
{{#if Values.service.enabled}}
apiVersion: v1
kind: Service
metadata:
name: {{Values.appName}}-service
namespace: {{Values.namespace}}
labels:
app: {{Values.appName}}
spec:
type: {{Values.service.type}}
ports:
- port: {{Values.service.port}}
targetPort: {{Values.service.targetPort}}
protocol: TCP
{{#if Values.service.nodePort}}
nodePort: {{Values.service.nodePort}}
{{/if}}
selector:
app: {{Values.appName}}
{{/if}}
---
{{#if Values.ingress.enabled}}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{Values.appName}}-ingress
namespace: {{Values.namespace}}
{{#if Values.ingress.annotations}}
annotations:
{{#each Values.ingress.annotations}}
{{@key}}: "{{this}}"
{{/each}}
{{/if}}
spec:
{{#if Values.ingress.tls}}
tls:
{{#each Values.ingress.tls}}
- hosts:
{{#each hosts}}
- {{this}}
{{/each}}
secretName: {{secretName}}
{{/each}}
{{/if}}
rules:
{{#each Values.ingress.hosts}}
- host: {{host}}
http:
paths:
{{#each paths}}
- path: {{path}}
pathType: {{pathType}}
backend:
service:
name: {{@root.Values.appName}}-service
port:
number: {{@root.Values.service.port}}
{{/each}}
{{/each}}
{{/if}}

159 changes: 159 additions & 0 deletions benchmarks/TextTemplate.Benchmarks/TestData/complex-template.liquid
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ Values.appName }}-deployment
namespace: {{ Values.namespace }}
labels:
app: {{ Values.appName }}
version: {{ Values.version }}
{% if Values.environment %}
environment: {{ Values.environment }}
{% endif %}
{% for label in Values.customLabels %}
{{ label.Key }}: {{ label.Value }}
{% endfor %}
spec:
replicas: {{ Values.replicaCount }}
selector:
matchLabels:
app: {{ Values.appName }}
template:
metadata:
labels:
app: {{ Values.appName }}
version: {{ Values.version }}
spec:
containers:
- name: {{ Values.appName }}
image: {{ Values.image.repository }}:{{ Values.image.tag }}
ports:
- containerPort: {{ Values.service.port }}
{% if Values.env %}
env:
{% for e in Values.env %}
- name: {{ e.name }}
value: "{{ e.value }}"
{% endfor %}
{% endif %}
{% if Values.resources %}
resources:
{% if Values.resources.limits %}
limits:
{% for lim in Values.resources.limits %}
{{ lim.Key }}: {{ lim.Value }}
{% endfor %}
{% endif %}
{% if Values.resources.requests %}
requests:
{% for req in Values.resources.requests %}
{{ req.Key }}: {{ req.Value }}
{% endfor %}
{% endif %}
{% endif %}
{% if Values.volumeMounts %}
volumeMounts:
{% for m in Values.volumeMounts %}
- name: {{ m.name }}
mountPath: {{ m.mountPath }}
{% if m.readOnly %}
readOnly: {{ m.readOnly }}
{% endif %}
{% endfor %}
{% endif %}
{% if Values.volumes %}
volumes:
{% for v in Values.volumes %}
- name: {{ v.name }}
{% if v.configMap %}
configMap:
name: {{ v.configMap.name }}
{% endif %}
{% if v.secret %}
secret:
secretName: {{ v.secret.secretName }}
{% endif %}
{% if v.persistentVolumeClaim %}
persistentVolumeClaim:
claimName: {{ v.persistentVolumeClaim.claimName }}
{% endif %}
{% endfor %}
{% endif %}
{% if Values.nodeSelector %}
nodeSelector:
{% for ns in Values.nodeSelector %}
{{ ns.Key }}: {{ ns.Value }}
{% endfor %}
{% endif %}
{% if Values.tolerations %}
tolerations:
{% for t in Values.tolerations %}
- key: {{ t.key }}
operator: {{ t.operator }}
{% if t.value %}
value: {{ t.value }}
{% endif %}
effect: {{ t.effect }}
{% endfor %}
{% endif %}
---
{% if Values.service.enabled %}
apiVersion: v1
kind: Service
metadata:
name: {{ Values.appName }}-service
namespace: {{ Values.namespace }}
labels:
app: {{ Values.appName }}
spec:
type: {{ Values.service.type }}
ports:
- port: {{ Values.service.port }}
targetPort: {{ Values.service.targetPort }}
protocol: TCP
{% if Values.service.nodePort %}
nodePort: {{ Values.service.nodePort }}
{% endif %}
selector:
app: {{ Values.appName }}
{% endif %}
---
{% if Values.ingress.enabled %}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ Values.appName }}-ingress
namespace: {{ Values.namespace }}
{% if Values.ingress.annotations %}
annotations:
{% for a in Values.ingress.annotations %}
{{ a.Key }}: "{{ a.Value }}"
{% endfor %}
{% endif %}
spec:
{% if Values.ingress.tls %}
tls:
{% for t in Values.ingress.tls %}
- hosts:
{% for h in t.hosts %}
- {{ h }}
{% endfor %}
secretName: {{ t.secretName }}
{% endfor %}
{% endif %}
rules:
{% for host in Values.ingress.hosts %}
- host: {{ host.host }}
http:
paths:
{% for p in host.paths %}
- path: {{ p.path }}
pathType: {{ p.pathType }}
backend:
service:
name: {{ Values.appName }}-service
port:
number: {{ Values.service.port }}
{% endfor %}
{% endfor %}
{% endif %}

Loading
Loading