ThreadLocal and generics - performance

I would like to create some thread local static arrays, using generics. The size of the array depends on the type. I'm trying to do something like:
type LeftoverPool private () =
static let instance = new ThreadLocal<'T[]>(fun () -> Array.zeroCreate (Vector<'T>.Count))
static member Instance = instance.Value
But that constrains T to int.
I've tried making the instance method generic, or the type, but can't get this to work.

From a type perspective, what you're trying to do at the moment really doesn't make sense.
You have a static property Instance but its type its completely ambiguous because it's impossible to resolve the meaning of 'T. In order to do this you need to propagate the type annotation up to the containing type, e.g.:
type LeftoverPool<'T> private () =
static let instance = new ThreadLocal<'T[]>(fun () -> Array.zeroCreate<'T> (Vector<'T>.Count))
static member Instance = instance.Value

Create a generic type, then its static members will be specific for the type. Resharper (for C#) will issue a warning, but here is what you really need.
Also, you need to benchmark ThreadStatic vs ThreadLocal as well, the later is effectively a pool of objects and it my have some lookup overheads compared to thread-static fields that just reside in a special memory region for each thread.
Update
I was going to test it for a while anyway, here is the code and output. ThreadStatic is faster.
[TestFixture]
public class BuffersTests {
public static class LocalBuffers<T> {
[ThreadStatic]
private static T[] _threadStatic;
private static ThreadLocal<T[]> _threadLocal = new ThreadLocal<T[]>(() => new T[10]);
public static T[] ThreadStatic => _threadStatic ?? (_threadStatic = new T[10]);
public static T[] ThreadLocal => _threadLocal.Value;
}
[Test, Ignore]
public void ThreadStaticVsThreadLocal() {
for (int r = 0; r < 10; r++) {
const int count = 100000000;
var sw = new Stopwatch();
sw.Restart();
var sum = 0L;
for (var i = 0; i < count; i++) {
var buffer = LocalBuffers<int>.ThreadStatic;
buffer[0] = 123;
sum += buffer[0] + buffer[1];
}
Assert.IsTrue(sum > 0);
sw.Stop();
Console.WriteLine($"ThreadStatic {sw.ElapsedMilliseconds}");
sw.Restart();
sum = 0L;
for (var i = 0; i < count; i++) {
var buffer = LocalBuffers<int>.ThreadLocal;
buffer[0] = 123;
sum += buffer[0] + buffer[1];
}
Assert.IsTrue(sum > 0);
sw.Stop();
Console.WriteLine($"ThreadLocal {sw.ElapsedMilliseconds}");
Console.WriteLine("---------------------");
}
}
}
ThreadStatic 1286
ThreadLocal 1860
---------------------
ThreadStatic 1312
ThreadLocal 1849
---------------------
ThreadStatic 1334
ThreadLocal 1933
---------------------
ThreadStatic 1390
ThreadLocal 2076
---------------------
ThreadStatic 1438
ThreadLocal 2088
---------------------
ThreadStatic 1295
ThreadLocal 2216
---------------------
ThreadStatic 1317
ThreadLocal 1972
---------------------
ThreadStatic 1380
ThreadLocal 1943
---------------------
ThreadStatic 1410
ThreadLocal 1970
---------------------

Related

how to get multi properties's mean values using java8 stream?

there's one Object
#Data
class ScoreInfo{
String id;
float cove_score;
float theam_score;
float content_score;
float teach_score;
Date create_date;
ScoreInfoP scoreInfoP;
}
and ScoreInfoP is :
#Data
class ScoreInfoP{
String stream_sn;
String anchor_id;
String create_by;
}
sourceList is a list of ScoreInfo,I want to get cove_score,theam_score,content_score,teach_score's mean values,group by scoreInfoP property and return four mean values for each of these properties.
I can get only one mean value using such code:
Map<ScoreInfoP, Double> meanForCoveScore = sourceList.stream().collect(Collectors.groupingBy(ScoreInfo::getScoreInfoP,
Collectors.averagingDouble(ScoreInfo::getCove_score)));
I want to learn how to get four mean values using java8 or any easier way you suggest achieving this.
Waiting here for your generous help.
There isn't anything build-in for this, but it's not that complicated to build a custom Collector for that...
Map<String, List<Float>> result = Arrays.asList(first, second)
.stream()
.collect(Collectors.groupingBy(
x -> x.getScoreInfoP().getAnchorId(),
Collector.of(
() -> new float[5],
(a, x) -> {
a[0] += x.getCoveScore();
a[1] += x.getTheamScore();
a[2] += x.getTeachScore();
a[3] += x.getContentScore();
a[4]++;
},
(left, right) -> {
for (int i = 0; i < 4; ++i) {
left[i] += right[i];
}
return left;
}, x -> Arrays.asList(x[0] / x[4], x[1] / x[4], x[2] / x[4], x[3] / x[4]))
));
System.out.println(result);
I actually groupBy here on ScoreInfoP#anchorId; but you can do it on ScoreInfoP - for that you need to change x -> x.getScoreInfoP().getAnchorId() to x -> x.getScoreInfoP(). But obviously ScoreInfoP needs to override hashCode and equals.
As I said in the comment you should use a proper result class.
class ScoreInfoAverage {
private float cove_score;
private float theam_score;
private float content_score;
private float teach_score;
// ctor, getter, setter
}
Then you can use a custom Collector:
public static Collector<ScoreInfo, ?, ScoreInfoAverage> scoreInfoToAverage() {
class ScoreInfoAccumulator {
private DoubleSummaryStatistics cove_score = new DoubleSummaryStatistics();
private DoubleSummaryStatistics theam_score = new DoubleSummaryStatistics();
private DoubleSummaryStatistics content_score = new DoubleSummaryStatistics();
private DoubleSummaryStatistics teach_score = new DoubleSummaryStatistics();
public void add(ScoreInfo si) {
cove_score.accept(si.cove_score);
theam_score.accept(si.theam_score);
content_score.accept(si.content_score);
teach_score.accept(si.teach_score);
}
public ScoreInfoAccumulator combine(ScoreInfoAccumulator sia) {
cove_score.combine(sia.cove_score);
theam_score.combine(sia.theam_score);
content_score.combine(sia.content_score);
teach_score.combine(sia.teach_score);
return this;
}
public ScoreInfoAverage average() {
return new ScoreInfoAverage((float) cove_score.getAverage(),
(float) theam_score.getAverage(), (float) content_score.getAverage(),
(float) teach_score.getAverage());
}
}
return Collector.of(ScoreInfoAccumulator::new, ScoreInfoAccumulator::add,
ScoreInfoAccumulator::combine, ScoreInfoAccumulator::average);
}
Last but not least you add your Collector to the downstream:
Map<ScoreInfoP, ScoreInfoAverage> collect = scoreInfos.stream()
.collect(Collectors.groupingBy(ScoreInfo::getScoreInfoP, scoreInfoToAverage()));

FCFS inside memory list

Hi i am new in java programing. I've created a program to allocate 20 block inside 10 memory.
Here's the code
import java.util.*;
import java.io.*;
public class BestFit
{
private int[] job;//f
private int[] memBlock;//b
private int[] jobStatus;
private int[] jobAT;
static private int[] memTaken;
static int[] ff;
private int[] jobCC;
private int[] ArrivalTime;
private int[] waitingTime;
private int[] turnaroundTime;
public BestFit()
{
job = new int[]{5040,4600,1060,1950,6950,6410,2960,3070,2770,7790,5680,9150,7880,3870,7160,8880,4410,6130,6750,2560};
memBlock = new int[]{4400,6200,9300,1000,4200,8200,4600,3700,6300,2900};
memTaken = new int[20];
ff = new int[20];//to store no. of block that used by particular file
jobCC = new int[]{2,8,10,1,10,8,4,2,6,7,1,1,1,8,8,2,5,7,6,7};//cpu cycle
ArrivalTime = new int[]{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20};
waitingTime = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
turnaroundTime = new int[]{0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
}
public void BestFitAlgo()
{
int[] frag = new int[25];
int i,j,nb,nf,sizeDifference;
int lowest = 10000;
nf = 20;
nb = 10;
int startTime = 1;
int complete = 1;
int totalTime = 1;
int waitTime;
int tTime = 1;
Arrays.sort(memBlock);
for (i=0;i<nf;i++)
{
if (complete != 20)
{
for (j=0;j<nb;j++)
{
sizeDifference = memBlock[j] - job[i];
if (sizeDifference>=0)
if (lowest>sizeDifference)
{
ff[i] = j;//no of block = j
lowest = sizeDifference;
complete++;
System.out.println("Job: "+i+" is added to block: "+ff[i]+" and being process");
for (int k = 1;k<jobCC[i];k++)
{
startTime++;
}
if(startTime == jobCC[i])
{
waitingTime[i] = tTime - ArrivalTime[i];
turnaroundTime[i] = jobCC[i] + waitingTime[i];
System.out.println("Job: "+i+" is fully processed.Block: "+ff[i]+" is free");
System.out.println("Arrival Time: "+ArrivalTime[i]);
System.out.println("Start time: "+totalTime);
System.out.println("CPU cycle: "+jobCC[i]);
totalTime +=startTime;
startTime = 1;
tTime = totalTime;
System.out.println("Waiting time: "+waitingTime[i]);
System.out.println("Turnaround time: "+turnaroundTime[i]+"\n");
}
}
}
}
frag[i]=lowest;
lowest = 10000;
}
System.out.println("File No:\tFile_Size:\tBlock_No:\tBlock_Size:\tFragment");
for (i=0;i<nf&&ff[i]!=0;i++)
{
System.out.println(i+"\t\t"+job[i]+"\t\t"+ff[i]+"\t\t"+memBlock[ff[i]]+"\t\t"+frag[i]);
}
System.out.println("\nTotal time: "+totalTime);
}
public static void main (String[] args)
{
BestFit b = new BestFit();
b.BestFitAlgo();
}
}
For now the job can be allocated to the memory block by fcfs but the problem now is the next job wont be able to enter the memory list ( where all the block) until the previous job is done. So there are 9 free memory block everytime a job enter.
How do i make it so that job can enter the block simultaneously (with the condition the desired mem block is not occupied and based on arrival time).
I know how fcfs work but that is with only 1 memory block. I've been googling all day trying to find how fcfs work in multiple memory block but no avail.
I hope anyone can help me to understand how it work and maybe a hint on how to implement in in coding.
Thanks in advance
EDIT: i put my code instead so anyone can get a clear view of my problem.

Repeated overriding of functional interface's abstract method?

I have a functional interface in Java 8:
public interface IFuncLambda1 {
public int someInt();
}
in main:
IFuncLambda1 iFuncL1 = () -> 5;
System.out.println("\niFuncL1.someInt: " + iFuncL1.someInt());
iFuncL1 = () -> 1;
System.out.println("iFuncL1.someInt: " + iFuncL1.someInt());
Running this will yield:
iFuncL1.someInt: 5
iFuncL1.someInt: 1
Is this functionality OK as it is? Is it intended?
If the overriding would be done in an implementing class, and the implementation would change at some point, then in every place that that method is called, the behaviour would be the same, we would have consistency. But if I change the behaviour/implementation through lambda expressions like in the example, the behaviour will only be valid til the next change, later on in the flow. This feels unreliable and hard to follow.
EDIT:
#assylias I don't see how someInt() has its behaviour changed...
What if I added a param to someInt and have this code:
IFuncLambda1 iFuncL1 = (x) -> x - 1;
System.out.println("\niFuncL1.someInt: " + iFuncL1.someInt(var));
iFuncL1 = (x) -> x + 1;
System.out.println("iFuncL1.someInt: " + iFuncL1.someInt(var));
with var being a final even, how would you re-write that with classes?
In your example, () -> 5 is one object and () -> 1 is another object. You happen to use the same variable to refer to them but that is just how references work in Java.
By the way it behaves exactly the same way as if you had used anonymous classes:
IFuncLambda1 iFuncL1 = new IFuncLambda1() { public int someInt() { return 5; } };
System.out.println("\niFuncL1.someInt: " + iFuncL1.someInt());
iFuncL1 = new IFuncLambda1() { public int someInt() { return 1; } };
System.out.println("iFuncL1.someInt: " + iFuncL1.someInt());
Or using "normal" classes:
public static class A implements IFuncLambda1 {
private final int i;
public A(int i) { this.i = i; }
public int someInt() { return i; }
}
IFuncLambda1 iFuncL1 = new A(5);
System.out.println("\niFuncL1.someInt: " + iFuncL1.someInt());
iFuncL1 = new A(1);
System.out.println("iFuncL1.someInt: " + iFuncL1.someInt());
There again there are two instances of A but you lose the reference to the first instance when you reassign iFuncL1.

Generics around Entityframework DbContext causes performance degradation?

I wrote a simple import/export application that transforms data from source->destination using EntityFramework and AutoMapper. It basically:
selects batchSize of records from the source table
'maps' data from source->destination entity
add new destination entities to destination table and saves context
I move around 500k records in under 5 minutes. After I refactored the code using generics the performance drops drastically to 250 records in 5 minutes.
Are my delegates that return DbSet<T> properties on the DbContext causing these problems? Or is something else going on?
Fast non-generic code:
public class Importer
{
public void ImportAddress()
{
const int batchSize = 50;
int done = 0;
var src = new SourceDbContext();
var count = src.Addresses.Count();
while (done < count)
{
using (var dest = new DestinationDbContext())
{
var list = src.Addresses.OrderBy(x => x.AddressId).Skip(done).Take(batchSize).ToList();
list.ForEach(x => dest.Address.Add(Mapper.Map<Addresses, Address>(x)));
done += batchSize;
dest.SaveChanges();
}
}
src.Dispose();
}
}
(Very) slow generic code:
public class Importer<TSourceContext, TDestinationContext>
where TSourceContext : DbContext
where TDestinationContext : DbContext
{
public void Import<TSourceEntity, TSourceOrder, TDestinationEntity>(Func<TSourceContext, DbSet<TSourceEntity>> getSourceSet, Func<TDestinationContext, DbSet<TDestinationEntity>> getDestinationSet, Func<TSourceEntity, TSourceOrder> getOrderBy)
where TSourceEntity : class
where TDestinationEntity : class
{
const int batchSize = 50;
int done = 0;
var ctx = Activator.CreateInstance<TSourceContext>();
//Does this getSourceSet delegate cause problems perhaps?
//Added this
var set = getSourceSet(ctx);
var count = set.Count();
while (done < count)
{
using (var dctx = Activator.CreateInstance<TDestinationContext>())
{
var list = set.OrderBy(getOrderBy).Skip(done).Take(batchSize).ToList();
//Or is the db-side paging mechanism broken by the getSourceSet delegate?
//Added this
var destSet = getDestinationSet(dctx);
list.ForEach(x => destSet.Add(Mapper.Map<TSourceEntity, TDestinationEntity>(x)));
done += batchSize;
dctx.SaveChanges();
}
}
ctx.Dispose();
}
}
Problem is invocation of the Func delegates you're doing a lot. Cache the resulting values in variables and it'll be fine.

How to execute multiple tests in one method?

I'm new to the Visual Studio Unit Testing Framework. I've dabbled a little in XUnit, though (DUnit to be specific).
I don't know why the following tests are failing. Based on my C# code (exhibit A), I would think my tests (exhibit B) would pass with the proverbial flying colors.
[EXHIBIT A - Pertinent code]
public class MessageClass
{
private int _messageTypeCode = 0;
private int _messageTypeSubcode;
private int _messageSequenceNumber;
private string _messageText;
public MessageClass()
{
this._messageTypeCode = 0;
this._messageTypeSubcode = 0;
this._messageSequenceNumber = 0;
this._messageText = string.Empty;
}
public void SetMessageTypeSubcode(int AMessageTypeSubcode)
{
int iMsgTypeSubCode = AMessageTypeSubcode;
if (iMsgTypeSubCode > 9999)
{
iMsgTypeSubCode = 9999;
}
else if (iMsgTypeSubCode < 0)
{
iMsgTypeSubCode = 42;
}
_messageTypeSubcode = AMessageTypeSubcode;
}
public int MessageTypeSubcode()
{
return _messageTypeSubcode;
}
[EXHIBIT B - Test code in the corresponding MessageClassTest]
[TestMethod()]
public void SetMessageTypeSubcodeTest()
{
int AMessageTypeSubcode;
// Should I put this class instantiation in MyTestInitialize?
MessageClass target = new MessageClass();
// Test 1
AMessageTypeSubcode = 0;
target.SetMessageTypeSubcode(AMessageTypeSubcode);
Assert.AreEqual(AMessageTypeSubcode, target.MessageTypeSubcode());
// Test 2 - 10000 is too much
AMessageTypeSubcode = 12345;
target.SetMessageTypeSubcode(AMessageTypeSubcode);
Assert.AreEqual(9999, target.MessageTypeSubcode());
// Test 3 - val must be positive
AMessageTypeSubcode = -77;
target.SetMessageTypeSubcode(AMessageTypeSubcode);
Assert.AreEqual(42, target.MessageTypeSubcode());
}
... It is failing on the second test. Having set the val higher than the cutoff (9999), it should be assigned that (9999) rather than 12345.
As I said, I'm new to Visual Studio Unit Testing Framework; is it not possible to have more than one test in a TestMethod? Or do I need to do something like call flush() or finish() or close() or reset() or something?
The tests are failing because the test should fail. Your method is incorrect:
_messageTypeSubcode = AMessageTypeSubcode;
Should be:
_messageTypeSubcode = iMsgTypeSubCode ;

Resources