InteropBenchmark.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Reflection;
  4. using BenchmarkDotNet.Attributes;
  5. using Jint.Native;
  6. using Jint.Native.Array;
  7. namespace Jint.Benchmark
  8. {
  9. [MemoryDiagnoser]
  10. public class InteropBenchmark
  11. {
  12. private const int OperationsPerInvoke = 1_000;
  13. public class Person
  14. {
  15. public string Name { get; set; }
  16. }
  17. private Engine _engine;
  18. [GlobalSetup]
  19. public void Setup()
  20. {
  21. _engine = new Engine(cfg => cfg.AllowClr(
  22. typeof(Person).GetTypeInfo().Assembly,
  23. typeof(Console).GetTypeInfo().Assembly,
  24. typeof(System.IO.File).GetTypeInfo().Assembly))
  25. .SetValue("log", new Action<object>(Console.WriteLine))
  26. .SetValue("assert", new Action<bool>(x => { }))
  27. .SetValue("equal", new Action<object, object>((x, y) => { }));
  28. }
  29. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  30. public void DelegatesCanBeSet()
  31. {
  32. for (int i = 0; i < OperationsPerInvoke; ++i)
  33. {
  34. _engine.SetValue("square", new Func<double, double>(x => x * x));
  35. _engine.Execute("assert(square(10) === 100);");
  36. }
  37. }
  38. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  39. public void ExtraParametersAreIgnored()
  40. {
  41. for (int i = 0; i < OperationsPerInvoke; ++i)
  42. {
  43. _engine.SetValue("passNumber", new Func<int, int>(x => x));
  44. _engine.Execute("assert(passNumber(123,'test',{},[],null) === 123);");
  45. }
  46. }
  47. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  48. public void GetObjectProperties()
  49. {
  50. var p = new Person
  51. {
  52. Name = "Mickey Mouse"
  53. };
  54. for (int i = 0; i < OperationsPerInvoke; ++i)
  55. {
  56. _engine.SetValue("p", p);
  57. _engine.Execute("assert(p.Name === 'Mickey Mouse');");
  58. }
  59. }
  60. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  61. public void InvokeObjectMethods()
  62. {
  63. var p = new Person
  64. {
  65. Name = "Mickey Mouse"
  66. };
  67. for (int i = 0; i < OperationsPerInvoke; ++i)
  68. {
  69. _engine.SetValue("p", p);
  70. _engine.Execute(@"assert(p.ToString() === 'Mickey Mouse');");
  71. }
  72. }
  73. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  74. public void SetObjectProperties()
  75. {
  76. var p = new Person
  77. {
  78. Name = "Mickey Mouse"
  79. };
  80. for (int i = 0; i < OperationsPerInvoke; ++i)
  81. {
  82. _engine.SetValue("p", p);
  83. _engine.Execute("p.Name = 'Donald Duck'; assert(p.Name === 'Donald Duck');");
  84. }
  85. }
  86. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  87. public void GetIndexUsingStringKey()
  88. {
  89. var dictionary = new Dictionary<string, Person>();
  90. dictionary.Add("person1", new Person {Name = "Mickey Mouse"});
  91. dictionary.Add("person2", new Person {Name = "Goofy"});
  92. for (int i = 0; i < OperationsPerInvoke; ++i)
  93. {
  94. _engine.SetValue("dictionary", dictionary);
  95. _engine.Execute("assert(dictionary['person1'].Name === 'Mickey Mouse'); assert(dictionary['person2'].Name === 'Goofy');");
  96. }
  97. }
  98. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  99. public void GenericMethods()
  100. {
  101. var dictionary = new Dictionary<int, string>
  102. {
  103. {1, "Mickey Mouse"}
  104. };
  105. for (int i = 0; i < OperationsPerInvoke; ++i)
  106. {
  107. _engine.SetValue("dictionary", dictionary);
  108. _engine.Execute("dictionary.Clear(); dictionary.Add(2, 'Goofy'); assert(dictionary[2] === 'Goofy');");
  109. }
  110. }
  111. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  112. public void MultiGenericTypes()
  113. {
  114. for (int i = 0; i < OperationsPerInvoke; ++i)
  115. {
  116. _engine.Execute(@"
  117. var type = System.Collections.Generic.Dictionary(System.Int32, System.String);
  118. var dictionary = new type();
  119. dictionary.Add(1, 'Mickey Mouse');
  120. dictionary.Add(2, 'Goofy');
  121. assert(dictionary[2] === 'Goofy');
  122. ");
  123. }
  124. }
  125. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  126. public void IndexOnList()
  127. {
  128. var list = new List<object>(2);
  129. list.Add("Mickey Mouse");
  130. list.Add("Goofy");
  131. for (int i = 0; i < OperationsPerInvoke; ++i)
  132. {
  133. _engine.SetValue("list", list);
  134. _engine.Execute("list[1] = 'Donald Duck'; assert(list[1] === 'Donald Duck');");
  135. }
  136. }
  137. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  138. public void EcmaValuesAreAutomaticallyConvertedWhenSetInPoco()
  139. {
  140. var p = new Person
  141. {
  142. Name = "foo",
  143. };
  144. for (int i = 0; i < OperationsPerInvoke; ++i)
  145. {
  146. _engine.SetValue("p", p);
  147. _engine.Execute(@"
  148. assert(p.Name === 'foo');
  149. assert(p.Age === 0);
  150. p.Name = 'bar';
  151. p.Age = 10;
  152. ");
  153. }
  154. }
  155. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  156. public void Trim()
  157. {
  158. var p = new Person
  159. {
  160. Name = "Mickey Mouse "
  161. };
  162. for (int i = 0; i < OperationsPerInvoke; ++i)
  163. {
  164. _engine.SetValue("p", p);
  165. _engine.Execute(@"
  166. assert(p.Name === 'Mickey Mouse ');
  167. p.Name = p.Name.trim();
  168. assert(p.Name === 'Mickey Mouse');
  169. ");
  170. }
  171. }
  172. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  173. public void MathFloor()
  174. {
  175. var p = new Person();
  176. for (int i = 0; i < OperationsPerInvoke; ++i)
  177. {
  178. _engine.SetValue("p", p);
  179. _engine.Execute("p.Age = Math.floor(1.6); assert(p.Age === 1);");
  180. }
  181. }
  182. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  183. public void DelegateAsFunction()
  184. {
  185. var even = new Func<int, bool>(x => x % 2 == 0);
  186. for (int i = 0; i < OperationsPerInvoke; ++i)
  187. {
  188. _engine.SetValue("even", even);
  189. _engine.Execute("assert(even(2) === true);");
  190. }
  191. }
  192. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  193. public void ConvertArrayToArrayInstance()
  194. {
  195. var ints = new[] {1, 2, 3, 4, 5, 6};
  196. for (int i = 0; i < OperationsPerInvoke; ++i)
  197. {
  198. _engine
  199. .SetValue("values", ints)
  200. .Execute("values.filter(function(x){ return x % 2 == 0; })");
  201. }
  202. }
  203. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  204. public void ConvertListsToArrayInstance()
  205. {
  206. var ints = new List<object> {1, 2, 3, 4, 5, 6};
  207. for (int i = 0; i < OperationsPerInvoke; ++i)
  208. {
  209. _engine
  210. .SetValue("values", ints)
  211. .Execute("new Array(values).filter(function(x){ return x % 2 == 0; })");
  212. }
  213. }
  214. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  215. public void ConvertArrayInstanceToArray()
  216. {
  217. for (int i = 0; i < OperationsPerInvoke; ++i)
  218. {
  219. _engine.Execute("'[email protected]'.split('@');");
  220. }
  221. }
  222. [Benchmark(OperationsPerInvoke = OperationsPerInvoke)]
  223. public void LoopWithNativeEnumerator()
  224. {
  225. JsValue Adder(JsValue argValue)
  226. {
  227. ArrayInstance args = argValue.AsArray();
  228. double sum = 0;
  229. foreach (var item in args)
  230. {
  231. if (item.IsNumber())
  232. {
  233. sum += item.AsNumber();
  234. }
  235. }
  236. return sum;
  237. }
  238. for (int i = 0; i < OperationsPerInvoke; ++i)
  239. {
  240. _engine.SetValue("getSum", new Func<JsValue, JsValue>(Adder));
  241. _engine.Execute("getSum([1,2,3]);");
  242. }
  243. }
  244. }
  245. }