Assisted warmup with the Zing JVM Ivn Kr lov @JohnWings Assisted - - PowerPoint PPT Presentation

assisted warmup with the zing jvm
SMART_READER_LITE
LIVE PREVIEW

Assisted warmup with the Zing JVM Ivn Kr lov @JohnWings Assisted - - PowerPoint PPT Presentation

Assisted warmup with the Zing JVM Ivn Kr lov @JohnWings Assisted warmup with the Zing JVM Overview of 3 technologies Falcon compiler ReadyNow & Compile Stashing Challenges (largely universal to all AOTs) Identification


slide-1
SLIDE 1

Assisted warmup with the Zing JVM

Iván Krȳlov @JohnWings

slide-2
SLIDE 2

Assisted warmup with the Zing JVM

  • Overview of 3 technologies
  • Falcon compiler
  • ReadyNow & Compile Stashing
  • Challenges (largely universal to all AOTs)
  • Identification of classloaders & classes
  • Timing of class’ initializers
  • Consistency of class generators

!2

slide-3
SLIDE 3

!3

  • Zing: A better JVM for the your servers
  • Consistent performance - not just fast, always fast
  • Eliminate GC as a concern for large apps
  • Very wide operating range
  • From human-sensitive app responsiveness to low-latency

trading

  • From microservices to huge in-memory apps
  • Eliminates an entire class of engineering workarounds

common in Java

  • Home for Falcon, ReadyNow, Compile Stashing and other

technologies

Zing

slide-4
SLIDE 4

Sources in .java Bytecodes

Machine code from the Interpreter Machine code from a compiler

Javac
 1) Static verification
 2) Compilation with near-0 opts Runtime
 1) Dynamic verification
 2) Linking One of N compilers
 Governed by runtime next tier deoptimization live
 profile data

Code pipeline in JVM

slide-5
SLIDE 5

Falcon

!5

A new LLVM-based JIT for JVM-languages in Zing VM

slide-6
SLIDE 6

“The LLVM Project is a collection of modular and reusable compiler and toolchain technologies”

– llvm.org

slide-7
SLIDE 7

Where LLVM is used?

  • C/C++/Objective C
  • Swift
  • Haskell
  • Rust

!7

slide-8
SLIDE 8

Who makes LLVM?

!8

More than 500 developers

slide-9
SLIDE 9

A typical llvm-based compiler

!9

LLVM Optimizer GHC Frontend llvm-gcc Frontend Clang C/C++/ ObjectiveC Frontend LLVM ARM Backend LLVM PowerPC Backend LLVM X86 Backend C Fortran Haskell X86 Power PC ARM LLVM IR LLVM IR

slide-10
SLIDE 10

Java Specific
 Optimizations

New concepts for LLVM

!13

Bytecode Frontend Java Bytecode LLVM IR

JVM

LLVM X86 Backend Installed Method LLVM Optimizer 


PassManager PM; PM.addPass(createLLVMPassA()); PM.addPass(createLLVMPassB()); PM.addPass(createAzulPassA()); PM.addPass(createLLVMPassC()); PM.addPass(createAzulPassB()); …

LLVM IR machine code LLVM VM Callbacks

GC Safepoint Deopt Safepoint

slide-11
SLIDE 11

Support for new CPUs

Thanks to Intel’s hard work on LLVMs backed Falcon emits AVX-512 instructions from the day those CPUs are on the market

!14

slide-12
SLIDE 12

Faster feature development

  • A. Thomas, JVMLS 2018, https://www.youtube.com/watch?v=2HfnaXND7-M

!15

slide-13
SLIDE 13

Simple things done simpler

  • Developing new intrinsics is super-easy
  • Example for onSpinWait intrinsic written in LLVM IR

declare void @llvm.x86.sse2.pause() nounwind ;; intrinsic for java.lang.Thread.onSpinWait() define zing void @_onSpinWait_performance_Hints() nounwind alwaysinline "azul-inlining-candidate" { entry: call void @llvm.x86.sse2.pause() nounwind ret void }

!16

slide-14
SLIDE 14

On Falcon performance

  • Beats our own C2 across the board
  • Looks good against other VMs

!17

slide-15
SLIDE 15

Falcon vs OpenJDK 8u171

Individual java tests Green - Falcon is ahead Red - Falcon is behind Falcon score OpenJDK 8 score * 100

!18

slide-16
SLIDE 16

Falcon vs OpenJDK 10

Individual java tests Green - Falcon is ahead Red - Falcon is behind Falcon score OpenJDK 10 score * 100

!19

slide-17
SLIDE 17

ReadyNow

  • To reduces warmup times
  • To avoid mistakes of JITs speculative optimizations
  • Achieved by feeding information from pervious run
  • Very simple to use: -XX:ProfileLogOut=yourapp.log


and -XX:ProfileLogIn=yourapp.log

!20

slide-18
SLIDE 18

Terminology: profile

  • Method’s Live profile - memory structure inside of JVM

filled during warm up and updated as needed

!21

slide-19
SLIDE 19

Terminology: profile

  • Method’s Live profile - memory structure inside of JVM

filled during warm up and updated as needed

  • Method’s Persisted profile - the one externally saved to

a “file” during one run and used during the other

  • Can be in per-method context or full-application

context

!21

slide-20
SLIDE 20

On ReadyNow performance

slide-21
SLIDE 21

!23

ReadyNow

transaction time / latency

300 sec

Original With ReadyNow

slide-22
SLIDE 22

Compile Stashing

  • Reuse top-tier compilation
  • Applied to JDK and user code
  • Challenges are the same as for

JAOT

!25

slide-23
SLIDE 23

Compiled Methods

VM Callbacks API

Bytecode Frontend Java Bytecode LLVM IR

JVM

LLVM X86 Backend Installed Method LLVM LLVM IR machine code LLVM VM Callbacks

!26

slide-24
SLIDE 24

Compiled Methods

Bytecode Frontend LLVM IR LLVM machine code VM Callbacks Queriers Responses

!27

slide-25
SLIDE 25

Compiled Methods

Bytecode Frontend LLVM IR LLVM machine code VM Callbacks Queriers Responses

!29

java.lang.String::concat(String)

Initial IR (method byte codes & live profile) Queries & Responses Produced Machine Code

slide-26
SLIDE 26

java.lang.String::concat(String)

Initial IR (method byte codes & live profile) Queries & Responses Produced Machine Code

Determinism in compilation

!30

slide-27
SLIDE 27

Compiled Methods

Bytecode Frontend LLVM IR LLVM machine code VM Callbacks Queriers Responses

!32

java.lang.String::concat(String)

Initial IR (method byte codes & live profile) Queries & Responses Produced Machine Code

slide-28
SLIDE 28

More on Falcon

  • A. Pilipenko, I. Krylov, JFocus 2018, https://www.youtube.com/watch?v=XovFnMw_eGk

!33

slide-29
SLIDE 29

Challenges

slide-30
SLIDE 30

Class Referencing Profile Normalization Class’ and method’ instrumentation Classloader identity Class generators Static Initializers

!35

Challenges

slide-31
SLIDE 31

Class referencing

slide-32
SLIDE 32

Referencing a class in IR

!37

class Merchandise { Map<Integer, String> merchandise; int getLength() { return merchandise.size(); } }

slide-33
SLIDE 33

Devirtualization

!38

// IR written as pseudo C++ code 
 int getLength() { if (merchandise instanceof HashMap) { return HashMap::size(); } else { // Continue in interpreter & perhaps recompile
 } }

slide-34
SLIDE 34

Classes as pointers

!39

// IR written as pseudo C++ code 
 int getLength() { if (merchandise instanceof 0x4d3v7ef0) { return 0x4d3v7ef0::size(); } else { // Deoptimize and continue in interpreter
 } }

slide-35
SLIDE 35

Zing uses persistent klass ids

!40

// IR written as pseudo C++ code 
 int getLength() { if (merchandise instanceof 336) { return 336::size(); } else { // Deoptimize and continue in interpreter
 } }

Klass id Klass address 335 0x4d3e4d20 336 0x4d3e4df0 337 0x4d3ea03c 338 0x447c21d0

slide-36
SLIDE 36

✓ Class Referencing

Profile Normalization Class’ and method’ instrumentation Classloader identity Class generators Static Initializers

!41

Challenges

slide-37
SLIDE 37

Profile Normalization

slide-38
SLIDE 38

!43

public int indexOf(int ch, int fromIndex) { final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }

j.l.String::indexOf

slide-39
SLIDE 39

public int indexOf(int ch, int fromIndex) { final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }

!44

public int indexOf(int, int); Code: 0: aload_0 1: getfield #3 // Field value:[C 4: arraylength 5: istore_3 6: iload_2 7: ifge 15 10: iconst_0 11: istore_2 12: goto 22 15: iload_2 16: iload_3 17: if_icmplt 22 20: iconst_m1 21: ireturn 22: iload_1 23: ldc #62 // int 65536 25: if_icmpge 63 28: aload_0 29: getfield #3 // Field value:[C 32: astore 4 34: iload_2 35: istore 5 37: iload 5 39: iload_3 40: if_icmpge 61 43: aload 4 45: iload 5 47: caload 48: iload_1 49: if_icmpne 55 52: iload 5

BCI:7 Value: True:0 False: 2471 BCI:17 Value: True:357 False: 2112 BCI:25 Value: True:2112 False: 0 BCI:40 Value: True:149604 False: 2003 BCI:49 Value: True:109 False: 149495

Live profile

slide-40
SLIDE 40

!45

BCI:7 Value: True:0 False: 2471 BCI:17 Value: True:357 False: 2112 BCI:25 Value: True:2112 False: 0 BCI:40 Value: True:149604 False: 2003 BCI:49 Value: True:109 False: 149495 BCI:7 Value: True:0 False: 1000 BCI:17 Value: True:100 False: 1000 BCI:25 Value: True:1000 False: 0 BCI:40 Value: True:100000 False: 1000 BCI:49 Value: True:100 False: 100000

After normalization

slide-41
SLIDE 41

✓ Class Referencing ✓ Profile Normalization

Class’ and method’ instrumentation Classloader identity Class generators Static Initializers

!46

Challenges

slide-42
SLIDE 42

Class’ and method’ instrumentation

slide-43
SLIDE 43

!48

public int indexOf(int ch, int fromIndex) { final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }

modified j.l.String::indexOf

slide-44
SLIDE 44

!48

public int indexOf(int ch, int fromIndex) { final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }

modified j.l.String::indexOf

MyAgent.incrementCounter();

slide-45
SLIDE 45

!49

public int indexOf(int ch, int fromIndex) { MyAgent.incrementCounter(); final int max = value.length; if (fromIndex < 0) { fromIndex = 0; } else if (fromIndex >= max) { return -1; } if (ch < Character.MIN_SUPPLEMENTARY_CODE_POINT) { final char[] value = this.value; for (int i = fromIndex; i < max; i++) { if (value[i] == ch) { return i; } } return -1; } else { return indexOfSupplementary(ch, fromIndex); } }

modified j.l.String::indexOf

public int indexOf(int, int); Code: 0: invokestatic #61 3: aload_0 4: getfield #3 7: arraylength 8: istore_3 9: iload_2 10: ifge 18 13: iconst_0 14: istore_2 15: goto 25 18: iload_2 19: iload_3 20: if_icmplt 25 23: iconst_m1 24: ireturn 25: iload_1 26: ldc #63 28: if_icmpge 66 31: aload_0

* * *

slide-46
SLIDE 46

!50

Without and with modification

public int indexOf(int, int); Code: 0: aload_0 1: getfield #3 4: arraylength 5: istore_3 6: load_2 7: ifge 15 10: iconst_0 11: istore_2 12: goto 22 15: iload_2 16: iload_3 17: if_icmplt 22 20: iconst_m1 21: ireturn 22: iload_1 23: ldc #62 25: if_icmpge 63 28: aload_0

* * *

public int indexOf(int, int); Code: 0: invokestatic #61 3: aload_0 4: getfield #3 7: arraylength 8: istore_3 9: iload_2 10: ifge 18 13: iconst_0 14: istore_2 15: goto 25 18: iload_2 19: iload_3 20: if_icmplt 25 23: iconst_m1 24: ireturn 25: iload_1 26: ldc #63 28: if_icmpge 66 31: aload_0

* * *

slide-47
SLIDE 47

!51

Without and with modification

BCI:7 Value: True:0 False: 2471 BCI:17 Value: True:357 False: 2112 BCI:25 Value: True:2112 False: 0

?

slide-48
SLIDE 48

✓ Class Referencing ✓ Profile Normalization ✓ Class’ and method’ instrumentation

Classloader identity Class generators Static Initializers

!52

Challenges

slide-49
SLIDE 49

Classloader Identification

slide-50
SLIDE 50

Classloader example

!54

Example 1

ClassLoader ClassLoader Class A Class B Class A Class B

slide-51
SLIDE 51

Classloader example

!55

Example 1

ClassLoader CL1 ClassLoader CL2

class CLexample { CustomClassLoader loader1 = new CustomClassLoader(); CustomClassLoader loader2 = new CustomClassLoader(); Class<?> class1A = loader1.loadClass("ClassA"); Class<?> class2A = loader1.loadClass("ClassA"); Class<?> class1B = loader2.loadClass("ClassB"); Class<?> class2B = loader2.loadClass(“ClassB"); } class CustomClassLoader extends ClassLoader{ //… }

slide-52
SLIDE 52

Classloader example

!56

Example 1

ClassLoader ClassLoader Class A Class B Class A Class B

slide-53
SLIDE 53

Classloader example - Java 9

!57

Example 1

ClassLoader CL1 ClassLoader CL2

class CLexample_v9 { CustomClassLoader loader1 = new CustomClassLoader(“Foo”); CustomClassLoader loader2 = new CustomClassLoader(“Bar”); Class<?> class1A = loader1.loadClass("ClassA"); Class<?> class2A = loader1.loadClass("ClassA"); Class<?> class1B = loader1.loadClass("ClassB"); Class<?> class2B = loader1.loadClass("ClassB"); } class CustomClassLoader extends ClassLoader{ public CustomClassLoader(String name) { super(name, null); } ... }

slide-54
SLIDE 54

Classloader names

  • Same name for all - not useful
  • Truly unique (i.e. Random()) - not useful
  • Unique within the run, repeated across runs - good!

!59

slide-55
SLIDE 55

Classloaders identification algos

  • Name
  • Automatic
  • works for classloaders created for distinct

purposes

!60

slide-56
SLIDE 56

✓ Class Referencing ✓ Profile Normalization ✓ Class’ and method’ instrumentation ✓ Classloader identity

Class generators Static Initializers

!61

Challenges

slide-57
SLIDE 57

Class generators

slide-58
SLIDE 58

Class generators Case study Lambda metafactory

!63

slide-59
SLIDE 59

Lambda example (1)

2 2

64

slide-60
SLIDE 60

Lambda example (2)

class Square { public static DoubleUnaryOperator fn = d -> d * d; } class Cube { public static DoubleUnaryOperator fn = d -> d * d * d; }

65

slide-61
SLIDE 61

Lambda example (3)

public double computeIntegral(DoubleUnaryOperator fn) { double result = 0.0; for (double d = start; d < end + IntegralTest.espilon ; d +=step) { result += step * op.applyAsDouble(d); } return result; }

66

slide-62
SLIDE 62

Lambda example - two runs

{ t1 = new Thread("Thread 1") { public void run(){ test.integralValue1 = test.computeIntegral(Square.fn); } }.start(); t2 = new Thread("Thread 2") { public void run(){ test.integralValue2 = test.computeIntegral(Cube.fn); } }.start(); }

67

slide-63
SLIDE 63

Generated Classes

First run

Second run

java -Djdk.internal.lambda.dumpProxyClasses=./lambda_classes_openjdk IntegralTest

$ ls lambda_classes_openjdk 
 'Square$$Lambda$2.class' ‘Cube$$Lambda$1.class'
 $ ls lambda_classes_openjdk 
 ‘Square$$Lambda$1.class’ ‘Cube$$Lambda$2.class'


68

slide-64
SLIDE 64

TraceClassLoading

Order 1

Order 2

java -XX:+TraceClassLoading IntegralTest

[Loaded Cube$$Lambda$1/1418481495 from Cube] [Loaded Square$$Lambda$2/1044036744 from Square] [Loaded Square$$Lambda$1/531885035 from Square] [Loaded Cube$$Lambda$2/142257191 from Cube]

69

slide-65
SLIDE 65

LMF solution

  • Normalize names
  • Replace LambdaMetafactory with an alternative

70

slide-66
SLIDE 66

Shout to classgen writers

  • Classname
  • Unique within a given run
  • Consistent across runs

71

slide-67
SLIDE 67

✓ Class Referencing ✓ Profile Normalization ✓ Class’ and method’ instrumentation ✓ Classloader identity ✓ Class generators

Static Initializers

!72

Challenges

slide-68
SLIDE 68

–Johnny Appleseed

“Type a quote here.”

Static Initializers

slide-69
SLIDE 69

Terminology: method bar requires class Foo

!74

void bar(int param) { if (param != 0) { Foo a; // * * * } else { // * * * } }

slide-70
SLIDE 70

When class may be initialized?

!75

JVMLS for Java 8. Section 5.5: Initialization 
 
 Initialization of a class or interface consists of executing its class or interface initialization method (§2.9). A class or interface C may be initialized only as a result of:

  • The execution of any one of the Java Virtual

Machine instructions new, getstatic, putstatic, or invokestatic that references C (§new, §getstatic, §putstatic, §invokestatic). These instructions reference a class or interface directly or indirectly through either a field reference or a method reference
 …..

https://docs.oracle.com/javase/specs/jvms/se8/jvms8.pdf

slide-71
SLIDE 71

9:00 10:30

class Foo first used VM started

11:30

method bar compiled class Foo initialized

Order of events

76

10:00 9:30

slide-72
SLIDE 72

9:00 10:30

class Foo first used VM started

11:30

method bar compiled class Foo initialized

Order of events

77

10:00 9:30

?

slide-73
SLIDE 73

9:00 10:30

class Foo first used VM started

11:30

method bar compiled class Foo initialized

Order of events

78

10:00 9:30

slide-74
SLIDE 74

9:00 10:30

class Foo first used VM started

11:30

method bar compiled class Foo initialized

Order of events

80

10:00 9:30

?

early

slide-75
SLIDE 75

May JVM early initialize this?

class Foo { int baz; }

class Foo0 { int bar; Foo1(); Code: 0: aload_0 1: invokespecial #1// Method j.l.Object.”<init>”:()V 4: return }

81

slide-76
SLIDE 76

And this?

class Foo { static final java.lang.Integer bar; Foo2(); Code: 0: aload_0 1: invokespecial #1 // Method j.l.Object.”<init>”:()V 4: return static {}; Code: 0: new #2 // class j.l.Integer 3: dup 4: bipush 42 6: invokespecial #3 // Method j.l.Integer.”<init>”:(I)V 9: putstatic #4 // Field bar:Ljava/lang/Integer; 12: return }

class Foo { final static Integer bad = new Integer(42); }

82

slide-77
SLIDE 77

And this???

class Foo { static final LocalDateTime baz = LocalDateTime.now(); }

83

9:00 10:30

class Foo first used VM started

11:30

method bar compiled class Foo initialized

10:00 9:30

class Foo initialized ? method bar compiled early

slide-78
SLIDE 78

And this???

class Foo3 { static final java.time.LocalDateTime bar; Foo3(); Code: 0: aload_0 1: invokespecial #1 // Method java.lang.Object.”<init>”:()V 4: return static {}; Code: 0: invokestatic #2 // Method j.time.LocalDateTime.now:()Ljava/time/LocalDateTime; 3: putstatic #3 // Field bar:Ljava/time/LocalDateTime; 6: return }

class Foo3 { final LocalDateTime bar = LocalDateTime.now(); }

84

slide-79
SLIDE 79

SimpleEnum

>ll SimpleEnum.java

  • rw-r--r-- 1 ivan staff 35 Feb 23 21:30 SimpleEnum.java

>ll SimpleEnum.class

  • rw-r--r-- 1 ivan staff 732 Feb 23 21:30 SimpleEnum.class

public enum SimpleEnum { One };

85

slide-80
SLIDE 80

SimpleEnum

Compiled from "SimpleEnum.java" public final class SimpleEnum extends java.lang.Enum<SimpleEnum> { public static final SimpleEnum One; public static SimpleEnum[] values(); Code: 0: getstatic #1 // Field $VALUES:[LSimpleEnum; 3: invokevirtual #2 // Method "[LSimpleEnum;".clone:()Ljava/lang/Object; 6: checkcast #3 // class "[LSimpleEnum;" 9: areturn public static SimpleEnum valueOf(java.lang.String); Code: 0: ldc #4 // class SimpleEnum 2: aload_0 3: invokestatic #5 // Method java/lang/Enum.valueOf:(Ljava/lang/Class;Ljava/lang/String;)Ljava/lang/Enum; 6: checkcast #4 // class SimpleEnum 9: areturn static {}; Code: 0: new #4 // class SimpleEnum 3: dup 4: ldc #7 // String One 6: iconst_0 7: invokespecial #8 // Method "<init>":(Ljava/lang/String;I)V 10: putstatic #9 // Field One:LSimpleEnum; 13: iconst_1 14: anewarray #4 // class SimpleEnum 17: dup 18: iconst_0 19: getstatic #9 // Field One:LSimpleEnum; 22: aastore 23: putstatic #1 // Field $VALUES:[LSimpleEnum; 26: return }

public enum SimpleEnum { One };

85

slide-81
SLIDE 81

Is it simple?

static { Code: 0: new #4 // class SimpleEnum 3: dup 4: ldc #7 // String One 6: iconst_0 7: invokespecial #8 // Method “<init>”:(Lj.l.String;I)V 10: putstatic #9 // Field One:LSimpleEnum; 13: iconst_1 14: anewarray #4 // class SimpleEnum 17: dup 18: iconst_0 19: getstatic #9 // Field One:LSimpleEnum; 22: aastore 23: putstatic #1 // Field $VALUES:[LSimpleEnum; 26: return }

public enum SimpleEnum { One };

86

slide-82
SLIDE 82

✓ Class Referencing ✓ Profile Normalization ✓ Class’ and method’ instrumentation ✓ Classloader identity ✓ Class generators ✓ Static Initializers

!87

Challenges

slide-83
SLIDE 83

Conclusions

  • Innovations in JITs and Runtimes continue
  • ”Assisted” warmup is challenging

!88

slide-84
SLIDE 84

Can I try it?

  • ReadyNow
  • Since 04/2015
  • Falcon
  • Since 12/2016
  • Compile Stashing
  • Since 12/2017

!89

slide-85
SLIDE 85

Questions?

http://www.azul.com/zingtrial/ How to try?

Iván Krȳlov @JohnWings

http://docs.azul.com/zing/zing-quick-start-fp.htm

slide-86
SLIDE 86

Pictures references

https://www.publicdomainpictures.net/en/view-image.php?image=133995&picture=honda-generator https://cdn.pixabay.com/photo/2016/09/01/17/18/profile-1636642_960_720.png http://www.publicdomainpictures.net/download-picture.php?id=117770&check=ae32542cbc42a32769782673144d168d http://www.picserver.org/highway-signs2/images/reference.jpg https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTR6oN4158MtVGPSuQ_hBoQLlaVTe7eq_U3CTCFqr9LOE2KprrD http://techfrag.com/wp-content/uploads/2015/10/Intel_Xeon_Skylake_0.jpg https://cdn.comsol.com/wordpress/2014/04/integral.png https://www.maxpixel.net/static/photo/2x/Hashtag-Hash-Social-Analytics-Hash-Tag-Pencils-2998837.jpg https://upload.wikimedia.org/wikipedia/commons/thumb/4/46/Plasma_globe_60th.jpg/1920px-Plasma_globe_60th.jpg https://tenyearsago.files.wordpress.com/2012/06/bourne-2_2.jpg

!91