Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Lazily initialize backing store of Vector #90

Merged
merged 8 commits into from
Feb 10, 2024
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
69 changes: 41 additions & 28 deletions benchmarks/Crystal/som.cr
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
}
Expand All @@ -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
Expand All @@ -148,15 +158,18 @@ 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
@last_idx - @first_idx
end

def capacity
@storage.size
@storage == nil ? 0 : @storage.not_nil!.size
end

def sort(&block : T, T -> Bool)
Expand Down Expand Up @@ -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
Expand All @@ -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

Expand All @@ -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
Expand Down
26 changes: 17 additions & 9 deletions benchmarks/Java/src/som/Vector.java
Original file line number Diff line number Diff line change
Expand Up @@ -42,23 +42,23 @@ public static <E> Vector<E> with(final E elem) {
}

public Vector(final int size) {
storage = new Object[size];
storage = size == 0 ? null : 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;
Expand All @@ -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);
}
Expand Down Expand Up @@ -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};
Expand All @@ -152,15 +158,17 @@ 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() {
return lastIdx - firstIdx;
}

public int capacity() {
return storage.length;
return storage == null ? 0 : storage.length;
}

public void sort(final Comparator<E> c) {
Expand Down
52 changes: 26 additions & 26 deletions benchmarks/JavaScript/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -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/"]
}
10 changes: 8 additions & 2 deletions benchmarks/JavaScript/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
21 changes: 12 additions & 9 deletions benchmarks/JavaScript/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
Loading
Loading