Why creating an object in Java using Singleton is so slow? - java

Recently I made a class Singleton, where was a method returning the object myInstance of class Singleton. It was something like:
private final static Singleton myInstance = new Singleton();
After that I coded entire constructor, which was private, lets say:
private Singleton(){
doStuff()
}
However the performance was terrible. Maybe someone can give me a hint why doStuff() is much slower then when I don't use Singleton? I guess it has something to do with calling the constructor while declaring variables, but can someone share some info about that?
I have no idea why is that, I tried to search for explanation, but I couldn't find it.
Edit: the dostuff function includes stuff like opening files/reading them/using regexp on them, using levenstein function[which by profiler was the slowest part of the code].
When running that levenstein from constructor while using singleton the speed of levenstein function took around 10 seconds. After the object was created the call on this function inside this singleton object took only 0.5 seconds. Now, when not using singleton, calling the levenstein function from the constructor is also 0.5 seconds, prior to 10 seconds when it was done by the singleton. The code for the function is as follows:
["odleglosci" is just a simple map]
private static int getLevenshteinDistance(String s, String t) {
int n = s.length(); // length of s
int m = t.length(); // length of t
int p[] = new int[n + 1]; //'previous' cost array, horizontally
int d[] = new int[n + 1]; // cost array, horizontally
int _d[]; //placeholder to assist in swapping p and d
// indexes into strings s and t
int i; // iterates through s
int j; // iterates through t
char t_j; // jth character of t
int cost; // cost
for (i = 0; i <= n; i++) {
p[i] = i * 2;
}
int add = 2;//how much to add per increase
char[] c = new char[2];
String st;
for (j = 1; j <= m; j++) {
t_j = t.charAt(j - 1);
d[0] = j;
for (i = 1; i <= n; i++) {
cost = s.charAt(i - 1) == t_j ? 0 : Math.min(i, j) > 1 ? (s.charAt(i - 1) == t.charAt(j - 2) ? (s.charAt(i - 2) == t.charAt(j - 1) ? 0 : 1) : 1) : 1;//poprawa w celu zmniejszenia wartosci czeskiego bledu
if (cost == 1) {
c[0] = s.charAt(i - 1);
c[1] = t_j;
st = new String(c);
if (!odleglosci.containsKey(st)) {
//print((int) c[0]);
//print((int) c[1]);
} else if (odleglosci.get(st) > 1) {
cost = 2;
}
} else {
c[0] = s.charAt(i - 1);
c[1] = t_j;
st = new String(c);
if (!odleglosci.containsKey(st)) {
// print((int) c[0]);
// print((int) c[1]);
} else if (odleglosci.get(st) > 1) {
cost = -1;
}
}
d[i] = Math.min(Math.min(d[i - 1] + 2, p[i] + 2), p[i - 1] + cost);
}
_d = p;
p = d;
d = _d;
}
return p[n];
}
I didn't thought that the code in here could have any relevance to the question I asked, that's why I did not include it before, sorry.

The reason it is slow is because doStuff() is slow.

Related

Writing an iterative algorithm recursive, but I don´t see what Im doing wrong

I´m trying to write an iterative algorithm recursive, but my code isn´t working. This is my iterative algorithm:
public long calculate(long n) {
int var = 0;
for (int i = 0; i < n; i++) {
var += ((var - 1) + (var - 3));
}
return var;
And this is what I have tried for the recursive one:
public long calculate(long n) {
if (n <= 2) {
return 0;
}
else {
return n + calculate((n - 1) + (n - 3));
}
I just started learning recursive algorithms and I can´t see why this doesn´t work. Any suggestions? Thank you!
Iterative: n and var are to different values
Recursive: there is only n, so not the same formula as before - simplest solution, use two parameters instead of just one
Note: not a good example of a problem to solve by recursion, neither the best way to develop (transform an iterative algorithm to recursive). Recursive solutions are best suited for recursive problems... INHO
The calculation in the iterative method may be rewritten as:
public static long calculateIterative(long n) {
int var = 0;
for (int i = 0; i < n; i++) {
var += 2 * (var - 2); //((var - 1) + (var - 3));
}
return var;
}
Here we can see that for n = 0 it returns 0, for n = 1, var = -4, for n = 2: -4 + 2 * (-4 - 2) = -16, etc.
Thus, the recursive function has to "imitate" compound assignment and can be transformed:
var += 2 * (var - 2); -> var = var + 2 * (var - 2); -> var = 3 * var - 4;
so finally it may look like this:
public static long calculate(long n) {
if (n <= 0) {
return 0;
}
return 3 * calculate(n - 1) - 4;
}
tests:
for (int n = 0; n < 10; n++) {
System.out.printf("iterative(%d)=%-6d recursive(%d)=%-6d%n",
n, calculateIterative(n), n, calculate(n)
);
}
Output:
iterative(0)=0 recursive(0)=0
iterative(1)=-4 recursive(1)=-4
iterative(2)=-16 recursive(2)=-16
iterative(3)=-52 recursive(3)=-52
iterative(4)=-160 recursive(4)=-160
iterative(5)=-484 recursive(5)=-484
iterative(6)=-1456 recursive(6)=-1456
iterative(7)=-4372 recursive(7)=-4372
iterative(8)=-13120 recursive(8)=-13120
iterative(9)=-39364 recursive(9)=-39364

Google Foobar Challenge Level 2 "Hey-I-Already-Did-That" [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 2 years ago.
Improve this question
I need help with solving the second level of Google's Foobar challenge.
Commander Lambda uses an automated algorithm to assign minions randomly to tasks, in order to keep her minions on their toes. But you've noticed a flaw in the algorithm - it eventually loops back on itself, so that instead of assigning new minions as it iterates, it gets stuck in a cycle of values so that the same minions end up doing the same tasks over and over again. You think proving this to Commander Lambda will help you make a case for your next promotion.
You have worked out that the algorithm has the following process:
1) Start with a random minion ID n, which is a nonnegative integer of length k in base b
2) Define x and y as integers of length k. x has the digits of n in descending order, and y has the digits of n in ascending order
3) Define z = x - y. Add leading zeros to z to maintain length k if necessary
4) Assign n = z to get the next minion ID, and go back to step 2
For example, given minion ID n = 1211, k = 4, b = 10, then x = 2111, y = 1112 and z = 2111 - 1112 = 0999. Then the next minion ID will be n = 0999 and the algorithm iterates again: x = 9990, y = 0999 and z = 9990 - 0999 = 8991, and so on.
Depending on the values of n, k (derived from n), and b, at some point the algorithm reaches a cycle, such as by reaching a constant value. For example, starting with n = 210022, k = 6, b = 3, the algorithm will reach the cycle of values [210111, 122221, 102212] and it will stay in this cycle no matter how many times it continues iterating. Starting with n = 1211, the routine will reach the integer 6174, and since 7641 - 1467 is 6174, it will stay as that value no matter how many times it iterates.
Given a minion ID as a string n representing a nonnegative integer of length k in base b, where 2 <= k <= 9 and 2 <= b <= 10, write a function solution(n, b) which returns the length of the ending cycle of the algorithm above starting with n. For instance, in the example above, solution(210022, 3) would return 3, since iterating on 102212 would return to 210111 when done in base 3. If the algorithm reaches a constant, such as 0, then the length is 1.
Test Cases: Solution.solution("1211", 10) returns 1
Solution.solution("210022", 3) returns 3
Here is my code:
import java.util.ArrayList;
import java.util.Arrays;
public class Solution {
public static int solution(String n, int b) {
int k = n.length();
String m = n;
ArrayList<String> minionID = new ArrayList<>();
while (!minionID.contains(m)) {
minionID.add(m);
char[] s = m.toCharArray();
Arrays.sort(s);
int y = Integer.parseInt(toString(s));
int x = Integer.parseInt(reverseString(s));
if (b == 10) {
int intM = x - y;
m = Integer.toString(intM);
} else {
int intM10 = ((int) Integer.parseInt(toBase10(x,b))) - ((int) Integer.parseInt(toBase10(y, b)));
m = toBaseN(intM10, b);
}
m = addLeadingZeros(k, m);
}
System.out.println(minionID);
return minionID.size() - minionID.indexOf(m);
}
private static String toBaseN (int intBase10, int b) {
int residual = intBase10;
ArrayList<String> digitsBaseN = new ArrayList<>();
while (residual >= b) {
int r = residual % b;
digitsBaseN.add(Integer.toString(residual));
residual = (residual - r) / b;
}
digitsBaseN.add(Integer.toString(residual));
StringBuilder reverseDigits = new StringBuilder();
for (int i = digitsBaseN.size() -1; i >= 0; i--) {
reverseDigits.append(digitsBaseN.get(i));
}
return reverseDigits.toString();
}
private static String toBase10 (int intBaseN, int b) {
int[] xArr = new int[Integer.toString(intBaseN).length()];
int count = 0;
for (int i = xArr.length - 1; i >= 0; i--) {
xArr[count] = Integer.toString(intBaseN).charAt(i) - '0';
count++;
}
int yBase10 = 0;
for(int i = 0; i < xArr.length; i++) {
yBase10 += xArr[i] * (Math.pow(b, i));
}
return Integer.toString(yBase10);
}
public static String toString(char[] arr) {
StringBuilder newString = new StringBuilder();
for (char c : arr) {
newString.append(c);
}
if (newString.toString().contains("-")) {
newString.deleteCharAt(0);
}
return newString.toString();
}
public static String reverseString(char[] arr) {
StringBuilder newString = new StringBuilder();
for (int i = arr.length - 1; i >= 0; i--) {
newString.append(arr[i]);
}
if (newString.toString().contains("-")) {
newString.deleteCharAt(newString.length()-1);
}
return newString.toString();
}
public static String addLeadingZeros(int k, String z) {
if (k > z.length()) {
String zeros = "";
for (int i = 0; i < (k - z.length()); i++) {
zeros += "0";
}
zeros += z;
return zeros;
}
return z;
}
It only works for three out of the ten test cases
def answer(n, b):
k = len(n)
m = n
mini_id = []
while m not in mini_id:
mini_id.append(m)
s = sorted(m)
x_descend = ''.join(s[::-1])
y_ascend = ''.join(s)
if b == 10:
int_m = int(x_descend) - int(y_ascend)
m = str(int_m)
else:
int_m_10 = int(to_base_10(x_descend, b)) - int(to_base_10(y_ascend, b))
m = to_base_n(str(int_m_10), b)
m = (k - len(m)) * '0' + m
return len(mini_id) - mini_id.index(m)

Optimisation of string & conversion operations

I had a go at writing this bit of java code which allows me to add and subtract (large) numbers which are represented using a String rather than a numeric datatype. This allows me to do basic calculations on numbers much bigger than the numeric data types can handle.
It is a bit rough and ready, I don't perform any checks on the input strings at all for instance, but for the constraints that I am using the code works fine.
I am not that familiar with java library functions (is there something instead of Character#getNumericValue that works better?) and I was wondering if there is any scope for improving the execution speed. I guess when the input numbers differ considerably in length, using the '0's to keep the loop running isn't very efficient. Perhaps I am not using a very good algorithm to do this at all. Any pointers would be welcome.
public static String addBig(String a, String b)
{
// no checks or exception handling at all ...
String result = "";
int carry = 0;
int a_int, b_int, res_int;
for(int current = 1; ; current++)
{
if(current > a.length() && current > b.length())
{
if(carry == 1)
result = "1" + result;
break;
}
a_int = a.length() - current < 0 ? 0
: Character.getNumericValue(a.charAt(a.length() - current));
b_int = b.length() - current < 0 ? 0
: Character.getNumericValue(b.charAt(b.length() - current));
res_int = a_int + b_int + carry;
if(res_int > 9)
{
res_int -= 10;
carry = 1;
}
else
carry = 0;
result = Integer.toString(res_int) + result;
}
return result;
}
public static String subtractBig(String a, String b)
{
// no checks or exception handling at all, a is expected to be bigger than b
String result = "";
int borrow = 0;
int a_int, b_int, res_int;
for(int current = 1; current <= a.length(); current++)
{
// subtract the digits
a_int = Character.getNumericValue(a.charAt(a.length() - current));
b_int = b.length() - current < 0 ? 0
: Character.getNumericValue(b.charAt(b.length()-current));
res_int = (a_int-borrow)-b_int;
if(res_int < 0)
{
res_int += 10;
borrow = 1;
}
else
borrow = 0;
result = Integer.toString(res_int) + result;
}
// tidy zeros
while(result.length() > 1 && result.charAt(0) == '0')
result = result.substring(1);
return result;
}

Diagnosing a performance issue

I'm not very experienced with Rust and I'm trying to diagnose a performance problem. Below there is a pretty fast Java code (runs in 7 seconds) and what I think should the the equivalent Rust code. However, the Rust code runs very slowly (yes, I compiled it with --release as well), and it also appears to overflow. Changing i32 to i64 just pushes the overflow later, but it still happens. I suspect there is some bug in what I wrote, but after staring at the problem for a long time, I decided to ask for help.
public class Blah {
static final int N = 100;
static final int K = 50;
public static void main(String[] args) {
//initialize S
int[] S = new int[N];
for (int n = 1; n <= N; n++) S[n-1] = n*n;
// compute maxsum and minsum
int maxsum = 0;
int minsum = 0;
for (int n = 0; n < K; n++) {
minsum += S[n];
maxsum += S[N-n-1];
}
// initialize x and y
int[][] x = new int[K+1][maxsum+1];
int[][] y = new int[K+1][maxsum+1];
y[0][0] = 1;
// bottom-up DP over n
for (int n = 1; n <= N; n++) {
x[0][0] = 1;
for (int k = 1; k <= K; k++) {
int e = S[n-1];
for (int s = 0; s < e; s++) x[k][s] = y[k][s];
for (int s = 0; s <= maxsum-e; s++) {
x[k][s+e] = y[k-1][s] + y[k][s+e];
}
}
int[][] t = x;
x = y;
y = t;
}
// sum of unique K-subset sums
int sum = 0;
for (int s = minsum; s <= maxsum; s++) {
if (y[K][s] == 1) sum += s;
}
System.out.println(sum);
}
}
extern crate ndarray;
use ndarray::prelude::*;
use std::mem;
fn main() {
let numbers: Vec<i32> = (1..101).map(|x| x * x).collect();
let deg: usize = 50;
let mut min_sum: usize = 0;
for i in 0..deg {
min_sum += numbers[i] as usize;
}
let mut max_sum: usize = 0;
for i in deg..numbers.len() {
max_sum += numbers[i] as usize;
}
// Make an array
let mut x = OwnedArray::from_elem((deg + 1, max_sum + 1), 0i32);
let mut y = OwnedArray::from_elem((deg + 1, max_sum + 1), 0i32);
y[(0, 0)] = 1;
for n in 1..numbers.len() + 1 {
x[(0, 0)] = 1;
println!("Completed step {} out of {}", n, numbers.len());
for k in 1..deg + 1 {
let e = numbers[n - 1] as usize;
for s in 0..e {
x[(k, s)] = y[(k, s)];
}
for s in 0..max_sum - e + 1 {
x[(k, s + e)] = y[(k - 1, s)] + y[(k, s + e)];
}
}
mem::swap(&mut x, &mut y);
}
let mut ans = 0;
for s in min_sum..max_sum + 1 {
if y[(deg, s)] == 1 {
ans += s;
}
}
println!("{}", ans);
}
To diagnose a performance issue in general, I:
Get a baseline time or rate. Preferably create a testcase that only takes a few seconds, as profilers tend to slow down the system a bit. You will also want to iterate frequently.
Compile in release mode with debugging symbols.
Run the code in a profiler. I'm on OS X so my main choice is Instruments, but I also use valgrind.
Find the hottest code path, think about why it's slow, try something, measure.
The last step is the hard part.
In your case, you have a separate implementation that you can use as your baseline. Comparing the two implementations, we can see that your data structures differ. In Java, you are building nested arrays, but in Rust you are using the ndarray crate. I know that crate has a good maintainer, but I personally don't know anything about the internals of it, or what use cases it best fits.
So I rewrote it with using the standard-library Vec.
The other thing I know is that direct array access isn't as fast as using an iterator. This is because array access needs to perform a bounds check, while iterators bake the bounds check into themselves. Many times this means using methods on Iterator.
The other change is to perform bulk data transfer when you can. Instead of copying element-by-element, move whole slices around, using methods like copy_from_slice.
With those changes the code looks like this (apologies for poor variable names, I'm sure you can come up with semantic names for them):
use std::mem;
const N: usize = 100;
const DEGREE: usize = 50;
fn main() {
let numbers: Vec<_> = (1..N+1).map(|v| v*v).collect();
let min_sum = numbers[..DEGREE].iter().fold(0, |a, &v| a + v as usize);
let max_sum = numbers[DEGREE..].iter().fold(0, |a, &v| a + v as usize);
// different data types for x and y!
let mut x = vec![vec![0; max_sum+1]; DEGREE+1];
let mut y = vec![vec![0; max_sum+1]; DEGREE+1];
y[0][0] = 1;
for &e in &numbers {
let e2 = max_sum - e + 1;
let e3 = e + e2;
x[0][0] = 1;
for k in 0..DEGREE {
let current_x = &mut x[k+1];
let prev_y = &y[k];
let current_y = &y[k+1];
// bulk copy
current_x[0..e].copy_from_slice(&current_y[0..e]);
// more bulk copy
current_x[e..e3].copy_from_slice(&prev_y[0..e2]);
// avoid array index
for (x, y) in current_x[e..e3].iter_mut().zip(&current_y[e..e3]) {
*x += *y;
}
}
mem::swap(&mut x, &mut y);
}
let sum = y[DEGREE][min_sum..max_sum+1].iter().enumerate().filter(|&(_, &v)| v == 1).fold(0, |a, (i, _)| a + i + min_sum);
println!("{}", sum);
println!("{}", sum == 115039000);
}
2.060s - Rust 1.9.0
2.225s - Java 1.7.0_45-b18
On OS X 10.11.5 with a 2.3 GHz Intel Core i7.
I'm not experienced enough with Java to know what kinds of optimizations it can do automatically.
The biggest potential next step I see is to leverage SIMD instructions when performing the addition; it's pretty much exactly what SIMD is made for.
As pointed out by Eli Friedman, avoiding array indexing by zipping isn't currently the most performant way of doing this.
With the changes below, the time is now 1.267s.
let xx = &mut current_x[e..e3];
xx.copy_from_slice(&prev_y[0..e2]);
let yy = &current_y[e..e3];
for i in 0..(e3-e) {
xx[i] += yy[i];
}
This generates assembly that appears to unroll the loop as well as using SIMD instructions:
+0x9b0 movdqu -48(%rsi), %xmm0
+0x9b5 movdqu -48(%rcx), %xmm1
+0x9ba paddd %xmm0, %xmm1
+0x9be movdqu %xmm1, -48(%rsi)
+0x9c3 movdqu -32(%rsi), %xmm0
+0x9c8 movdqu -32(%rcx), %xmm1
+0x9cd paddd %xmm0, %xmm1
+0x9d1 movdqu %xmm1, -32(%rsi)
+0x9d6 movdqu -16(%rsi), %xmm0
+0x9db movdqu -16(%rcx), %xmm1
+0x9e0 paddd %xmm0, %xmm1
+0x9e4 movdqu %xmm1, -16(%rsi)
+0x9e9 movdqu (%rsi), %xmm0
+0x9ed movdqu (%rcx), %xmm1
+0x9f1 paddd %xmm0, %xmm1
+0x9f5 movdqu %xmm1, (%rsi)
+0x9f9 addq $64, %rcx
+0x9fd addq $64, %rsi
+0xa01 addq $-16, %rdx
+0xa05 jne "slow::main+0x9b0"

Is the complexity of this code O(n^2) or O(n^2 * n^(1/2))?

I was thinking the complexity would be O(n^2). Am I wrong? If so, could you please explain why?
public int countXs(char[][] m)
{
int rows = m.length, cols = m[0].length;
int r = 0, c = 0, count = 0;
while (r < rows || c < cols)
{
count += r;
while (r < rows && m[r][c] == 'x')
{
count++;
r++;
}
c++;
}
return count;
}
Firstly, your code may crash because of arrayIndexOutofBound with c index.
Next, when you invest the time complexity, firstly, you need to define what is n. Normally n indicates the size of input, in this case n is the size of 2-dimensional array.
So, you need setup the formula to time complexity and specify the worst case of your code to find time complexity. Suppose that array m is pxq (p + q = n) and we denote O(1) = 1.
T(n) = Sum(i->max(p, q)) {1 + sum(j->p)(1)}
= max(p,q) + sum(i->max(p,q)){p}
= max(p, n-p) + sum(i-> max(p, n-p)) {p}
= max(p, n-p) + p(n-p)
Based on Cauchy inequality:
4*ab <= (a+b)^2 we have: p(n - p) < (p + n - p)^2 /4 = n^2/4
So:
T(n) <= n + n^2/4 = O(n^2) . Q.E.D
Read more: http://en.wikipedia.org/wiki/Time_complexity

Categories

Resources