Using superfasthash in Java - java

I am testing the speed comparison between superfasthash and the default hashing algorithm used in Java.
But I'm not sure if I'm using the superfasthash algo correctly as I can't really find any documentation on what the params mean.
I got the java impl of the algo here.
This is my code:
public class Main
{
static List<String> dataArray = new ArrayList<>();
public static void main(String[] args) throws IOException
{
writeToArray();
System.out.println("Finished writing to the array.");
//hashing using default java
long startTime = System.nanoTime();
dataArray.stream()
.forEach(s -> s.hashCode());
long endTime = System.nanoTime();
long duration = (endTime - startTime); //divide by 1000000 to get milliseconds.
System.out.println("Finished hashing the file using default java (nanoseconds): " + duration );
//hashing using superfasthash algo
startTime = System.nanoTime();
dataArray.stream()
.forEach(s -> {
SuperFastHash.calculate(s.getBytes(), 1, 1, 1);
});
endTime = System.nanoTime();
duration = (endTime - startTime); //divide by 1000000 to get milliseconds.
System.out.println("Finished hashing superfasthash algo (nanoseconds): " + duration );
}
private static void writeToArray()
{
String abc = "abcdefghijklmnopqrstuvwxyz";
String toHash;
Random r = new Random();
for (int i = 0; i <= 1000000; i++)
{
toHash = "";
for (int ii = 0; ii < 10; ii++)
{
int low = 0;
int high = 26;
int result = r.nextInt(high - low) + low;
toHash = toHash + abc.charAt(result);
}
dataArray.add(toHash);
System.out.println("Writing index = " + i + ". String: " + toHash);
}
}
}
but not sure what to write in the parameter when using the calculate function from SuperFastHash class.

Related

Java calculate time difference between check in and out

I want to calculate the time difference hour and minute without using java dateformat
user should input like
Clock In: 23:00
Clock Out: 01:00
The expected output shall be something like 2 hours 00 minutes.
But how can I calculate them?
Scanner input = new Scanner(System.in);
//Read data
System.out.print("Clock In: ");
String sTimeIn = input.nextLine();
System.out.print("Clock Out: ");
String sTimeOut = input.nextLine();
// Process data
String sHourIn = sTimeIn.substring(0, 2);
String sMinuteIn = sTimeIn.substring(3, 5);
String sHourOut = sTimeOut.substring(0, 2);
String sMinuteOut = sTimeOut.substring(3, 5);
int iHourIn = Integer.parseInt(sHourIn);
int iMinuteIn = Integer.parseInt(sMinuteIn);
int iHourOut = Integer.parseInt(sHourOut);
int iMinuteOut = Integer.parseInt(sMinuteOut);
int sumHour =
int sumMinute =
//Display Output
System.out.print(sumHour +"Hour "+ sumMinute + " Minute");
}
}
After I have reviewed all the solutions you given. Here is what I have edited. But I still found an issue is,
if Clock in 23:00 Clock Out: 01:00 and the output is 22Hour(s) 0 Minute(s). The output should be 02 Hour(s) 0 Minute(s).
System.out.println("*Your time format must be 00:00");
System.out.print("Clock In: ");
String getTimeIn = input.nextLine();
System.out.print("Clock Out: ");
String getTimeOut = input.nextLine();
// Process data
String sHourIn = getTimeIn.substring(0, 2);
String sMinuteIn = getTimeIn.substring(3, 5);
String sHourOut = getTimeOut.substring(0, 2);
String sMinuteOut = getTimeOut.substring(3, 5);
int sumHour = Integer.parseInt(sHourIn) - Integer.parseInt(sHourOut);
int sumMinute = Integer.parseInt(sMinuteIn) - Integer.parseInt(sMinuteOut);
if(sumHour < 0) {
sumHour =-sumHour;
}
if(sumMinute < 0) {
sumMinute =- sumMinute;
}
//Display Output
System.out.print(sumHour +"Hour(s) "+ sumMinute + " Minute(s)");
If you want to use LocalTime and ChronoUnit classes of Java 8:
String sTimeIn = "23:15";
String sTimeOut = "1:30";
LocalTime timeIn = LocalTime.parse(sTimeIn, DateTimeFormatter.ofPattern("H:m"));
LocalTime timeOut = LocalTime.parse(sTimeOut, DateTimeFormatter.ofPattern("H:m"));
long dif = ChronoUnit.MINUTES.between(timeIn, timeOut);
if (dif < 0)
dif += 24 * 60;
long sumHour = dif / 60;
long sumMinute = dif % 60;
System.out.println(sumHour + ":"+ sumMinute);
or formatted to HH:mm:
System.out.println(String.format("%02d", sumHour) + ":"+ String.format("%02d", sumMinute));
will print:
02:15
As #Stultuske said the time library should be a safer option, I have provided an example below
import java.time.LocalTime;
public class HelloWorld
{
public static void main(String[] args)
{
LocalTime in = LocalTime.parse("18:20");
LocalTime out = LocalTime.parse("20:30");
int hoursDiff = (out.getHour() - in.getHour()),
minsDiff = (int)Math.abs(out.getMinute() - in.getMinute()),
secsDiff = (int)Math.abs(out.getSecond() - in.getSecond());
System.out.println(hoursDiff+":"+minsDiff+":"+secsDiff);
}
}
Update:
The solution is missing the midnight crossing as pointed by #Joakim Danielson, So I have modified the above solution to check for in > out or out < in.
import java.time.LocalTime;
public class HelloWorld
{
public static void main(String[] args)
{
LocalTime in = LocalTime.parse("16:00");
LocalTime out = LocalTime.parse("01:00");
int hOut = out.getHour(),
hIn = in.getHour();
int hoursDiff = hOut < hIn ? 24 - hIn + hOut : hOut - hIn,
minsDiff = (int)Math.abs(out.getMinute() - in.getMinute()),
secsDiff = (int)Math.abs(out.getSecond() - in.getSecond());
System.out.println(hoursDiff+":"+minsDiff+":"+secsDiff);
}
}
Here is my suggested solution including some simple (not perfect) validation of the input, I have put the solution inside a method so asking user for input is not handled
public static void calcTime(String sTimeIn, String sTimeOut) {
final String timePattern = "[0-2][0-9]:[0-5][0-9]";
if (sTimeIn == null || sTimeOut == null || !sTimeIn.matches(timePattern) || !sTimeIn.matches(timePattern)) {
throw new IllegalArgumentException();
}
String[] timeIn = sTimeIn.split(":");
String[] timeOut = sTimeOut.split(":");
int inMinutes = 60 * Integer.valueOf(timeIn[0]) + Integer.valueOf(timeIn[1]);
int outMinutes = 60 * Integer.valueOf(timeOut[0]) + Integer.valueOf(timeOut[1]);
int diff = 0;
if (outMinutes > inMinutes) {
diff = outMinutes - inMinutes;
} else if (outMinutes < inMinutes) {
diff = outMinutes + 24 * 60 - inMinutes;
}
System.out.printf("Time difference between %s and %s is %d hours and %d minutes\n", sTimeIn, sTimeOut, diff / 60, diff % 60);
}
Update
Here is a solution based on LocalTime and Duration
public static void calcTime2(String sTimeIn, String sTimeOut) {
final String timePattern = "[0-2][0-9]:[0-5][0-9]";
if (sTimeIn == null || sTimeOut == null || !sTimeIn.matches(timePattern) || !sTimeIn.matches(timePattern)) {
throw new IllegalArgumentException();
}
String[] timeIn = sTimeIn.split(":");
String[] timeOut = sTimeOut.split(":");
LocalTime localTimeIn = LocalTime.of(Integer.valueOf(timeIn[0]), Integer.valueOf(timeIn[1]));
LocalTime localTimeOut = LocalTime.of(Integer.valueOf(timeOut[0]), Integer.valueOf(timeOut[1]));
Duration duration;
if (localTimeOut.isAfter(localTimeIn)) {
duration = Duration.between(localTimeIn, localTimeOut);
} else {
Duration prevDay = Duration.ofHours(24).minusHours(localTimeIn.getHour()).minusMinutes(localTimeIn.getMinute());
Duration nextDay = Duration.between(LocalTime.MIDNIGHT, localTimeOut);
duration = prevDay.plus(nextDay);
}
System.out.printf("Time difference between %s and %s is %d hours and %d minutes\n", sTimeIn, sTimeOut,
duration.toHours(), duration.minusHours(duration.toHours()).toMinutes());
}
try this :
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//Read data
System.out.println("Clock In: ");
String sTimeIn = "20:30";
System.out.println("Clock Out: ");
String sTimeOut = "18:20";
// Process data
String sHourIn = sTimeIn.substring(0, 2);
String sMinuteIn = sTimeIn.substring(3, 5);
String sHourOut = sTimeOut.substring(0, 2);
String sMinuteOut = sTimeOut.substring(3, 5);
int iHourIn = Integer.parseInt(sHourIn);
int iMinuteIn = Integer.parseInt(sMinuteIn);
int iHourOut = Integer.parseInt(sHourOut);
int iMinuteOut = Integer.parseInt(sMinuteOut);
Calendar cal = Calendar.getInstance();
cal.set(Calendar.HOUR_OF_DAY,iHourIn);
cal.set(Calendar.MINUTE,iMinuteIn);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
Long timeIn = cal.getTime().getTime();
cal.set(Calendar.HOUR_OF_DAY,iHourOut);
cal.set(Calendar.MINUTE,iMinuteOut);
cal.set(Calendar.SECOND,0);
cal.set(Calendar.MILLISECOND,0);
Long timeOut = cal.getTime().getTime();
Long finaltime= timeIn-timeOut;
// Convert the result to Hours and Minutes
Long temp = null;
// get hours
temp = finaltime % 3600000 ;
int sumHour = (int) ((finaltime - temp) / 3600000 );
finaltime = temp;
int sumMinute = (int) (finaltime/ 60000);
//Display Output
System.out.println(sumHour +" Hour "+ sumMinute + " Minute");
}
I have added some code in addition to your code. Please check and let me know if this is enough for your requirement
public class MainClass1 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
//Read data
System.out.print("Clock In: ");
String[] sTimeIn = input.nextLine().split(":");
System.out.print("Clock Out: ");
String[] sTimeOut = input.nextLine().split(":");
int iHourIn = Integer.parseInt(sTimeIn[0]);
int iMinuteIn = Integer.parseInt(sTimeIn[1]);
int iHourOut = Integer.parseInt(sTimeOut[0]);
int iMinuteOut = Integer.parseInt(sTimeOut[1]);
if(iMinuteIn < iMinuteOut) {
iMinuteIn = 60 + iMinuteIn;
iHourIn--;
}
int sumHour = iHourIn - iHourOut;
int sumMinute = iMinuteIn - iMinuteOut;
//Display Output
System.out.print(sumHour +"Hour "+ sumMinute + " Minute");
}
}

How can I improve the performance of execution time? And Is their any better way to read this file?

I am trying to split a text file with multiple threads. The file is of 1 GB. I am reading the file by char. The Execution time is 24 min 54 seconds. Instead of reading a file by char is their any better way where I can reduce the execution time.
I'm having a hard time figuring out an approach that will reduce the execution time. Please do suggest me also, if there is any other better way to split file with multiple threads. I am very new to java.
Any help will be appreciated. :)
public static void main(String[] args) throws Exception {
RandomAccessFile raf = new RandomAccessFile("D:\\sample\\file.txt", "r");
long numSplits = 10;
long sourceSize = raf.length();
System.out.println("file length:" + sourceSize);
long bytesPerSplit = sourceSize / numSplits;
long remainingBytes = sourceSize % numSplits;
int maxReadBufferSize = 9 * 1024;
List<String> filePositionList = new ArrayList<String>();
long startPosition = 0;
long endPosition = bytesPerSplit;
for (int i = 0; i < numSplits; i++) {
raf.seek(endPosition);
String strData = raf.readLine();
if (strData != null) {
endPosition = endPosition + strData.length();
}
String str = startPosition + "|" + endPosition;
if (sourceSize > endPosition) {
startPosition = endPosition;
endPosition = startPosition + bytesPerSplit;
} else {
break;
}
filePositionList.add(str);
}
for (int i = 0; i < filePositionList.size(); i++) {
String str = filePositionList.get(i);
String[] strArr = str.split("\\|");
String strStartPosition = strArr[0];
String strEndPosition = strArr[1];
long startPositionFile = Long.parseLong(strStartPosition);
long endPositionFile = Long.parseLong(strEndPosition);
MultithreadedSplit objMultithreadedSplit = new MultithreadedSplit(startPositionFile, endPositionFile);
objMultithreadedSplit.start();
}
long endTime = System.currentTimeMillis();
System.out.println("It took " + (endTime - startTime) + " milliseconds");
}
}
public class MultithreadedSplit extends Thread {
public static String filePath = "D:\\tenlakh\\file.txt";
private int localCounter = 0;
private long start;
private long end;
public static String outPath;
List<String> result = new ArrayList<String>();
public MultithreadedSplit(long startPos, long endPos) {
start = startPos;
end = endPos;
}
#Override
public void run() {
try {
String threadName = Thread.currentThread().getName();
long currentTime = System.currentTimeMillis();
RandomAccessFile file = new RandomAccessFile("D:\\sample\\file.txt", "r");
String outFile = "out_" + threadName + ".txt";
System.out.println("Thread Reading started for start:" + start + ";End:" + end+";threadname:"+threadName);
FileOutputStream out2 = new FileOutputStream("D:\\sample\\" + outFile);
file.seek(start);
int nRecordCount = 0;
char c = (char) file.read();
StringBuilder objBuilder = new StringBuilder();
int nCounter = 1;
while (c != -1) {
objBuilder.append(c);
// System.out.println("char-->" + c);
if (c == '\n') {
nRecordCount++;
out2.write(objBuilder.toString().getBytes());
objBuilder.delete(0, objBuilder.length());
//System.out.println("--->" + nRecordCount);
// break;
}
c = (char) file.read();
nCounter++;
if (nCounter > end) {
break;
}
}
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
The fastest way would be to map the file into memory segment by segment (mapping a large file as a whole may cause undesired side effects). It will skip few relatively expensive copy operations. The operating system will load file into RAM and JRE will expose it to your application as a view into an off-heap memory area in a form of a ByteBuffer. It would usually allow you to squeze last 2x/3x of the performance.
Memory-mapped way requires quite a bit of helper code (see the fragment in the bottom), it's not always the best tactical way. Instead, if your input is line-based and you just need reasonable performance (what you have now is probably not) then just do something like:
import java.nio.Files;
import java.nio.Paths;
...
File.lines(Paths.get("/path/to/the/file"), StandardCharsets.ISO_8859_1)
// .parallel() // parallel processing is still possible
.forEach(line -> { /* your code goes here */ });
For the contrast, a working example of the code for working with the file via memory mapping would look something like below. In case of fixed-size records (when segments can be selected precisely to match record boundaries) subsequent segments can be processed in parallel.
static ByteBuffer mapFileSegment(FileChannel fileChannel, long fileSize, long regionOffset, long segmentSize) throws IOException {
long regionSize = min(segmentSize, fileSize - regionOffset);
// small last region prevention
final long remainingSize = fileSize - (regionOffset + regionSize);
if (remainingSize < segmentSize / 2) {
regionSize += remainingSize;
}
return fileChannel.map(FileChannel.MapMode.READ_ONLY, regionOffset, regionSize);
}
...
final ToIntFunction<ByteBuffer> consumer = ...
try (FileChannel fileChannel = FileChannel.open(Paths.get("/path/to/file", StandardOpenOption.READ)) {
final long fileSize = fileChannel.size();
long regionOffset = 0;
while (regionOffset < fileSize) {
final ByteBuffer regionBuffer = mapFileSegment(fileChannel, fileSize, regionOffset, segmentSize);
while (regionBuffer.hasRemaining()) {
final int usedBytes = consumer.applyAsInt(regionBuffer);
if (usedBytes == 0)
break;
}
regionOffset += regionBuffer.position();
}
} catch (IOException ex) {
throw new UncheckedIOException(ex);
}

How to measure time taken by websocket to respond

We are using web sockets in our project and there is a requirement on to evaluate the speed of websocket. How to measure the time taken by websocket to respond
Given that I am new in Stack Overflow and I can't write comments, I will try to give you an answer with the info that you posted.
If you go to Google you will find many examples about "How to calculate elapsed" or "execute time in Java". The following examples were extracted from mkyong
Date().getTime():
long lStartTime = new Date().getTime();
//some tasks
long lEndTime = new Date().getTime();
long difference = lEndTime - lStartTime;
System.out.println("Elapsed milliseconds: " + difference);
System.currentTimeMillis()
long lStartTime = System.currentTimeMillis();
//some tasks
long lEndTime = System.currentTimeMillis();
long difference = lEndTime - lStartTime;
System.out.println("Elapsed milliseconds: " + difference);
System.nanoTime()
long lStartTime = System.nanoTime();
//some tasks
long lEndTime = System.nanoTime();
long difference = lEndTime - lStartTime;
System.out.println("Elapsed milliseconds: " + difference/1000000);
Full example
import java.util.Date;
public class TimeApp {
public static void main(String[] argv) {
long lStartTime = new Date().getTime(); // start time
createArray(); // some tasks to eat time
long lEndTime = new Date().getTime(); // end time
long difference = lEndTime - lStartTime; // check different
System.out.println("Elapsed milliseconds: " + difference);
}
public static void createArray() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
String sArray[] = new String[1000000];
for (int i = 0; i < 1000000; i++)
sArray[i] = "Array " + i;
}
}
Hopefully this will help you!

Clipping mp4s with mp4parser. Can't get past timeCorrected with SyncSample

I am writing an Android app and I have a bunch of 5-15 second .mp4 files that I want to clip. I have been trying to use Sebastian Annies' mp4parser to do so, following the example code given here: ShortenExample.
Here is the code I am using (heavily resembles the example code above):
public static void clip(Sprinkle sprinkle, double start, double end) throws IOException {
Movie movie = MovieCreator.build(sprinkle.getLocalVideoPath());
// Save all tracks then remove them from movie
List<Track> tracks = movie.getTracks();
movie.setTracks(new LinkedList<Track>());
boolean timeCorrected = false;
// Here we try to find a track that has sync samples. Since we can only start decoding
// at such a sample we SHOULD make sure that the start of the new fragment is exactly
// such a frame
for (Track track : tracks) {
if (track.getSyncSamples() != null && track.getSyncSamples().length > 0) {
if (timeCorrected) {
// This exception here could be a false positive in case we have multiple tracks
// with sync samples at exactly the same positions. E.g. a single movie containing
// multiple qualities of the same video (Microsoft Smooth Streaming file)
Log.v("clip", "track.getSyncSamples().length: " + track.getSyncSamples().length);
throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
}
Log.v("syncSample", "start before: " + start);
Log.v("syncSample", "end before: " + end);
start = correctTimeToSyncSample(track, start, false);
end = correctTimeToSyncSample(track, end, true);
Log.v("syncSample", "start after: " + start);
Log.v("syncSample", "end after: " + end);
timeCorrected = true;
}
}
for (Track track : tracks) {
long currentSample = 0;
double currentTime = 0;
double lastTime = 0;
long startSample = -1;
long endSample = -1;
for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
for (int j = 0; j < entry.getCount(); j++) {
if (currentTime > lastTime && currentTime <= start) {
// current sample is still before the new starttime
startSample = currentSample;
}
if (currentTime > lastTime && currentTime <= end) {
// current sample is after the new start time and still before the new endtime
endSample = currentSample;
}
lastTime = currentTime;
currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
currentSample++;
}
}
movie.addTrack(new AppendTrack(new CroppedTrack(track, startSample, endSample)));
}
long start1 = System.currentTimeMillis();
Container out = new DefaultMp4Builder().build(movie);
long start2 = System.currentTimeMillis();
File file = Constants.getEditsDir();
FileOutputStream fos = new FileOutputStream(file.getPath() + String.format("output-%f-%f.mp4", start, end));
FileChannel fc = fos.getChannel();
out.writeContainer(fc);
fc.close();
fos.close();
long start3 = System.currentTimeMillis();
System.err.println("Building IsoFile took : " + (start2 - start1) + "ms");
System.err.println("Writing IsoFile took : " + (start3 - start2) + "ms");
System.err.println("Writing IsoFile speed : " + (new File(String.format("output-%f-%f.mp4", start, end)).length() / (start3 - start2) / 1000) + "MB/s");
}
private static double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
long currentSample = 0;
double currentTime = 0;
for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
for (int j = 0; j < entry.getCount(); j++) {
if (Arrays.binarySearch(track.getSyncSamples(), currentSample + 1) >= 0) {
// samples always start with 1 but we start with zero therefore +1
timeOfSyncSamples[Arrays.binarySearch(track.getSyncSamples(), currentSample + 1)] = currentTime;
}
currentTime += (double) entry.getDelta() / (double) track.getTrackMetaData().getTimescale();
currentSample++;
}
}
double previous = 0;
for (double timeOfSyncSample : timeOfSyncSamples) {
if (timeOfSyncSample > cutHere) {
if (next) {
return timeOfSyncSample;
} else {
return previous;
}
}
previous = timeOfSyncSample;
}
return timeOfSyncSamples[timeOfSyncSamples.length - 1];
}
I can't seem to prevent the error "The startTime has already been corrected by another track with SyncSample. Not Supported." from occurring. When I log the tracks that I am looping through, getHandler() returns "vide", "soun", and then crashes when it comes to "hint". If I comment this part out:
if (timeCorrected) {
// This exception here could be a false positive in case we have multiple tracks
// with sync samples at exactly the same positions. E.g. a single movie containing
// multiple qualities of the same video (Microsoft Smooth Streaming file)
Log.v("clip", "track.getSyncSamples().length: " + track.getSyncSamples().length);
throw new RuntimeException("The startTime has already been corrected by another track with SyncSample. Not Supported.");
}
then the program just crashes with an index out of bounds error when it gets to the line
Container out = new DefaultMp4Builder().build(movie);
What am I doing wrong?
You are getting an IndexOutOfBoundsException, because either your startSample or your endSample has a wrong value (e.g. still -1) when reaching
Container out = new DefaultMp4Builder().build(movie);
In my example using a start value for the clipping process of smaller than 2 seconds resulted in the effect that if (currentTime > lastTime && currentTime <= start) never reached a true value and thus startSample was not updated from it's initial value of -1. One solution for this is to change the initial value of startSample from -1 to 0.
use this iso-parser library.https://code.google.com/p/mp4parser/downloads/detail?name=isoviewer-1.0-RC-28.jar&can=2&q=
private void doShorten(final int _startTime, final int _endTime) {
try {
File folder = new File(VideoPath);
Movie movie = MovieCreator.build(VideoPath);
List<Track> tracks = movie.getTracks();
movie.setTracks(new LinkedList<Track>());
// remove all tracks we will create new tracks from the old
double startTime = _startTime;
double endTime = _endTime;// (double) getDuration(tracks.get(0)) /
// tracks.get(0).getTrackMetaData().getTimescale();
boolean timeCorrected = false;
// Here we try to find a track that has sync samples. Since we can
// only start decoding
// at such a sample we SHOULD make sure that the start of the new
// fragment is exactly
// such a frame
for (Track track : tracks) {
if (track.getSyncSamples() != null
&& track.getSyncSamples().length > 0) {
if (timeCorrected) {
// This exception here could be a false positive in case
// we have multiple tracks
// with sync samples at exactly the same positions. E.g.
// a single movie containing
// multiple qualities of the same video (Microsoft
// Smooth Streaming file)
throw new RuntimeException(
"The startTime has already been corrected by another track with SyncSample. Not Supported.");
}
startTime = correctTimeToSyncSample(track, startTime, false);
endTime = correctTimeToSyncSample(track, endTime, true);
timeCorrected = true;
}
}
for (Track track : tracks) {
long currentSample = 0;
double currentTime = 0;
long startSample = -1;
long endSample = -1;
for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
TimeToSampleBox.Entry entry = track
.getDecodingTimeEntries().get(i);
for (int j = 0; j < entry.getCount(); j++) {
// entry.getDelta() is the amount of time the current
// sample covers.
if (currentTime <= startTime) {
// current sample is still before the new starttime
startSample = currentSample;
}
if (currentTime <= endTime) {
// current sample is after the new start time and
// still before the new endtime
endSample = currentSample;
} else {
// current sample is after the end of the cropped
// video
break;
}
currentTime += (double) entry.getDelta()
/ (double) track.getTrackMetaData()
.getTimescale();
currentSample++;
}
}
movie.addTrack(new CroppedTrack(track, startSample, endSample));
}
long start1 = System.currentTimeMillis();
Container out = new DefaultMp4Builder().build(movie);
long start2 = System.currentTimeMillis();
String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss")
.format(new Date());
String filename = "TrimVideo"+System.currentTimeMillis()+".mp4";
RandomAccessFile fc = new RandomAccessFile(
Environment.getExternalStorageDirectory()+"/myfolder/"+filename,
"rw");
FileChannel fc2 = fc.getChannel();
out.writeContainer(fc2);
fc2.close();
AddVideoInfo(filename);
long start3 = System.currentTimeMillis();
System.err.println("Building IsoFile took : " + (start2 - start1)
+ "ms");
System.err.println("Writing IsoFile took : " + (start3 - start2)
+ "ms");
System.err.println("Writing IsoFile speed : "
+ (new File(String.format("TMP4_APP_OUT-%f-%f", startTime,
endTime)).length() / (start3 - start2) / 1000)
+ "MB/s");
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private void AddVideoInfo(String filename) {
// TODO Auto-generated method stub
File f = new File(Environment.getExternalStorageDirectory()
+ "/TotalRecall/"+filename);
EvientVideosListActivity.mVideoNamesList.add(f.getAbsolutePath());
Date lastModDate = new Date(f.lastModified());
SimpleDateFormat sdf = new SimpleDateFormat(
"MMM dd, yyyy hh:mm");
String date = sdf.format(lastModDate);
EvientVideosListActivity.mVideoDateList.add(date);
Bitmap bitmap = ThumbnailUtils.createVideoThumbnail(
f.getAbsolutePath(),
MediaStore.Video.Thumbnails.MINI_KIND);
EvientVideosListActivity.mVideoThumbsList.add(bitmap);
Global.mVideoCheckList.add(false);
}
long getDuration(Track track) {
long duration = 0;
for (TimeToSampleBox.Entry entry : track.getDecodingTimeEntries()) {
duration += entry.getCount() * entry.getDelta();
}
return duration;
}
double correctTimeToSyncSample(Track track, double cutHere, boolean next) {
double[] timeOfSyncSamples = new double[track.getSyncSamples().length];
long currentSample = 0;
double currentTime = 0;
for (int i = 0; i < track.getDecodingTimeEntries().size(); i++) {
TimeToSampleBox.Entry entry = track.getDecodingTimeEntries().get(i);
for (int j = 0; j < entry.getCount(); j++) {
if (Arrays.binarySearch(track.getSyncSamples(),
currentSample + 1) >= 0) {
// samples always start with 1 but we start with zero
// therefore +1
timeOfSyncSamples[Arrays.binarySearch(
track.getSyncSamples(), currentSample + 1)] = currentTime;
}
currentTime += (double) entry.getDelta()
/ (double) track.getTrackMetaData().getTimescale();
currentSample++;
}
}
double previous = 0;
for (double timeOfSyncSample : timeOfSyncSamples) {
if (timeOfSyncSample > cutHere) {
if (next) {
return timeOfSyncSample;
} else {
return previous;
}
}
previous = timeOfSyncSample;
}
return timeOfSyncSamples[timeOfSyncSamples.length - 1];
}

Java vs C# Multithreading performance, why is Java getting slower? (graphs and full code included)

I have recently been running benchmarks on Java vs C# for 1000 tasks to be scheduled over a threadpool. The server has 4 physical processors, each with 8 cores. The OS is Server 2008, has 32 GB of memory and each CPU is a Xeon x7550 Westmere/Nehalem-C.
In short, the Java implementation is much faster than C# at 4 threads but much slower as the number of threads increases. It also seems C# has become quicker per iteration, when the thread count has increased. Graphs are included in this post:
The Java implementation was written on a 64bit Hotspot JVM, with Java 7 and using an Executor Service threadpool I found online (see below). I also set the JVM to concurrent GC.
C# was written on .net 3.5 and the threadpool came from codeproject:
http://www.codeproject.com/Articles/7933/Smart-Thread-Pool
(I have included the code below).
My questions:
1) Why is Java getting slower but C# is getting quicker?
2) Why do the execution times of C# fluctuate greatly? (This is our main question)
We did wonder whether the C# fluctuation was caused by the memory bus being maxed out....
Code (Please do not highlight errors with locking, this is irrelevant with my aims):
Java
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PoolDemo {
static long FastestMemory = 2000000000;
static long SlowestMemory = 0;
static long TotalTime;
static long[] FileArray;
static DataOutputStream outs;
static FileOutputStream fout;
public static void main(String[] args) throws InterruptedException, FileNotFoundException {
int Iterations = Integer.parseInt(args[0]);
int ThreadSize = Integer.parseInt(args[1]);
FileArray = new long[Iterations];
fout = new FileOutputStream("server_testing.csv");
// fixed pool, unlimited queue
ExecutorService service = Executors.newFixedThreadPool(ThreadSize);
//ThreadPoolExecutor executor = (ThreadPoolExecutor) service;
for(int i = 0; i<Iterations; i++) {
Task t = new Task(i);
service.execute(t);
}
service.shutdown();
service.awaitTermination(90, TimeUnit.SECONDS);
System.out.println("Fastest: " + FastestMemory);
System.out.println("Average: " + TotalTime/Iterations);
for(int j=0; j<FileArray.length; j++){
new PrintStream(fout).println(FileArray[j] + ",");
}
}
private static class Task implements Runnable {
private int ID;
static Byte myByte = 0;
public Task(int index) {
this.ID = index;
}
#Override
public void run() {
long Start = System.nanoTime();
int Size1 = 10000000;
int Size2 = 2 * Size1;
int Size3 = Size1;
byte[] list1 = new byte[Size1];
byte[] list2 = new byte[Size2];
byte[] list3 = new byte[Size3];
for(int i=0; i<Size1; i++){
list1[i] = myByte;
}
for (int i = 0; i < Size2; i=i+2)
{
list2[i] = myByte;
}
for (int i = 0; i < Size3; i++)
{
byte temp = list1[i];
byte temp2 = list2[i];
list3[i] = temp;
list2[i] = temp;
list1[i] = temp2;
}
long Finish = System.nanoTime();
long Duration = Finish - Start;
FileArray[this.ID] = Duration;
TotalTime += Duration;
System.out.println("Individual Time " + this.ID + " \t: " + (Duration) + " nanoseconds");
if(Duration < FastestMemory){
FastestMemory = Duration;
}
if (Duration > SlowestMemory)
{
SlowestMemory = Duration;
}
}
}
}
C#:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using Amib.Threading;
using System.Diagnostics;
using System.IO;
using System.Runtime;
namespace ServerTesting
{
class Program
{
static long FastestMemory = 2000000000;
static long SlowestMemory = 0;
static long TotalTime = 0;
static int[] FileOutput;
static byte myByte = 56;
static System.IO.StreamWriter timeFile;
static System.IO.StreamWriter memoryFile;
static void Main(string[] args)
{
Console.WriteLine("Concurrent GC enabled: " + GCSettings.IsServerGC);
int Threads = Int32.Parse(args[1]);
int Iterations = Int32.Parse(args[0]);
timeFile = new System.IO.StreamWriter(Threads + "_" + Iterations + "_" + "time.csv");
FileOutput = new int[Iterations];
TestMemory(Threads, Iterations);
for (int j = 0; j < Iterations; j++)
{
timeFile.WriteLine(FileOutput[j] + ",");
}
timeFile.Close();
Console.ReadLine();
}
private static void TestMemory(int threads, int iterations)
{
SmartThreadPool pool = new SmartThreadPool();
pool.MaxThreads = threads;
Console.WriteLine("Launching " + iterations + " calculators with " + pool.MaxThreads + " threads");
for (int i = 0; i < iterations; i++)
{
pool.QueueWorkItem(new WorkItemCallback(MemoryIntensiveTask), i);
}
pool.WaitForIdle();
double avg = TotalTime/iterations;
Console.WriteLine("Avg Memory Time : " + avg);
Console.WriteLine("Fastest: " + FastestMemory + " ms");
Console.WriteLine("Slowest: " + SlowestMemory + " ms");
}
private static object MemoryIntensiveTask(object args)
{
DateTime start = DateTime.Now;
int Size1 = 10000000;
int Size2 = 2 * Size1;
int Size3 = Size1;
byte[] list1 = new byte[Size1];
byte[] list2 = new byte[Size2];
byte[] list3 = new byte[Size3];
for (int i = 0; i < Size1; i++)
{
list1[i] = myByte;
}
for (int i = 0; i < Size2; i = i + 2)
{
list2[i] = myByte;
}
for (int i = 0; i < Size3; i++)
{
byte temp = list1[i];
byte temp2 = list2[i];
list3[i] = temp;
list2[i] = temp;
list1[i] = temp2;
}
DateTime finish = DateTime.Now;
TimeSpan ts = finish - start;
long duration = ts.Milliseconds;
Console.WriteLine("Individual Time " + args + " \t: " + duration);
FileOutput[(int)args] = (int)duration;
TotalTime += duration;
if (duration < FastestMemory)
{
FastestMemory = duration;
}
if (duration > SlowestMemory)
{
SlowestMemory = duration;
}
return null;
}
}
}
You don't appear to be testing the threading frame work as much as you are testing how the language optimises un-optimised code.
Java is particular good at optimising pointless code, which I believe would explain the difference in the languages. As the number of threads grows, I suspect the bottle neck moves to how the GC performs or some thing else incidental to your test.
Java could also be slowing down as its not NUMA aware by default. Try running -XX:+UseNUMA However I suggest for maximum performance you should try to keep each process to a single numa region to avoid cross numa overhead.
You can also try this slightly optimise code which was 40% fast on my machine
import java.io.DataOutputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintStream;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class PoolDemo {
static long FastestMemory = 2000000000;
static long SlowestMemory = 0;
static long TotalTime;
static long[] FileArray;
static FileOutputStream fout;
public static void main(String[] args) throws InterruptedException, FileNotFoundException {
int Iterations = Integer.parseInt(args[0]);
int ThreadSize = Integer.parseInt(args[1]);
FileArray = new long[Iterations];
fout = new FileOutputStream("server_testing.csv");
// fixed pool, unlimited queue
ExecutorService service = Executors.newFixedThreadPool(ThreadSize);
//ThreadPoolExecutor executor = (ThreadPoolExecutor) service;
for (int i = 0; i < Iterations; i++) {
Task t = new Task(i);
service.execute(t);
}
service.shutdown();
service.awaitTermination(90, TimeUnit.SECONDS);
System.out.println("Fastest: " + FastestMemory);
System.out.println("Average: " + TotalTime / Iterations);
PrintStream ps = new PrintStream(fout);
for (long aFileArray : FileArray) {
ps.println(aFileArray + ",");
}
}
static class ThreadLocalBytes extends ThreadLocal<byte[]> {
private final int bytes;
ThreadLocalBytes(int bytes) {
this.bytes = bytes;
}
#Override
protected byte[] initialValue() {
return new byte[bytes];
}
}
private static class Task implements Runnable {
static final int Size1 = 10000000;
static final int Size2 = 2 * Size1;
static final int Size3 = Size1;
private int ID;
private static final ThreadLocalBytes list1b = new ThreadLocalBytes(Size1);
private static final ThreadLocalBytes list2b = new ThreadLocalBytes(Size2);
private static final ThreadLocalBytes list3b = new ThreadLocalBytes(Size3);
static byte myByte = 0;
public Task(int index) {
this.ID = index;
}
#Override
public void run() {
long Start = System.nanoTime();
byte[] list1 = list1b.get();
byte[] list2 = list2b.get();
byte[] list3 = list3b.get();
for (int i = 0; i < Size1; i++) {
list1[i] = myByte;
}
for (int i = 0; i < Size2; i = i + 2) {
list2[i] = myByte;
}
for (int i = 0; i < Size3; i++) {
byte temp = list1[i];
byte temp2 = list2[i];
list3[i] = temp;
list2[i] = temp;
list1[i] = temp2;
}
long Finish = System.nanoTime();
long Duration = Finish - Start;
FileArray[this.ID] = Duration;
TotalTime += Duration;
System.out.println("Individual Time " + this.ID + " \t: " + (Duration) + " nanoseconds");
if (Duration < FastestMemory) {
FastestMemory = Duration;
}
if (Duration > SlowestMemory) {
SlowestMemory = Duration;
}
}
}
}

Categories