What is the quickest way to export a very large string (several megabytes) from a Java app to on-page javascript? At the moment it's taking so long the browser grinds to a halt.
Here is the code I'm using to modify the DOM:
window = JSObject.getWindow(this);
document = (JSObject) window.getMember("document");
for (int i = 0; i < encHexFileUploadStr.length(); i++){
char c = encHexFileUploadStr.charAt(i);
document.eval("document.getElementById('encOutgoingData').value += '"+c+"';");
if (i % 100 == 0) document.eval("console.log("+i+");");
}
Before this I tried to just assign the encHexFileUploadStr variable directly in one go, that was no better.
Is there any good way to do this that isn't so slow?
Thanks!
I have not attempted to transfer the amount of data you are mentioning from a Java application to a webpage, however, if you are using document.eval the performance problem you are having is most likely due to the processing required on an eval statement. An alternative approach is to directly invoke a JavaScript method which performs the actual data update work. Here is an example of how you would go about using this approach:
Java
JSObject jso = JSObject.getWindow(this);
// invoke JavaScript method updateData with parameter encHexFileUploadStr
jso.call("updateData", new String[] { encHexFileUploadStr });
JavaScript
function updateData(s) {
document.getElementById('encOutgoingData').value = s;
}
I would combine Kris' suggestion with breaking the string in chunks of 1024 bytes or such and append to a string in JavaScript and at the end copy, in JavaScript, the string to the field
How do I optimize this method for breaking a string in chunks?
Also in the loop, make it a habit to do
for (int i = 0, n=something.length();i<n; i++){
rather than
for (int i = 0; i < something.length(); i++){
Related
I created a custom DataSetIterator. It works by randomly generating two INDArrays (one for input and one for output) in the next method and creating a DataSet out of it:
int[][] inputArray = new int[num][NUM_INPUTS];
int[][] expectedOutputArray = new int[num][];
for (int i = 0; i < num; i++) {//just fill the arrays with some data
int sum = 0;
int product = 1;
for (int j = 0; j < inputArray[i].length; j++) {
inputArray[i][j] = rand.nextInt();
sum += inputArray[i][j];
product *= inputArray[i][j];
}
expectedOutputArray[i] = new int[] { sum, product, sum / inputArray[i].length };
}
INDArray inputs = Nd4j.createFromArray(inputArray);//never closed
INDArray desiredOutputs = Nd4j.createFromArray(expectedOutputArray);//never closed
return new DataSet(inputs, desiredOutputs);
However, INDArray implements AutoClosable and the javadoc for close() states:
This method releases exclusive off-heap resources uses by this INDArray instance. If INDArray relies on shared resources, exception will be thrown instead PLEASE NOTE: This method is NOT safe by any means
Do I need to close the INDArrays?
If so, when do I need to close the INDArrays?
I have tried to use a try-with-resources but it threw an exception as the INDArray is closed when using it in the fit method.
The documentation of createFromArray(int[][]) does not seem to explain this.
you don't really need to close them. We take care of that automatically with javacpp. You can choose to close them but AutoCloseable was implemented for people who wanted more control over the memory management of the ndarrays.
Edit: Javacpp is the underlying native integration that we use to connect to native libraries we maintain written in c++ and other libraries. All of our calculations and data are all based on native code and off heap memory.
close() just forces us to de allocate those buffers faster. Javacpp has automatic de allocation built in to it already though.
I have to remove all slash (/) from the beginning of string.
So I have written
while (convertedUrl.startsWith("\\"))
{
convertedUrl = convertedUrl.substring(1);
}
Above code creates string for each substring.
Is there any better way to write this code in java 8 or later?
How can I do it keeping mind memory utilisation and performance.
I would guess at:
int len = str.length();
int i=0;
for (; i<len && str.charAt(i) == '\\'; ++i) {
;
}
return str.substring(i);
I write str instead of convertedUrl because this should be in its own method.
It is unlikely this is a performance bottleneck, but the original code may run as slow as O(n^2) (depending on implementation).
can you simply not use something like this, to replace all the "/" in one go
convertedUrl = convertedUrl.replaceAll("\\/","");
I am sorry for the initial one, but I think this will do:
convertedUrl = convertedUrl.replaceFirst("^/*","");
OR this:
convertedUrl = convertedUrl.replaceAll("^/*","");
both will get the job done!
as they replaces all the leading "/" chars!
I use Twitter anomaly detection algorithm in my project. For this purpose I use Rserve library to run R code in my Java application.
My Java code:
RConnection connection = new RConnection();
connection.voidEval("library(AnomalyDetection)");
connection.eval("res <- AnomalyDetectionTs(data.frame(/*list of timestamps*/,/*list of values*/), direction='both', plot=FALSE, longterm=TRUE)");
And, as a result, I got this output:
$anoms
timestamp anoms
1 1980-09-25 16:05:00 21.3510
2 1980-09-29 06:40:00 193.1036
3 1980-09-29 21:44:00 148.1740
To get results now I'm using this not nice solution:
connection.eval("write.csv(res[['anoms']],file='anom.csv')");
Then I open this file in Java and parse the results.
So, how to get the output results in Java using Rserve possibilities for data.frame structure?
Simply write the R command such that it returns the desired result back to Java:
RList l = c.eval("AnomalyDetectionTs(data, direction='both',
plot=FALSE, longterm=TRUE)$anoms").asList();
What you get is the data frame (as a list) with the two variables timestamp and anoms.
However, AnomalyDetectionTs returns dates in a horribly annoying and inefficient format so you may want to actually return a more sane result which is easier to work with in Java, e.g.:
RList l = c.eval("{ res <- AnomalyDetectionTs(data, direction='both', plot=FALSE,
longterm=TRUE)$anoms;
list(as.POSIXct(res$timestamp), res$anoms) }").asList();
double ts[] = l.at(0).asDoubles();
double anom[] = l.at(1).asDoubles();
for (int i = 0; i < ts.length; i++)
System.out.println(new java.util.Date((long)(ts[i]*1000.0)) + ": " + anom[i]);
PS: the right place for Rserve questions is the stats-rosuda-devel mailing list which will give you answers much faster.
I am using the below line in JAVA Embedding to assign value to a BPEL Invoke DB adapter input variable.
setVariableData("S2C_insert_InputVariable","TmpInvStoc3Collection","/ns8:TmpInvStoc3Collection/ns8:TmpInvStoc3/ns8:batchid","12345");
Now i want to put this statement in a while loop within java and want to repeat this for n iterations. I want to place a loop variable in the collection but I dont know how to do this.
I am looking for something like below.
setVariableData("S2C_insert_InputVariable","TmpInvStoc3Collection","/ns8:TmpInvStoc3Collection/ns8:TmpInvStoc3[$loop_variable]/ns8:batchid","12345");
Please let me know how to achieve this
Regards
Murali
This is based on the assumption that value is a function of i and cannot be calculated in the BPEL.
String qry = "";
for (int i = 0; i < n; i++)
{
value = SomeFunctionThatRequiresJavaRatherThanBPEL(i);
qry = "/ns8:TmpInvStoc3Collection/ns8:TmpInvStoc3[" + i + "]/ns8:batchid";
setVariableData("S2C_insert_InputVariable","TmpInvStoc3Collection",qry,value);
}
The code could be more efficient but it should do what you want.
I am working with matrix in java. ( another story :) )
I want to read a CSV file and store it in a variable. I will manipulate values then again store it in CSV file. I used STRING as data type. But if CSV file has like 500 columns. It kill my program speed :(. I think this is not good data type. Which data type I can use to temporary store LONG TEXT?
If my question is not clear please ask questions. I will explain.
Thanks
P.S: I am reading one line and storing it in variable like this
String str;
str += read line by line from CSV;
here is the loop
String reduceM="";
for(int kk=0;kk<W2.getRowDimension();kk++){
for(int jj=0;jj<W2.getColumnDimension();jj++){
reduceM += Double.toString(reduceMatrix[kk][jj]);
}
System.out.println("\r\n");
}
Use a StringBuilder (or StringBuffer if you're using Java 1.5 or older):
StringBuilder builder = new StringBuilder();
for (int kk = 0; kk<W2.getRowDimension(); kk++) {
for(int jj = 0; jj < W2.getColumnDimension(); jj++) {
builder.append(reduceMatrix[kk][jj]);
}
}
This will avoid it creating a new (and increasingly long) string for each iteration of the two loops.
However, there are no commas or line-breaks in this code - I suspect you actually want something like this:
StringBuilder builder = new StringBuilder();
for (int kk = 0; kk < W2.getRowDimension(); kk++) {
for (int jj = 0; jj < W2.getColumnDimension(); jj++) {
builder.append(reduceMatrix[kk][jj])
.append(",");
}
builder.append("\n"); // Or whatever line terminator you want
}
Note that that will leave an extra comma at the end of each row - let me know if you want ideas of how to remove that.
See this article for why this could make a huge improvement to your running time. (Note that it's an old article, talking about StringBuffer rather than StringBuilder - the latter is just an unsynchronized version of the former.)
Use the 'StringBuffer' class for concatenations. It is much more efficient.
Take a look at this article for an explanation: here
EDIT - Sorry I did not see this was already answered
Prefer StringBuilder, there is a big difference in performance compared to the string concatenation(+).
In addition to the skeet's great answer; dont write to system.out if its not necessary, or if you want to write to console use buffers or write when loop finishes. It makes your program cumbersome because each time it is encountered in the loop System.out stream opens writes flushes and closes.