From 62ad8b49731b69d9b9d2104877a0f5d357c3ca7b Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 20:34:27 +0000 Subject: [PATCH 1/8] [JS] Update npm dependencies and make the build.sh run webpack This way, we test it in CI to a degree. Signed-off-by: Stefan Marr --- benchmarks/JavaScript/build.sh | 10 ++++++++-- benchmarks/JavaScript/package.json | 21 ++++++++++++--------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/benchmarks/JavaScript/build.sh b/benchmarks/JavaScript/build.sh index e06860d8..e5cba3fd 100755 --- a/benchmarks/JavaScript/build.sh +++ b/benchmarks/JavaScript/build.sh @@ -4,11 +4,17 @@ SCRIPT_PATH="$(dirname "$0")" source "$SCRIPT_PATH/../script.inc" INFO Build Node.js Benchmarks +pushd "$SCRIPT_PATH" + if [[ "$1" = "style" ]] then INFO Check style of JavaScript benchmarks - pushd "$SCRIPT_PATH" + npx eslint . else - exit 0 + if [[ ! -d "node_modules" ]] + then + npm install + fi + npm run webpack fi diff --git a/benchmarks/JavaScript/package.json b/benchmarks/JavaScript/package.json index 1bac3810..bdd1ef1c 100644 --- a/benchmarks/JavaScript/package.json +++ b/benchmarks/JavaScript/package.json @@ -10,15 +10,18 @@ "author": "", "license": "MIT", "devDependencies": { - "@babel/core": "^7.19.6", - "@babel/preset-env": "^7.19.4", - "babel-loader": "^8.2.5", - "eslint": "^8.23.1", + "@babel/core": "^7.23.9", + "@babel/preset-env": "^7.23.9", + "babel-loader": "^9.1.3", + "eslint": "^8.56.0", "eslint-config-airbnb-base": "^15.0.0", - "eslint-plugin-import": "^2.26.0", - "eslint-plugin-n": "^15.2.5", - "eslint-plugin-promise": "^6.0.1", - "webpack": "^5.74.0", - "webpack-cli": "4.10.0" + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-n": "^16.6.2", + "eslint-plugin-promise": "^6.1.1", + "webpack": "^5.90.1", + "webpack-cli": "5.1.4" + }, + "prettier": { + "singleQuote": true } } From 3900dc56eec8a1375eb6c11ce8b36bad46d6d375 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 20:35:16 +0000 Subject: [PATCH 2/8] =?UTF-8?q?[JS]=20Style=20changes=20from=20Prettier=20?= =?UTF-8?q?formatter=E2=80=A6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Marr --- benchmarks/JavaScript/som.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/benchmarks/JavaScript/som.js b/benchmarks/JavaScript/som.js index d5aa6296..f3a91541 100644 --- a/benchmarks/JavaScript/som.js +++ b/benchmarks/JavaScript/som.js @@ -292,7 +292,7 @@ function hashFn(key) { return 0; } const hash = key.customHash(); - return hash ^ hash >>> 16; + return hash ^ (hash >>> 16); } class Dictionary { @@ -491,7 +491,7 @@ class Random { } next() { - this.seed = ((this.seed * 1309) + 13849) & 65535; + this.seed = (this.seed * 1309 + 13849) & 65535; return this.seed; } } From 273e92e5e2014717f7f6571df93c98a338863da6 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 20:40:13 +0000 Subject: [PATCH 3/8] Change Vector to initialize array lazily Signed-off-by: Stefan Marr --- benchmarks/Crystal/som.cr | 69 +++++++++++++++++----------- benchmarks/Java/src/som/Vector.java | 24 ++++++---- benchmarks/JavaScript/som.js | 22 ++++++--- benchmarks/Lua/som.lua | 30 +++++++++--- benchmarks/Python/som/vector.py | 24 +++++++--- benchmarks/Ruby/som.rb | 27 ++++++++--- benchmarks/SOM/Core/Vector.som | 51 ++++++++++++-------- benchmarks/SOMns/Core.ns | 48 +++++++++++-------- benchmarks/Smalltalk/Core/Vector.som | 51 ++++++++++++-------- 9 files changed, 227 insertions(+), 119 deletions(-) diff --git a/benchmarks/Crystal/som.cr b/benchmarks/Crystal/som.cr index 2a197f38..e1d2183a 100644 --- a/benchmarks/Crystal/som.cr +++ b/benchmarks/Crystal/som.cr @@ -19,6 +19,8 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +require "math" + INITIAL_SIZE = 10 INITIAL_CAPACITY = 16 @@ -41,48 +43,52 @@ class Vector(T) new_vector end - def initialize(size = 50) - @storage = Array(T).new(size, nil) + def initialize(size = 0) + @storage = size == 0 ? nil : Array(T).new(size, nil) @first_idx = 0 @last_idx = 0 end def at(idx) - if idx >= @storage.size + if @storage == nil || idx >= @storage.not_nil!.size return nil end - @storage[idx] + @storage.not_nil![idx] end def at_put(idx, val : T) - if idx >= @storage.size - new_length = @storage.size + if @storage == nil + @storage = Array(T).new(Math.max(idx + 1, INITIAL_SIZE), nil) + elsif idx >= @storage.not_nil!.size + new_length = @storage.not_nil!.size while new_length <= idx new_length *= 2 end new_storage = Array(T).new(new_length, nil) - @storage.each_index { | i | - new_storage[i] = @storage[i] + @storage.not_nil!.each_index { | i | + new_storage[i] = @storage.not_nil![i] } @storage = new_storage end - @storage[idx] = val + @storage.not_nil![idx] = val if @last_idx < idx + 1 @last_idx = idx + 1 end end def append(elem : T) - if @last_idx >= @storage.size + if @storage == nil + @storage = Array(T).new(INITIAL_SIZE, nil) + elsif @last_idx >= @storage.not_nil!.size # Need to expand capacity first - new_storage = Array(T).new(2 * @storage.size, nil) - @storage.each_index { | i | - new_storage[i] = @storage[i] + new_storage = Array(T).new(2 * @storage.not_nil!.size, nil) + @storage.not_nil!.each_index { | i | + new_storage[i] = @storage.not_nil![i] } @storage = new_storage end - @storage[@last_idx] = elem + @storage.not_nil![@last_idx] = elem @last_idx += 1 self end @@ -93,13 +99,13 @@ class Vector(T) def each # &block (@first_idx..(@last_idx - 1)).each { | i | - yield @storage[i].not_nil! + yield @storage.not_nil![i].not_nil! } end def has_some (@first_idx..(@last_idx - 1)).each { | i | - if yield @storage[i] + if yield @storage.not_nil![i] return true end } @@ -122,10 +128,14 @@ class Vector(T) end @first_idx += 1 - @storage[@first_idx - 1] + @storage.not_nil![@first_idx - 1] end def remove(obj) + if @storage == nil || empty? + return false + end + new_array = Array(T).new(capacity, nil) new_last = 0 found = false @@ -148,7 +158,10 @@ class Vector(T) def remove_all @first_idx = 0 @last_idx = 0 - @storage = Array(T).new(@storage.size, nil) + + if @storage + @storage = Array(T).new(@storage.not_nil!.size, nil) + end end def size @@ -156,7 +169,7 @@ class Vector(T) end def capacity - @storage.size + @storage == nil ? 0 : @storage.not_nil!.size end def sort(&block : T, T -> Bool) @@ -194,12 +207,12 @@ class Vector(T) end # Sort di, dj - di = @storage[i] - dj = @storage[j] + di = @storage.not_nil![i] + dj = @storage.not_nil![j] # i.e., should di precede dj? unless block.call(di, dj) - @storage.swap(i, j) + @storage.not_nil!.swap(i, j) tt = di di = dj dj = tt @@ -208,15 +221,15 @@ class Vector(T) # NOTE: For DeltaBlue, this is never reached. if n > 2 # More than two elements. ij = ((i + j) / 2).floor.to_i32 # ij is the midpoint of i and j. - dij = @storage[ij] # Sort di,dij,dj. Make dij be their median. + dij = @storage.not_nil![ij] # Sort di,dij,dj. Make dij be their median. if block.call(di, dij) # i.e. should di precede dij? unless block.call(dij, dj) # i.e., should dij precede dj? - @storage.swap(j, ij) + @storage.not_nil!.swap(j, ij) dij = dj end else # i.e. di should come after dij - @storage.swap(i, ij) + @storage.not_nil!.swap(i, ij) dij = di end @@ -227,16 +240,16 @@ class Vector(T) l = j - 1 while ( - while k <= l && block.call(dij, @storage[l]) # i.e. while dl succeeds dij + while k <= l && block.call(dij, @storage.not_nil![l]) # i.e. while dl succeeds dij l -= 1 end k += 1 - while k <= l && block.call(@storage[k], dij) # i.e. while dij succeeds dk + while k <= l && block.call(@storage.not_nil![k], dij) # i.e. while dij succeeds dk k += 1 end k <= l) - @storage.swap(k, l) + @storage.not_nil!.swap(k, l) end # Now l < k (either 1 or 2 less), and di through dl are all less than or equal to dk diff --git a/benchmarks/Java/src/som/Vector.java b/benchmarks/Java/src/som/Vector.java index dc23badd..aad09b71 100644 --- a/benchmarks/Java/src/som/Vector.java +++ b/benchmarks/Java/src/som/Vector.java @@ -45,20 +45,20 @@ public Vector(final int size) { storage = new Object[size]; } - public Vector() { - this(50); - } + public Vector() { } @SuppressWarnings("unchecked") public E at(final int idx) { - if (idx >= storage.length) { + if (storage == null || idx >= storage.length) { return null; } return (E) storage[idx]; } public void atPut(final int idx, final E val) { - if (idx >= storage.length) { + if (storage == null) { + storage = new Object[Math.max(idx + 1, Constants.INITIAL_SIZE)]; + } else if (idx >= storage.length) { int newLength = storage.length; while (newLength <= idx) { newLength *= 2; @@ -72,7 +72,9 @@ public void atPut(final int idx, final E val) { } public void append(final E elem) { - if (lastIdx >= storage.length) { + if (storage == null) { + storage = new Object[Constants.INITIAL_SIZE]; + } else if (lastIdx >= storage.length) { // Need to expand capacity first storage = Arrays.copyOf(storage, 2 * storage.length); } @@ -131,6 +133,10 @@ public E removeFirst() { } public boolean remove(final E obj) { + if (storage == null || isEmpty()) { + return false; + } + Object[] newArray = new Object[capacity()]; int[] newLast = new int[] {0}; boolean[] found = new boolean[] {false}; @@ -152,7 +158,9 @@ public boolean remove(final E obj) { public void removeAll() { firstIdx = 0; lastIdx = 0; - storage = new Object[storage.length]; + if (storage != null) { + storage = new Object[storage.length]; + } } public int size() { @@ -160,7 +168,7 @@ public int size() { } public int capacity() { - return storage.length; + return storage == null ? 0 : storage.length; } public void sort(final Comparator c) { diff --git a/benchmarks/JavaScript/som.js b/benchmarks/JavaScript/som.js index f3a91541..a605e84a 100644 --- a/benchmarks/JavaScript/som.js +++ b/benchmarks/JavaScript/som.js @@ -26,7 +26,7 @@ const INITIAL_CAPACITY = 16; class Vector { constructor(size) { - this.storage = new Array(size === undefined ? 50 : size); + this.storage = size === undefined ? null : new Array(size); this.firstIdx = 0; this.lastIdx = 0; } @@ -38,14 +38,16 @@ class Vector { } at(idx) { - if (idx >= this.storage.length) { + if (this.storage === null || idx >= this.storage.length) { return null; } return this.storage[idx]; } atPut(idx, val) { - if (idx >= this.storage.length) { + if (this.storage === null) { + this.storage = new Array(Math.max(idx + 1, INITIAL_SIZE)); + } else if (idx >= this.storage.length) { let newLength = this.storage.length; while (newLength <= idx) { newLength *= 2; @@ -60,7 +62,9 @@ class Vector { } append(elem) { - if (this.lastIdx >= this.storage.length) { + if (this.storage === null) { + this.storage = new Array(INITIAL_SIZE); + } else if (this.lastIdx >= this.storage.length) { // Copy storage to comply with rules, but don't extend storage const newLength = this.storage.length * 2; this.storage = this.storage.slice(); @@ -109,6 +113,10 @@ class Vector { } remove(obj) { + if (this.storage === null || this.isEmpty()) { + return false; + } + const newArray = new Array(this.capacity()); let newLast = 0; let found = false; @@ -131,7 +139,9 @@ class Vector { removeAll() { this.firstIdx = 0; this.lastIdx = 0; - this.storage = new Array(this.storage.length); + if (this.storage !== null) { + this.storage = new Array(this.storage.length); + } } size() { @@ -139,7 +149,7 @@ class Vector { } capacity() { - return this.storage.length; + return this.storage === null ? 0 : this.storage.length; } // eslint-disable-next-line no-unused-vars diff --git a/benchmarks/Lua/som.lua b/benchmarks/Lua/som.lua index de27dd75..7f91f2ad 100644 --- a/benchmarks/Lua/som.lua +++ b/benchmarks/Lua/som.lua @@ -63,10 +63,13 @@ end local Vector = {_CLASS = 'Vector'} do local floor = math.floor +local max = math.max + +local INITIAL_SIZE = 10 function Vector.new (size) local obj = { - storage = alloc_array(size or 50), + storage = (size and size > 0) and alloc_array(size) or nil, first_idx = 1, last_idx = 1, } @@ -80,14 +83,16 @@ function Vector.with (elem) end function Vector:at (idx) - if idx > self.storage.n then + if self.storage == nil or idx > self.storage.n then return nil end return self.storage[idx] end function Vector:at_put (idx, val) - if idx > self.storage.n then + if self.storage == nil then + self.storage = alloc_array(max(idx + 1, INITIAL_SIZE)) + elseif idx > self.storage.n then local new_n = self.storage.n while idx > new_n do new_n = new_n * 2 @@ -107,7 +112,9 @@ function Vector:at_put (idx, val) end function Vector:append (elem) - if self.last_idx > self.storage.n then + if self.storage == nil then + self.storage = alloc_array(INITIAL_SIZE) + elseif self.last_idx > self.storage.n then -- Need to expand capacity first local new_storage = alloc_array(2 * self.storage.n) for i = 1, self.storage.n do @@ -159,6 +166,10 @@ function Vector:remove_first () end function Vector:remove (obj) + if self.storage == nil or self:is_empty() then + return false + end + local new_array = alloc_array(self:capacity()) local new_last = 1 local found = false @@ -181,7 +192,10 @@ end function Vector:remove_all () self.first_idx = 1 self.last_idx = 1 - self.storage = alloc_array(self:capacity()) + + if self.storage ~= nil then + self.storage = alloc_array(self:capacity()) + end end function Vector:size () @@ -189,7 +203,11 @@ function Vector:size () end function Vector:capacity () - return self.storage.n + if self.storage == nil then + return 0 + else + return self.storage.n + end end function Vector:sort (fn) diff --git a/benchmarks/Python/som/vector.py b/benchmarks/Python/som/vector.py index 4ea2443d..a5ee8584 100644 --- a/benchmarks/Python/som/vector.py +++ b/benchmarks/Python/som/vector.py @@ -19,6 +19,7 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN # THE SOFTWARE. +from som.constants import INITIAL_SIZE def vector_with(elem): @@ -31,18 +32,20 @@ def vector_with(elem): # - does not use an explicit array bounds check, because Java already does # that. Don't see a point in doing it twice. class Vector: - def __init__(self, size=50): - self._storage = [None] * size + def __init__(self, size=0): + self._storage = [None] * size if size > 0 else None self._first_idx = 0 self._last_idx = 0 def at(self, idx): - if idx >= len(self._storage): + if self._storage is None or idx >= len(self._storage): return None return self._storage[idx] def at_put(self, idx, val): - if idx >= len(self._storage): + if self._storage is None: + self._storage = [None] * max(idx + 1, INITIAL_SIZE) + elif idx >= len(self._storage): new_length = len(self._storage) while new_length <= idx: new_length *= 2 @@ -57,7 +60,9 @@ def at_put(self, idx, val): self._last_idx = idx + 1 def append(self, elem): - if self._last_idx >= len(self._storage): + if self._storage is None: + self._storage = [None] * INITIAL_SIZE + elif self._last_idx >= len(self._storage): # Need to expand capacity first new_storage = [None] * (2 * len(self._storage)) for i in range(len(self._storage)): @@ -99,6 +104,9 @@ def remove_first(self): return self._storage[self._first_idx - 1] def remove(self, obj): + if self._storage is None or self.is_empty(): + return False + new_array = [None] * self.capacity() new_last = 0 found = False @@ -122,13 +130,15 @@ def each(it): def remove_all(self): self._first_idx = 0 self._last_idx = 0 - self._storage = [None] * len(self._storage) + + if self._storage is not None: + self._storage = [None] * len(self._storage) def size(self): return self._last_idx - self._first_idx def capacity(self): - return len(self._storage) + return 0 if self._storage is None else len(self._storage) def sort(self, comparator): if self.size() > 0: diff --git a/benchmarks/Ruby/som.rb b/benchmarks/Ruby/som.rb index 78b7854e..583fed45 100644 --- a/benchmarks/Ruby/som.rb +++ b/benchmarks/Ruby/som.rb @@ -34,6 +34,10 @@ def initialize(key, value) end end +def max(a, b) + a < b ? b : a +end + class Vector def self.with(elem) new_vector = new(1) @@ -41,20 +45,22 @@ def self.with(elem) new_vector end - def initialize(size = 50) - @storage = Array.new(size) + def initialize(size = 0) + @storage = size == 0 ? nil : Array.new(size) @first_idx = 0 @last_idx = 0 end def at(idx) - return nil if idx >= @storage.length + return nil if @storage == nil || idx >= @storage.length @storage[idx] end def at_put(idx, val) - if idx >= @storage.length + if @storage == nil + @storage = Array.new(max(idx + 1, INITIAL_SIZE)) + elsif idx >= @storage.length new_length = @storage.length new_length *= 2 while new_length <= idx @@ -70,7 +76,9 @@ def at_put(idx, val) end def append(elem) - if @last_idx >= @storage.size + if @storage == nil + @storage = Array.new(INITIAL_SIZE) + elsif @last_idx >= @storage.size # Need to expand capacity first new_storage = Array.new(2 * @storage.size) @storage.each_index do |i| @@ -117,6 +125,8 @@ def remove_first end def remove(obj) + return false if @storage == nil || empty? + new_array = Array.new(capacity) new_last = 0 found = false @@ -139,7 +149,10 @@ def remove(obj) def remove_all @first_idx = 0 @last_idx = 0 - @storage = Array.new(@storage.size) + + if @storage + @storage = Array.new(@storage.size) + end end def size @@ -147,7 +160,7 @@ def size end def capacity - @storage.size + @storage == nil ? 0 : @storage.size end def sort(&block) diff --git a/benchmarks/SOM/Core/Vector.som b/benchmarks/SOM/Core/Vector.som index 8ee7c35d..89c6e244 100644 --- a/benchmarks/SOM/Core/Vector.som +++ b/benchmarks/SOM/Core/Vector.som @@ -27,23 +27,28 @@ Vector = ( initialize: size = ( first := 1. last := 1. - storage := Array new: size. + + size = 0 + ifFalse: [ storage := Array new: size ] ) at: index = ( - index > storage length ifTrue: [ ^ nil ]. + (storage == nil or: [ index > storage length ]) ifTrue: [ ^ nil ]. ^ storage at: index ) at: index put: val = ( - index > storage length ifTrue: [ - | newLength newStorage | - newLength := storage length. - [ newLength < index ] whileTrue: [ - newLength := newLength * 2 ]. - newStorage := Array new: newLength. - storage doIndexes: [:i | newStorage at: i put: (storage at: i) ]. - storage := newStorage ]. + storage == nil ifTrue: [ + storage := Array new: (index + 1 max: 10) + ] ifFalse: [ + index > storage length ifTrue: [ + | newLength newStorage | + newLength := storage length. + [ newLength < index ] whileTrue: [ + newLength := newLength * 2 ]. + newStorage := Array new: newLength. + storage doIndexes: [:i | newStorage at: i put: (storage at: i) ]. + storage := newStorage ] ]. storage at: index put: val. last < (index + 1) ifTrue: [ @@ -51,12 +56,15 @@ Vector = ( ) append: element = ( - (last > storage length) ifTrue: [ - "Need to expand capacity first" - | newStorage | - newStorage := Array new: (2 * storage length). - storage doIndexes: [ :i | newStorage at: i put: (storage at: i) ]. - storage := newStorage. ]. + storage == nil ifTrue: [ + storage := Array new: 10 + ] ifFalse: [ + last > storage length ifTrue: [ + "Need to expand capacity first" + | newStorage | + newStorage := Array new: (2 * storage length). + storage doIndexes: [ :i | newStorage at: i put: (storage at: i) ]. + storage := newStorage ] ]. storage at: last put: element. last := last + 1. @@ -94,11 +102,16 @@ Vector = ( removeAll = ( first := 1. last := 1. - storage := Array new: storage length + + storage == nil ifFalse: [ + storage := Array new: storage length + ] ) remove: object = ( | newArray newLast found | + (storage == nil or: [ self isEmpty ]) ifTrue: [ ^ false ]. + newArray := Array new: self capacity. newLast := 1. found := false. @@ -117,7 +130,7 @@ Vector = ( ) size = ( ^ last - first ) - capacity = ( ^ storage length ) + capacity = ( storage == nil ifTrue: [ ^ 0 ] ifFalse: [ ^ storage length ] ) sort: aBlock = ( " Make the argument, aBlock, be the criterion for ordering elements of @@ -186,7 +199,7 @@ Vector = ( ---------------------------- "Allocation" - new = ( ^ self new: 50 ) + new = ( ^ self new: 0 ) new: initialSize = ( ^ super new initialize: initialSize ) with: elem = ( diff --git a/benchmarks/SOMns/Core.ns b/benchmarks/SOMns/Core.ns index d60f563e..6824d88b 100644 --- a/benchmarks/SOMns/Core.ns +++ b/benchmarks/SOMns/Core.ns @@ -34,22 +34,25 @@ class Core with: kernel = ( public class Vector new: size = ( | private firstIdx ::= 1. private lastIdx ::= 1. - private storage ::= Array new: size. + private storage ::= size = 0 ifFalse: [ Array new: size ]. |) ( public at: index = ( - index > storage size ifTrue: [ ^ nil ]. + (storage == nil or: [ index > storage size ]) ifTrue: [ ^ nil ]. ^ storage at: index ) public at: index put: val = ( - index > storage size ifTrue: [ - | newLength newStorage | - newLength:: storage size. - [ newLength < index ] whileTrue: [ - newLength:: newLength * 2 ]. - newStorage:: Array new: newLength. - storage doIndexes: [:i | newStorage at: i put: (storage at: i) ]. - storage:: newStorage ]. + storage == nil ifTrue: [ + storage:: Array new: (index + 1 max: 10). + ] ifFalse: [ + index > storage size ifTrue: [ + | newLength newStorage | + newLength:: storage size. + [ newLength < index ] whileTrue: [ + newLength:: newLength * 2 ]. + newStorage:: Array new: newLength. + storage doIndexes: [:i | newStorage at: i put: (storage at: i) ]. + storage:: newStorage ] ]. storage at: index put: val. lastIdx < (index + 1) ifTrue: [ @@ -57,12 +60,15 @@ class Core with: kernel = ( ) public append: element = ( - (lastIdx > storage size) ifTrue: [ - (* Need to expand capacity first *) - | newStorage | - newStorage:: Array new: 2 * storage size. - storage doIndexes: [ :i | newStorage at: i put: (storage at: i) ]. - storage:: newStorage. ]. + storage == nil ifTrue: [ + storage:: Array new: 10 + ] ifFalse: [ + (lastIdx > storage size) ifTrue: [ + (* Need to expand capacity first *) + | newStorage | + newStorage:: Array new: 2 * storage size. + storage doIndexes: [ :i | newStorage at: i put: (storage at: i) ]. + storage:: newStorage ] ]. storage at: lastIdx put: element. lastIdx:: lastIdx + 1. @@ -101,11 +107,15 @@ class Core with: kernel = ( public removeAll = ( firstIdx:: 1. lastIdx:: 1. - storage:: Array new: storage size + + storage == nil ifFalse: [ + storage:: Array new: storage size ] ) public remove: object = ( | newArray newLast found | + (storage == nil or: [ self isEmpty ]) ifTrue: [ ^ false ]. + newArray:: Array new: self capacity. newLast:: 1. found:: false. @@ -124,7 +134,7 @@ class Core with: kernel = ( ) public size = ( ^ lastIdx - firstIdx ) - public capacity = ( ^ storage size ) + public capacity = ( storage == nil ifTrue: [ ^ 0 ] ifFalse: [ ^ storage size ] ) public sort: aBlock = ( (* Make the argument, aBlock, be the criterion for ordering elements of @@ -190,7 +200,7 @@ class Core with: kernel = ( ] ) ) : ( - public new = ( ^ self new: 50 ) + public new = ( ^ self new: 0 ) public with: elem = ( | newVector | diff --git a/benchmarks/Smalltalk/Core/Vector.som b/benchmarks/Smalltalk/Core/Vector.som index ec76384d..a5bffdd6 100644 --- a/benchmarks/Smalltalk/Core/Vector.som +++ b/benchmarks/Smalltalk/Core/Vector.som @@ -27,23 +27,28 @@ Vector = ( initialize: size = ( first := 1. last := 1. - storage := Array new: size. + + size = 0 + ifFalse: [ storage := Array new: size ] ) at: index = ( - index > storage size ifTrue: [ ^ nil ]. + (storage == nil or: [ index > storage size ]) ifTrue: [ ^ nil ]. ^ storage at: index ) at: index put: val = ( - index > storage size ifTrue: [ - | newLength newStorage | - newLength := storage size. - [ newLength < index ] whileTrue: [ - newLength := newLength * 2 ]. - newStorage := Array new: newLength. - 1 to: storage size do: [:i | newStorage at: i put: (storage at: i) ]. - storage := newStorage ]. + storage == nil ifTrue: [ + storage := Array new: (index + 1 max: 10) + ] ifFalse: [ + index > storage size ifTrue: [ + | newLength newStorage | + newLength := storage size. + [ newLength < index ] whileTrue: [ + newLength := newLength * 2 ]. + newStorage := Array new: newLength. + 1 to: storage size do: [:i | newStorage at: i put: (storage at: i) ]. + storage := newStorage ] ]. storage at: index put: val. last < (index + 1) ifTrue: [ @@ -51,12 +56,15 @@ Vector = ( ) append: element = ( - (last > storage size) ifTrue: [ - "Need to expand capacity first" - | newStorage | - newStorage := Array new: (2 * storage size). - 1 to: storage size do: [:i | newStorage at: i put: (storage at: i) ]. - storage := newStorage. ]. + storage == nil ifTrue: [ + storage := Array new: 10 + ] ifFalse: [ + (last > storage size) ifTrue: [ + "Need to expand capacity first" + | newStorage | + newStorage := Array new: (2 * storage size). + 1 to: storage size do: [:i | newStorage at: i put: (storage at: i) ]. + storage := newStorage ] ]. storage at: last put: element. last := last + 1. @@ -94,11 +102,16 @@ Vector = ( removeAll = ( first := 1. last := 1. - storage := Array new: storage size + + storage == nil ifFalse: [ + storage := Array new: storage size + ] ) remove: object = ( | newArray newLast found | + (storage == nil or: [ self isEmpty ]) ifTrue: [ ^ false ]. + newArray := Array new: self capacity. newLast := 1. found := false. @@ -117,7 +130,7 @@ Vector = ( ) size = ( ^ last - first ) - capacity = ( ^ storage size ) + capacity = ( storage == nil ifTrue: [ ^ 0 ] ifFalse: [ ^ storage size ] ) sort: aBlock = ( " Make the argument, aBlock, be the criterion for ordering elements of @@ -186,7 +199,7 @@ Vector = ( ---------------------------- "Allocation" - new = ( ^ self new: 50 ) + new = ( ^ self new: 0 ) new: initialSize = ( ^ super new initialize: initialSize ) with: elem = ( From c415c9dcf1a2db92613b43e48a33e8337efeec71 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 20:40:35 +0000 Subject: [PATCH 4/8] [JS] Ignore the generated code for style checking Signed-off-by: Stefan Marr --- benchmarks/JavaScript/.eslintrc.json | 52 ++++++++++++++-------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/benchmarks/JavaScript/.eslintrc.json b/benchmarks/JavaScript/.eslintrc.json index 3ba448d9..9c86424d 100644 --- a/benchmarks/JavaScript/.eslintrc.json +++ b/benchmarks/JavaScript/.eslintrc.json @@ -1,28 +1,28 @@ { - "env": { - "browser": true, - "commonjs": true, - "es2021": true - }, - "extends": "airbnb-base", - "overrides": [ - ], - "parserOptions": { - "ecmaVersion": "latest" - }, - "rules": { - "max-classes-per-file": "off", - "class-methods-use-this": "off", - "no-restricted-syntax": ["error", "WithStatement"], - "comma-dangle": "off", - "no-param-reassign": "off", - "no-nested-ternary": "off", - "yoda": "off", - "no-bitwise": "off", - "no-underscore-dangle": "off", - "no-new": "off", - "import/no-dynamic-require": "off", - "global-require": "off", - "no-cond-assign": "off" - } + "env": { + "browser": true, + "commonjs": true, + "es2021": true + }, + "extends": "airbnb-base", + "overrides": [], + "parserOptions": { + "ecmaVersion": "latest" + }, + "rules": { + "max-classes-per-file": "off", + "class-methods-use-this": "off", + "no-restricted-syntax": ["error", "WithStatement"], + "comma-dangle": "off", + "no-param-reassign": "off", + "no-nested-ternary": "off", + "yoda": "off", + "no-bitwise": "off", + "no-underscore-dangle": "off", + "no-new": "off", + "import/no-dynamic-require": "off", + "global-require": "off", + "no-cond-assign": "off" + }, + "ignorePatterns": ["node_modules/", "dist/"] } From a38ff1857e1624ed6c38af7fc7b953a0b97e9c8e Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 21:40:35 +0000 Subject: [PATCH 5/8] [Lua] Replace local max function with math max Signed-off-by: Stefan Marr --- benchmarks/Lua/havlak.lua | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/benchmarks/Lua/havlak.lua b/benchmarks/Lua/havlak.lua index ecc1268c..906fd60b 100644 --- a/benchmarks/Lua/havlak.lua +++ b/benchmarks/Lua/havlak.lua @@ -196,15 +196,11 @@ function LoopStructureGraph:calculate_nesting_level () self:calculate_nesting_level_rec(self.root, 0) end -local function max (a, b) - return (a < b) and b or a -end - function LoopStructureGraph:calculate_nesting_level_rec (loop, depth) loop.depth_level = depth loop.children:each(function (it) self:calculate_nesting_level_rec(it, depth + 1) - loop:set_nesting_level(max(loop.nesting_level, 1 + it.nesting_level)) + loop:set_nesting_level(math.max(loop.nesting_level, 1 + it.nesting_level)) end) end From 78f407d42081a9c593a440a412ba971176eb58f1 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Tue, 6 Feb 2024 22:32:39 +0000 Subject: [PATCH 6/8] [ReBench] Set min_iteration_time to 0 Signed-off-by: Stefan Marr --- test.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test.conf b/test.conf index 9124423e..ab154308 100644 --- a/test.conf +++ b/test.conf @@ -6,7 +6,7 @@ default_data_file: 'benchmark.data' runs: iterations: 1 invocations: 1 - min_iteration_time: 1 + min_iteration_time: 0 # definition of benchmark suites benchmark_suites: From 4e2262f9c9089a20dabe193035983a3503ca3b45 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sat, 10 Feb 2024 23:28:05 +0000 Subject: [PATCH 7/8] [Fix] Ordering of comparison to be the same everywhere Signed-off-by: Stefan Marr --- benchmarks/Java/src/som/Vector.java | 2 +- benchmarks/JavaScript/som.js | 2 +- benchmarks/Python/som/vector.py | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/benchmarks/Java/src/som/Vector.java b/benchmarks/Java/src/som/Vector.java index aad09b71..60a85e4d 100644 --- a/benchmarks/Java/src/som/Vector.java +++ b/benchmarks/Java/src/som/Vector.java @@ -42,7 +42,7 @@ public static Vector with(final E elem) { } public Vector(final int size) { - storage = new Object[size]; + storage = size == 0 ? null : new Object[size]; } public Vector() { } diff --git a/benchmarks/JavaScript/som.js b/benchmarks/JavaScript/som.js index a605e84a..68d9d4b1 100644 --- a/benchmarks/JavaScript/som.js +++ b/benchmarks/JavaScript/som.js @@ -26,7 +26,7 @@ const INITIAL_CAPACITY = 16; class Vector { constructor(size) { - this.storage = size === undefined ? null : new Array(size); + this.storage = size === undefined || size === 0 ? null : new Array(size); this.firstIdx = 0; this.lastIdx = 0; } diff --git a/benchmarks/Python/som/vector.py b/benchmarks/Python/som/vector.py index a5ee8584..5c10fdb8 100644 --- a/benchmarks/Python/som/vector.py +++ b/benchmarks/Python/som/vector.py @@ -33,7 +33,7 @@ def vector_with(elem): # that. Don't see a point in doing it twice. class Vector: def __init__(self, size=0): - self._storage = [None] * size if size > 0 else None + self._storage = None if size == 0 else [None] * size self._first_idx = 0 self._last_idx = 0 From 9681d0e7b72650e6a45fcbb1e29f333fccb1ba32 Mon Sep 17 00:00:00 2001 From: Stefan Marr Date: Sat, 10 Feb 2024 23:28:31 +0000 Subject: [PATCH 8/8] =?UTF-8?q?One-based=20indexing=20doesn=E2=80=99t=20ne?= =?UTF-8?q?ed=20+=201=20for=20the=20size?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Marr --- benchmarks/Lua/som.lua | 2 +- benchmarks/SOM/Core/Vector.som | 40 ++++++++++++++-------------- benchmarks/SOMns/Core.ns | 2 +- benchmarks/Smalltalk/Core/Vector.som | 40 ++++++++++++++-------------- 4 files changed, 42 insertions(+), 42 deletions(-) diff --git a/benchmarks/Lua/som.lua b/benchmarks/Lua/som.lua index 7f91f2ad..90bfbc1e 100644 --- a/benchmarks/Lua/som.lua +++ b/benchmarks/Lua/som.lua @@ -91,7 +91,7 @@ end function Vector:at_put (idx, val) if self.storage == nil then - self.storage = alloc_array(max(idx + 1, INITIAL_SIZE)) + self.storage = alloc_array(max(idx, INITIAL_SIZE)) elseif idx > self.storage.n then local new_n = self.storage.n while idx > new_n do diff --git a/benchmarks/SOM/Core/Vector.som b/benchmarks/SOM/Core/Vector.som index 89c6e244..baadfe31 100644 --- a/benchmarks/SOM/Core/Vector.som +++ b/benchmarks/SOM/Core/Vector.som @@ -23,7 +23,7 @@ THE SOFTWARE. Vector = ( | first last storage | - + initialize: size = ( first := 1. last := 1. @@ -36,10 +36,10 @@ Vector = ( (storage == nil or: [ index > storage length ]) ifTrue: [ ^ nil ]. ^ storage at: index ) - + at: index put: val = ( storage == nil ifTrue: [ - storage := Array new: (index + 1 max: 10) + storage := Array new: (index max: 10) ] ifFalse: [ index > storage length ifTrue: [ | newLength newStorage | @@ -54,7 +54,7 @@ Vector = ( last < (index + 1) ifTrue: [ last := index + 1 ] ) - + append: element = ( storage == nil ifTrue: [ storage := Array new: 10 @@ -65,25 +65,25 @@ Vector = ( newStorage := Array new: (2 * storage length). storage doIndexes: [ :i | newStorage at: i put: (storage at: i) ]. storage := newStorage ] ]. - + storage at: last put: element. last := last + 1. ^ self ) - + isEmpty = ( ^ last = first ) - + forEach: block = ( first to: last - 1 do: [ :i | block value: (storage at: i) ] ) - + hasSome: block = ( first to: last - 1 do: [ :i | (block value: (storage at: i)) ifTrue: [ ^ true ] ]. ^ false ) - + getOne: block = ( first to: last - 1 do: [ :i | | e | @@ -92,7 +92,7 @@ Vector = ( ifTrue: [ ^ e ] ]. ^ nil ) - + removeFirst = ( self isEmpty ifTrue: [ ^ nil ]. first := first + 1. @@ -115,7 +115,7 @@ Vector = ( newArray := Array new: self capacity. newLast := 1. found := false. - + self forEach: [ :it | it == object ifTrue: [ found := true ] @@ -128,10 +128,10 @@ Vector = ( first := 1. ^ found ) - + size = ( ^ last - first ) capacity = ( storage == nil ifTrue: [ ^ 0 ] ifFalse: [ ^ storage length ] ) - + sort: aBlock = ( " Make the argument, aBlock, be the criterion for ordering elements of the receiver. @@ -141,19 +141,19 @@ Vector = ( to: last - 1 with: aBlock ] ) - + sort: i to: j with: sortBlock = ( " Sort elements i through j of self to be non-descending according to sortBlock. " | di dij dj tt ij k l n | sortBlock isNil ifTrue: [ ^ self defaultSort: i to: j ]. - + "The prefix d means the data at that index." (n := j + 1 - i) <= 1 ifTrue: [ ^ self ]. "Nothing to sort." " Sort di,dj. " di := storage at: i. dj := storage at: j. - + "i.e., should di precede dj?" (sortBlock value: di with: dj) ifFalse: [ storage swap: i with: j. @@ -173,7 +173,7 @@ Vector = ( ifFalse: [ " i.e. di should come after dij " storage swap: i with: ij. dij := di]. - + n > 3 ifTrue: [ " More than three elements. Find k>i and l storage size ifTrue: [ | newLength newStorage | diff --git a/benchmarks/Smalltalk/Core/Vector.som b/benchmarks/Smalltalk/Core/Vector.som index a5bffdd6..bfba3bc9 100644 --- a/benchmarks/Smalltalk/Core/Vector.som +++ b/benchmarks/Smalltalk/Core/Vector.som @@ -23,7 +23,7 @@ THE SOFTWARE. Vector = ( | first last storage | - + initialize: size = ( first := 1. last := 1. @@ -36,10 +36,10 @@ Vector = ( (storage == nil or: [ index > storage size ]) ifTrue: [ ^ nil ]. ^ storage at: index ) - + at: index put: val = ( storage == nil ifTrue: [ - storage := Array new: (index + 1 max: 10) + storage := Array new: (index max: 10) ] ifFalse: [ index > storage size ifTrue: [ | newLength newStorage | @@ -54,7 +54,7 @@ Vector = ( last < (index + 1) ifTrue: [ last := index + 1 ] ) - + append: element = ( storage == nil ifTrue: [ storage := Array new: 10 @@ -65,25 +65,25 @@ Vector = ( newStorage := Array new: (2 * storage size). 1 to: storage size do: [:i | newStorage at: i put: (storage at: i) ]. storage := newStorage ] ]. - + storage at: last put: element. last := last + 1. ^ self ) - + isEmpty = ( ^ last = first ) - + forEach: block = ( first to: last - 1 do: [ :i | block value: (storage at: i) ] ) - + hasSome: block = ( first to: last - 1 do: [ :i | (block value: (storage at: i)) ifTrue: [ ^ true ] ]. ^ false ) - + getOne: block = ( first to: last - 1 do: [ :i | | e | @@ -92,7 +92,7 @@ Vector = ( ifTrue: [ ^ e ] ]. ^ nil ) - + removeFirst = ( self isEmpty ifTrue: [ ^ nil ]. first := first + 1. @@ -115,7 +115,7 @@ Vector = ( newArray := Array new: self capacity. newLast := 1. found := false. - + self forEach: [ :it | it == object ifTrue: [ found := true ] @@ -128,10 +128,10 @@ Vector = ( first := 1. ^ found ) - + size = ( ^ last - first ) capacity = ( storage == nil ifTrue: [ ^ 0 ] ifFalse: [ ^ storage size ] ) - + sort: aBlock = ( " Make the argument, aBlock, be the criterion for ordering elements of the receiver. @@ -141,19 +141,19 @@ Vector = ( to: last - 1 with: aBlock ] ) - + sort: i to: j with: sortBlock = ( " Sort elements i through j of self to be non-descending according to sortBlock. " | di dij dj tt ij k l n | sortBlock isNil ifTrue: [ ^ self defaultSort: i to: j ]. - + "The prefix d means the data at that index." (n := j + 1 - i) <= 1 ifTrue: [ ^ self ]. "Nothing to sort." " Sort di,dj. " di := storage at: i. dj := storage at: j. - + "i.e., should di precede dj?" (sortBlock value: di with: dj) ifFalse: [ storage swap: i with: j. @@ -173,7 +173,7 @@ Vector = ( ifFalse: [ " i.e. di should come after dij " storage swap: i with: ij. dij := di]. - + n > 3 ifTrue: [ " More than three elements. Find k>i and l