Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
mister_gosh
May 24, 2002

Ok, after trying for 8+ hours, I thought I better try here. I have two .war files which reference a couple of external jars in a Tomcat application.

I keep getting java.lang.NoClassDefFoundError: com/neva/COMException

Which, I believe, means it is not finding com.neva.COMException and likely none of the other external jars.

So, tried a number of attempts to get my war to read it, each one more desperate than the next:

1. modified setclasspath.bat in tomcat to include my jars in the classpath
2. modified catalina.properties (same as above)
3. deleted tomcat work directory
4. numerous machine restarts
5. numerous tomcat service restarts (after each configuration change)
6. put external jars directly in java home and next to rt.jar
7. put the jars in numerous and countless locations in the tomcat area including webapps/ROOT/lib
8. modified war's manifest to specify a classpath (and was careful to add the required end of line)

Nothing seems to work, and I'm very frustrated and would be very grateful if anyone has any ideas. Thanks!

Adbot
ADBOT LOVES YOU

epswing
Nov 4, 2003

Soiled Meat

yatagan posted:

Here's a better way, remember which was last filled in by the user.

I think I like yatagan's idea more, but another option is to have one "convert" button below each textfield.

vvv Edit: even better

epswing fucked around with this message at 14:38 on May 28, 2010

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
korofrog: Perhaps you could remove the "convert" button entirely?

If you attach keylisteners to your textfields, you can update the other fields live:

code:
private final JTextArea ft = new JTextArea();
private final JTextArea in = new JTextArea();
private final JTextArea cm = new JTextArea();
private final JTextArea m = new JTextArea();

...

ft.addKeyListener(new KeyListener() {
	public void keyReleased(KeyEvent e) {
		try {
			double n = Double.parseDouble(ft.getText());
			in.setText("" + (12 * n));
			cm.setText("" + (30.48 * n));
			m.setText("" + (.3048 * n));
		}
		catch (NumberFormatException nfe) {
			in.setText("---");
			cm.setText("---");
			m.setText("---");
		}
	}
	public void keyTyped(KeyEvent e) {}
	public void keyPressed(KeyEvent e) {}
});
And so forth for the other fields. I don't think you can use the keyTyped() event, because we also want to update the fields when you delete a character. In my experience KeyListener events are not very consistent across platforms, so your mileage may vary.

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe

mister_gosh posted:

Ok, after trying for 8+ hours, I thought I better try here. I have two .war files which reference a couple of external jars in a Tomcat application.

I keep getting java.lang.NoClassDefFoundError: com/neva/COMException

Which, I believe, means it is not finding com.neva.COMException and likely none of the other external jars.

So, tried a number of attempts to get my war to read it, each one more desperate than the next:

1. modified setclasspath.bat in tomcat to include my jars in the classpath
2. modified catalina.properties (same as above)
3. deleted tomcat work directory
4. numerous machine restarts
5. numerous tomcat service restarts (after each configuration change)
6. put external jars directly in java home and next to rt.jar
7. put the jars in numerous and countless locations in the tomcat area including webapps/ROOT/lib
8. modified war's manifest to specify a classpath (and was careful to add the required end of line)

Nothing seems to work, and I'm very frustrated and would be very grateful if anyone has any ideas. Thanks!

Try putting the jars in the tomcat/lib folder.

Fly
Nov 3, 2002

moral compass

MEAT TREAT posted:

Try putting the jars in the tomcat/lib folder.
Is that not a heavy-handed way to give access to the jar for just one application? Won't that make the jar available to all applications, and is there a better way to make it available just to one application?

If it's a result of dependency injection, it might called from some initialization stuff though, which would be weird IMO, but a stack trace of the ClassNotFoundException might illuminate that.

epswing
Nov 4, 2003

Soiled Meat
mister_gosh said he's got two war files, so two web apps. Isn't MEAT TREAT's suggestion exactly what tomcat/lib is for (ie multiple webapps having access to the same set of jars)?

Fly
Nov 3, 2002

moral compass

epswing posted:

mister_gosh said he's got two war files, so two web apps. Isn't MEAT TREAT's suggestion exactly what tomcat/lib is for (ie multiple webapps having access to the same set of jars)?
You're right, that's true. I was thinking about the case where there may be other, unmentioned war files or applications on the same server. I think there are ways to make the jar available only two the two war files in question, but that may not be necessary in this case.

Janitor Prime
Jan 22, 2004

PC LOAD LETTER

What da fuck does that mean

Fun Shoe

epswing posted:

mister_gosh said he's got two war files, so two web apps. Isn't MEAT TREAT's suggestion exactly what tomcat/lib is for (ie multiple webapps having access to the same set of jars)?

Exactly, if it's a common library that you are going to share with multiple applications you should place it there. This only becomes a problem when you need two different versions of the same library. But really I've never had a problem with deploying my wars with a lib directory, I believe the application server will use those first which will override whatever is in the tomcat/lib folder.

epswing
Nov 4, 2003

Soiled Meat
Does tomcat override by filename or by what's inside the jar?

Parantumaton
Jan 29, 2009


The OnLy ThInG
i LoVe MoRe
ThAn ChUgGiNg SeMeN
iS gEtTiNg PaId To Be A
sOcIaL MeDiA sHiLl
FoR mIcRoSoFt
AnD nOkIa

epswing posted:

Does tomcat override by filename or by what's inside the jar?

Load order. There's the bootstrap classloader, tomcat classloader (I think it's an URLClassLoader?) and then each webapp gets an individual classloader.

epswing
Nov 4, 2003

Soiled Meat
I'm writing about 100,000 lines to an HttpServletResponse:

code:
List<String> lines = ... // 100,000 elements, about 60 chars each, so about 6mb
String newline = System.getProperty("line.separator");

response.setContentType("text/plain; charset=utf-8");
PrintWriter out = response.getWriter();

long start = System.currentTimeMillis();

for (String line : lines) {
  out.write(line);
  out.write(newline);
}

logger.info("time: " + (System.currentTimeMillis() - start) + " ms"); // 10455 ms

out.flush();
out.close();
This takes about 10 seconds, running both the server (tomcat) and client (firefox) locally. Would you expect it to take that long? I thought perhaps 100k calls to out.write was a bit much, so using StringBuilder I concatenated all the elements in the list and did one big out.write(buffer.toString()), and that also took about 10 seconds.

I'm going to start playing with maybe setting the content length in advance, or trying different content types, but would you expect a response of this size to take 10 seconds? I don't think I'm bandwidth-limited, because we're only talking about 6mb / 10s = 600k/s here, and I'd expect to be able to hit a faster speed than that when everything is local.

trex eaterofcadrs
Jun 17, 2005
My lack of understanding is only exceeded by my lack of concern.

epswing posted:

I'm writing about 100,000 lines to an HttpServletResponse:

code:
List<String> lines = ... // 100,000 elements, about 60 chars each, so about 6mb
String newline = System.getProperty("line.separator");

response.setContentType("text/plain; charset=utf-8");
PrintWriter out = response.getWriter();

long start = System.currentTimeMillis();

for (String line : lines) {
  out.write(line);
  out.write(newline);
}

logger.info("time: " + (System.currentTimeMillis() - start) + " ms"); // 10455 ms

out.flush();
out.close();
This takes about 10 seconds, running both the server (tomcat) and client (firefox) locally. Would you expect it to take that long? I thought perhaps 100k calls to out.write was a bit much, so using StringBuilder I concatenated all the elements in the list and did one big out.write(buffer.toString()), and that also took about 10 seconds.

I'm going to start playing with maybe setting the content length in advance, or trying different content types, but would you expect a response of this size to take 10 seconds? I don't think I'm bandwidth-limited, because we're only talking about 6mb / 10s = 600k/s here, and I'd expect to be able to hit a faster speed than that when everything is local.

The only way to be SURE is to get your profiler of choice out and have a look-see in the internals.

However, allocating 6MB all at once MIGHT cause the JVM to double down on the heap allocation, which is a pretty costly operation. You might want to start your app with a higher -Xms setting and see if that helps.

epswing
Nov 4, 2003

Soiled Meat
Hm, I'll try this VisualVM I've been hearing about. Also, slamming all that text into a StringBuilder probably cost me an additional 6mb.

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb
Maybe specifying the StringBuilder capacity could help out?

Outlaw Programmer
Jan 1, 2008
Will Code For Food
Instead of constructing all 60k strings at once, then writing them out, is there any way you can construct them on demand and write them as they are created?

code:

String line;
while( (line = buildLine()) != null) {
    out.write(line);
}
Where that buildLine() call keeps track of whatever it's supposed to work on next. The best approach might be to create batches of X lines at a time, where you have to fine tune the optimal number. If you want to get really fancy, you can have 1 thread produce these lines while your consumer is constantly writing them out to the response.

Also, I notice that you are using System.getProperty("line.separator"). Does that really make sense in this context? That will give you the line separator of the webserver, which is presumably always under your control. Maybe you should ask the client for its preference? Or always assume \n unless the client decides otherwise?

korofrog
Dec 15, 2006
smell my face!!!

Internet Janitor posted:

korofrog: Perhaps you could remove the "convert" button entirely?

If you attach keylisteners to your textfields, you can update the other fields live:

code:
private final JTextArea ft = new JTextArea();
private final JTextArea in = new JTextArea();
private final JTextArea cm = new JTextArea();
private final JTextArea m = new JTextArea();

...

ft.addKeyListener(new KeyListener() {
	public void keyReleased(KeyEvent e) {
		try {
			double n = Double.parseDouble(ft.getText());
			in.setText("" + (12 * n));
			cm.setText("" + (30.48 * n));
			m.setText("" + (.3048 * n));
		}
		catch (NumberFormatException nfe) {
			in.setText("---");
			cm.setText("---");
			m.setText("---");
		}
	}
	public void keyTyped(KeyEvent e) {}
	public void keyPressed(KeyEvent e) {}
});
And so forth for the other fields. I don't think you can use the keyTyped() event, because we also want to update the fields when you delete a character. In my experience KeyListener events are not very consistent across platforms, so your mileage may vary.

Thanks for the idea! I had not gotten up to the point of keylisteners yet, which is why I had the button because I was comfortable with the actionlistener. I'll give this method a shot. Now, it looks like with your method I can get rid of the planned if statements, correct?

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Yep, you shouldn't need any conditionals for this approach. (Not that there's anything wrong with a few simple if statements.) You don't have to use anonymous classes like I did there- since you're going to have four listeners that vary only by a few parameters (conversion factors, source and destination fields), it probably makes more sense to make your own private class that implements KeyListener and accepts a couple of arrays as arguments. If you run into trouble, show us what you've come up with.

mister_gosh
May 24, 2002

Thanks everyone for the input, I put it in the equivalent location, tomcat/shared/lib. Actually, it was there already from putting it there earlier.

One of my big problems was I must have just overwhelmed the java environment by trying too hard, putting it so many places until it would find it. Removing it everywhere, starting over and just putting it in the one location fixed it.

Configuration and environment issues are the worst.

IMlemon
Dec 29, 2008
I need to create a (very simplified) message passing interface for Java processes so that you can do all kinds of parralel magic. Yeah right. Anyways, I know how to use threads and using those would be much easier but sadly, I have to use processes. Now, I googled this up a little bit and found processBuilder and runtime.exec thingies, but both of those seem to execute OS native commands, which isn't what im looking for. I want the process to execute Java code, like threads do.

Am I missing something very obvious and there's a way I can easily stuff some Java code to a process and tell the sucker to execute it? Or should I just say, whatever, and use threads? I don't have much time for this assignment :smith:.

TagUrIt
Jan 24, 2007
Freaking Awesome

IMlemon posted:

I need to create a (very simplified) message passing interface for Java processes so that you can do all kinds of parralel magic. Yeah right. Anyways, I know how to use threads and using those would be much easier but sadly, I have to use processes. Now, I googled this up a little bit and found processBuilder and runtime.exec thingies, but both of those seem to execute OS native commands, which isn't what im looking for. I want the process to execute Java code, like threads do.

Am I missing something very obvious and there's a way I can easily stuff some Java code to a process and tell the sucker to execute it? Or should I just say, whatever, and use threads? I don't have much time for this assignment :smith:.

What's your end-goal? Based on your description, it sounds like you want to have your one program compose some code for a different task, and then (compile then) run it in a separate jvm. This sounds like a terrible terrible idea.

If that flow is precisely what the assignment wants, you probably need to write your generated code out to a file, run "javac" on it, and then execute the compiled version. (I know it is possible to compile in-memory, but I don't think it would be possible to run the compiled source in a different jvm.)

If your goal is something more general (hopefully not involving dynamic compilation), then RMI is probably the way to go.

korofrog
Dec 15, 2006
smell my face!!!
Ok, I'm working on a different part of my project and haven't gotten to the conversion panel yet and I'm running into a small problem.

code:
public boolean checkFields()
		{
			if ((poolLengthField.getText().compareTo("")<1)	||
				(poolWidthField.getText().compareTo("")<1)	||
				(poolDepthField.getText().compareTo("")<1))
			{
				if (poolLengthField.getText().compareTo("")<1)
				{
					poolLengthField.setBackground(Color.RED);
				}//end if statement
				
				if ((poolWidthField.getText().compareTo("")<1));
				{
					poolWidthField.setBackground(Color.RED);
				}//end if statement
				
				if ((poolDepthField.getText().compareTo("")<1))
				{
					poolDepthField.setBackground(Color.RED);
				}//end if statement
				
				poolStatus.setText("Please fill out all fields");
				return false;
			}//end if statement
			else
			{
				poolLengthField.setBackground(Color.WHITE);
				poolWidthField.setBackground(Color.white);
				poolDepthField.setBackground(Color.WHITE);
				poolStatus.setText("");
				return true;
			}//end else statement
Basically, I have a panel that has 3 text fields for input, length, width, and depth.

While I can get the thing to update a JLabel for the status and everything works mostly correctly, I'm having a problem with the setBackground.

Here's what's happening:

length field blank = length & width field background changes to red
width field blank = no change in any field background
depth field blank = change in depth field background only

Mind you I was coding this while half asleep and it looks like it should work fine and it's got to be something simple I'm missing but I just can't see it. Any help would be appreciated.

Edit: Ok, I redid that block of code and looks like the extra parentheses I had in the if statements may have been the culprit.

korofrog fucked around with this message at 18:59 on May 31, 2010

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
korofrog: is there a reason you're using compareTo("") rather than equals("")?

Max Facetime
Apr 18, 2009

I'll give a hint about the culprit. If you redo the code above to use this brace style
code:
if(condition) {
  doSomething();
}
you should see the problem quite quickly.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

I am in posted:

I'll give a hint about the culprit. If you redo the code above to use this brace style
code:
if(condition) {
  doSomething();
}
you should see the problem quite quickly.

Telling him to switch to an inferior brace style is a terrible way of pointing him to his problem.

Max Facetime
Apr 18, 2009

Flobbster posted:

Telling him to switch to an inferior brace style is a terrible way of pointing him to his problem.

Mmmmmm, just try it on for a couple of weeks, see if it fits. You can always go back real easily.

epswing
Nov 4, 2003

Soiled Meat
code:
import java.util.ArrayList;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		
		Test t = new Test();
		t.method(list);
	}
	
	public void method(Object o) {
		System.out.println("method one: " + o);
	}
	
	public void method(List<Object> o) {
		System.out.println("method two: " + o);
	}
}
code:
method one: [1, 2, 3]
Why does Java run the first overloaded method, rather than the second? I mean I know List<Integer> is an Object but :ohdear:

fletcher
Jun 27, 2003

ken park is my favorite movie

Cybernetic Crumb

korofrog posted:

Ok, I'm working on a different part of my project and haven't gotten to the conversion panel yet and I'm running into a small problem.

code:
public boolean checkFields()
		{
			if ((poolLengthField.getText().compareTo("")<1)	||
				(poolWidthField.getText().compareTo("")<1)	||
				(poolDepthField.getText().compareTo("")<1))
			{
				if (poolLengthField.getText().compareTo("")<1)
				{
					poolLengthField.setBackground(Color.RED);
				}//end if statement
				
				if ((poolWidthField.getText().compareTo("")<1));
				{
					poolWidthField.setBackground(Color.RED);
				}//end if statement
				
				if ((poolDepthField.getText().compareTo("")<1))
				{
					poolDepthField.setBackground(Color.RED);
				}//end if statement
				
				poolStatus.setText("Please fill out all fields");
				return false;
			}//end if statement
			else
			{
				poolLengthField.setBackground(Color.WHITE);
				poolWidthField.setBackground(Color.white);
				poolDepthField.setBackground(Color.WHITE);
				poolStatus.setText("");
				return true;
			}//end else statement

This is pretty hard to read. No need to have a comment for every closing curly brace. Pretty much any IDE will have brace matching for you, so you simply put the cursor next to any brace and it will highlight the other one. It also looks like you are trying to do some weird string comparisons when you are working with numbers. Something like this may be easier to read and debug:

code:
public boolean checkFields() {
    double length = Double.parseDouble(poolLengthField.getText());
    double width = Double.parseDouble(poolWidthField.getText());
    double height = Double.parseDouble(poolHeightField.getText());
    if ((length == 0) || (width == 0) || (height == 0)) {
        poolStatus.setText("Please fill out all fields");
        if (length == 0)
            poolLengthField.setBackground(Color.RED);
        if (width == 0)
            poolWidthField.setBackground(Color.RED);
        if (height == 0)
            poolHeightField.setBackground(Color.RED);
        return false;
    } else {
        poolLengthField.setBackground(Color.WHITE);
        poolWidthField.setBackground(Color.WHITE);
        poolHeightField.setBackground(Color.WHITE);
        poolStatus.setText("");
        return true;
    }
}

trex eaterofcadrs
Jun 17, 2005
My lack of understanding is only exceeded by my lack of concern.

epswing posted:

code:
import java.util.ArrayList;
import java.util.List;

public class Test {
	
	public static void main(String[] args) {
		
		List<Integer> list = new ArrayList<Integer>();
		list.add(1);
		list.add(2);
		list.add(3);
		
		Test t = new Test();
		t.method(list);
	}
	
	public void method(Object o) {
		System.out.println("method one: " + o);
	}
	
	public void method(List<Object> o) {
		System.out.println("method two: " + o);
	}
}
code:
method one: [1, 2, 3]
Why does Java run the first overloaded method, rather than the second? I mean I know List<Integer> is an Object but :ohdear:

The generics. If you put List<Integer> instead of List<Object> it works how you want. If you want to refer to a List of anything just use List and ignore the parametric warnings.

OddObserver
Apr 3, 2009
To elaborate a bit, conceptually, a list of integers is not a list of objects. Why?
Well, you can put, say, a String into a list of objects, but not into a
list of integers.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

TRex EaterofCars posted:

The generics. If you put List<Integer> instead of List<Object> it works how you want. If you want to refer to a List of anything just use List and ignore the parametric warnings.

:gonk:

This is what wildcards are for. If you want a method that takes a List of anything, do this:

code:
	public void method(List<?> o) {
		System.out.println("method two: " + o);
	}

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

epswing posted:

Why does Java run the first overloaded method, rather than the second? I mean I know List<Integer> is an Object but :ohdear:

Because generic types in Java are always invariant in their type parameters, and even if they weren't, mutable collections would naturally need to be.

Let me break that down a little.

You're thinking that List<Integer> should be a subtype of List<Object> because Integer is a subtype of Object. That's called covariance: A-subtype-B implies f(A)-subtype-f(B) (where f is some type function, like f(x) = List<x> or f(x) = x[][]). The opposite is called contravariance: A-subtype-B implies f(A)-supertype-f(B).

It turns out that Java's generics system does not let you express parametric covariance/contravariance directly: that is, you can't say that List<T> is covariant in T. The rule that Java implements is that List<T> is totally unrelated to List<U> unless T = U. This would be extremely limiting if Java didn't let you write polymorphic methods, which I'll get to in a second.

It also turns out that collections should be invariant in their type parameters. You have a method that takes a collection and pulls a bunch of objects out it; operations like that are naturally covariant, because you can safely pull an Object out of a list of Integers (but not vice-versa). But someone else might have a method that takes a collection and adds a bunch of stuff to it; that operation is naturally contravariant, because you can safely put an Integer into a list of Objects (but not vice-versa). So a collection type that allows you to both read and write its members has to be invariant.

The solution to your specific problem is that you don't really want to require callers to give you a List<Object>. You want callers to give you a List<T> for any T that's a subtype of Object (which is to say, any T). The way you write that is:
code:
<T extends Object> void foo(List<T> list) { ... }
which happens to be equivalent to any of the following:
code:
<T> void foo(List<T> list) { ... }
void foo(List<? extends Object> list) { ... }
void foo(List<?> list) { ... }

epswing
Nov 4, 2003

Soiled Meat

rjmccall posted:

:words:

Thanks for the lesson :worship:

trex eaterofcadrs
Jun 17, 2005
My lack of understanding is only exceeded by my lack of concern.

Flobbster posted:

:gonk:

This is what wildcards are for. If you want a method that takes a List of anything, do this:

code:
	public void method(List<?> o) {
		System.out.println("method two: " + o);
	}

Ah christ I totally forgot about those. Oh well this is why I use groovy and not java anymore.

Chairman Steve
Mar 9, 2007
Whiter than sour cream

Flobbster posted:

This is what wildcards are for. If you want a method that takes a List of anything, do this:

Anyone using wildcard generics should also be familiar with the PECS rule:

http://groups.google.com/group/juglugano/browse_thread/thread/c11531309ed37646?pli=1

If you don't understand the proper usage of super and extends, you'll be missing out on a significant bit of the power of Java's wildcard generics.

geeves
Sep 16, 2004

I'm building a search based on weightings of Tags that ends with returning Weighted HTML pages. For example Tag A would have a value of 5, Tag B: 3, Tag C: 2, Tag D: 1.

These are used as search parameters for a Lucene search with XPath. This search is ridiculously fast. It's searching through about 80,000 pages. Takes less than a second most searches.

Search returns Page A that has Tags B & C, Page B has tags A, C & D and so on.

Anyway, that's not the problem, the search on average returns 6500-8000 Pages. Each Page has a certain number of Tags assigned to it, so now I have a loop in a loop.

I have to go in and weight the returned Pages and order them descending. I'm using a HashMap<String, Integer> (Page.getPath(), Total Weight) right now to handle this, but I don't this this is the best way and this adding of total weights.

So I end up with something like this. Not pretty, but I'm at a loss on how to improve this or if I should even be using a Map for this (I inherited the initial version from a Contractor we had and all around his code was sub-par) . Right now this part takes ~6 seconds to run.

code:
HashMap<String, Integer> tagWeights = getTagWeights();
HashMap<String, Integer> pageWeights = new HashMap<String, Integer>();

PageIterator<Page> pi = executeSearch(query);

while(pi.hasNext()) {
  
  Page p = pi.next();
  Tag[] tag = p.getTags();

  for (int i = 0; i < tag.length; i++) {
    if (tagWeights.containsKey(tags[i].getName())) {

      Integer weight = tagWeights.get(tags[i].getName());
      if (pageWeights.containsKey(page.getPath())) {
        Integer tmp = allContentAndWeights.get(page.getPath());
        pageWeights.put(page.getPath(), tmp + weight);
      } else {
        pageWeights.put(page.getPath(), weight);
      }

    }
  }
}

trex eaterofcadrs
Jun 17, 2005
My lack of understanding is only exceeded by my lack of concern.
I would profile that call and see where you're spending most of your time. It's probably in HashMap.put() when it has to rebalance the Map. Maybe when you initialize the HashMap, you should give it an initial capacity about the size of the search set / 0.75.

Specifically:

JDK SE posted:

As a general rule, the default load factor (.75) offers a good tradeoff between time and space costs. Higher values decrease the space overhead but increase the lookup cost (reflected in most of the operations of the HashMap class, including get and put). The expected number of entries in the map and its load factor should be taken into account when setting its initial capacity, so as to minimize the number of rehash operations. If the initial capacity is greater than the maximum number of entries divided by the load factor, no rehash operations will ever occur.

e: goddamnit i suck today :(

trex eaterofcadrs fucked around with this message at 15:46 on Jun 1, 2010

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
1. Consider whether you can reasonably just add this as an int field to Page.

2. You're doing a lot of unnecessary re-lookups. This actually hashes the tag name twice:
code:
if (tagWeights.containsKey(tags[i].getName())) {
  Integer weight = tagWeights.get(tags[i].getName());
Just call get() and check the result for null. Similarly with your pageWeights lookup.

3. Profile.

4. If Page is hashed/compared by object identity, consider using an IdentityHashMap. It's actually a totally different hash implementation from HashMap which is (1) substantially faster and (2) substantially less memory hungry.

5. Consider making the values of pageWeights a mutable record of some kind so that you don't have to create new objects all the time.

stubblyhead
Sep 13, 2007

That is treason, Johnny!

Fun Shoe
I'm starting a new job soon where it will be useful to have at least a fundamental knowledge of java. I have a fair amount of experience in other languages, but very little in java itself. They know I don't know it and that's ok, so I'm just trying to get my arms around the basics for now. I have a few basic questions though.

Say I have a compiled class HelloWorld.class. To run it from the command line, I would type java HelloWorld. Why can I not use java HelloWorld.class ? Unix is usually very particular about filenames, so it surprises me that using the full filename causes errors.

Secondly, is it possible to make the class file executable on its own, similar to how you can write a perl script, set the execute flag and add #!/usr/bin/perl at the top?

Sebbe
Feb 29, 2004

stubblyhead posted:

Say I have a compiled class HelloWorld.class. To run it from the command line, I would type java HelloWorld. Why can I not use java HelloWorld.class ? Unix is usually very particular about filenames, so it surprises me that using the full filename causes errors.

You are actually not telling Java to open HelloWorld.class, but rather telling Java to execute the main method on the class HelloWorld, which just so happens to be located in the directory you're in (which also by happenstance is the default class path.)

stubblyhead posted:

Secondly, is it possible to make the class file executable on its own, similar to how you can write a perl script, set the execute flag and add #!/usr/bin/perl at the top?
I'm pretty sure you need to package the program in an executable JAR to make it easily launchable.

Adbot
ADBOT LOVES YOU

geeves
Sep 16, 2004

TRex EaterofCars, Added the initial capacity, didn't make much difference.

rjmccall posted:

1. Consider whether you can reasonably just add this as an int field to Page.

Page is actually a Node (we're using a JCR) and it's its own object. I even went as far as thinking to extend it for this purpose, but that might be overkill.

quote:

2. You're doing a lot of unnecessary re-lookups. This actually hashes the tag name twice:
code:
if (tagWeights.containsKey(tags[i].getName())) {
  Integer weight = tagWeights.get(tags[i].getName());
Just call get() and check the result for null. Similarly with your pageWeights lookup.

Did this, no improvement.

quote:

3. Profile.
Working on this bit. There's only 2 of us doing a gargantuan amount of work (most of my work has been fixing most of what this contractor did for us. This is the last bit I'm trying to fix. I had a few suggestions earlier in this thread, but haven't had time to really explore them other than downloading what is necessary and read some "Getting Started" material.

quote:

4. If Page is hashed/compared by object identity, consider using an IdentityHashMap. It's actually a totally different hash implementation from HashMap which is (1) substantially faster and (2) substantially less memory hungry.

This is where I am now. Giving it a try.

quote:

5. Consider making the values of pageWeights a mutable record of some kind so that you don't have to create new objects all the time.

You're talking about where I create Integer weight = pageWeights.get... ?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply