Code Monkey home page Code Monkey logo

jactor's Introduction

jactor's People

Contributors

ccorsi avatar laforge49 avatar skunkiferous avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jactor's Issues

API Problems

I am very concerned that when creating an anonymous subclass of Binding, it is too easy to do unsafe things like call send from within acceptRequest. I find myself doing this, so I know it will happen. And the code seems to work, making it especially dangerous.

My solution is to pass internals in the processRequest method of Binding and to restrict the protected API of JBActor and Component. Methods that are unsafe to call in acceptRequest will then only be accessible via the internals parameter on processRequest.

It is a bit ugly, as now you will need to do a internals.send instead of just send. But it will eliminate a bunch of thread safety issues, so I think is is worth it.

Bug in sending to non-async actor

Go to https://github.com/laforge49/JActor/blob/master/src/test/java/org/agilewiki/jactor/multithreading/ResponsePrinterTest.java and look at the todo in test 4. The (commented out) code causes the test to hang.

This is the first time I've tested sending multiple requests from different threads to a mailbox. And it doesn't work. Fortunately it continues to fail after adding print statements, so it should not be a really hard bug to track down, but the bug is likely located in some of the more difficult code.

Drop ConcurrentRequest

Add a findParent method to JLPCActor:

public TargetActor findParent(Class parentClass);

Concurrent requests can now be handled by either a simple method call, or a call to the parent which is an instanceof a given class.

Atomic Requests

Some requests should be fully atomic, i.e. transactional. For this we need an atomic request, atomic binding and an atomic component.

rework timing tests

  1. calculation of response time (latency) is a bit naive but easily fixed.
  2. timings should remove the overhead of the test framework by first calculating that overhead without sending the messages being tested.
  3. processing time and latency should be reported in terms of CPU cycles.

API Change: Make Open a Request

JBActor calls the open(Internals) method the first time a non-initialization method is received. This is not thread safe, so we have a choice between making open an explicit request or using a synchronization lock. An ugly choice.

JActor does not use locks and that's important for performance, so we need to make open an initialization request. That's a big change and not a very good one, as it adds a line of code everywhere an actor is created. But necessary, methinks.

Initialization is always such a mess.

Simplify the RD class

We should drop the process method from the RD class--it is only there for historical reasons.

API betterment- Optimal number of threads for Async mailbox

Statement:
Consider the below code :

        // Please refer org.agilewiki.jactor.basics.Test5 for the complete program
        MailboxFactory mf = getMailboxFactory();
        Actor5 a = new Actor5();
        a.initialize(mf.createAsyncMailbox());
        Actor5 b = new Actor5();
        b.initialize(mf.createAsyncMailbox());
        Actor5 c = new Actor5();
        c.initialize(mf.createAsyncMailbox());
        a.delay = 10;
        c.delay = 10;
        a.delay = 10;
        final long t0 = System.currentTimeMillis();
        RP<Object> rc = new RP<Object>() {
            int c = 3;

            @Override
            public void processResponse(Object response) throws Exception {
                c -= 1;
                if (c == 0) {
                    long t1 = System.currentTimeMillis();
                    System.out.println("Time taken-->" + (t1 - t0));
                    rp.processResponse((t1 - t0) <= 30);
                }
            }
        };
        Delay.req.send(this, a, rc);
        Delay.req.send(this, b, rc);
        Delay.req.send(this, c, rc);

The timing test will yield best output for the following definition of MailboxFactory-

    MailboxFactory mailboxFactory = JAMailboxFactory.newMailboxFactory(3);  // creates 3 threads for 3 async mailboxes

Whereas, with 1 or 2 threads (JAMailboxFactory.newMailboxFactory(1) or JAMailboxFactory.newMailboxFactory(2)), it is not going yield optimal output.

Problem :
End user's program may be dynamic in nature. How about making the MailboxFactory initialization intelligent, so that based on a given problem it will spawn optimal number of threads automatically.

Exceptions not always caught

If you send a synchronous request rather than doing a call, and that request raises an exception, the exception is not handled properly.

JLCPActor Exception Handling Bug

While converting everything from components to JLPCActors, a bug was found in org.agilewiki.jactor.multithreadingTest.exceptions.ExceptionTest. Apparently the exception handler set in test case 4 is not being cleared in test case 5. (For the moment, test case 5 has been commented out.)

speedup

Eliminate the request and response wrappers by moving the code into the base Request class and by creating a base Response class.

Attempt to eliminate TargetActor

TargetActor is seemingly unnecessary. It was a device introduced to get Request to compile correctly. There may be a better way, especially considering the high-visibility of TargetActor in the API.

Replace ThreadManager with ExecutorService

It is time for JAThreadManager to become a full blown ExecutorService. This will allow the JAMailboxFactory constructor to take any ExecutorService as an argument. But more importantly, it will allow greater use of JAThreadManager.

speed up JAEventQueue

A small change to JAEventQueue should give us much better timings. Here's the code that needs improving:

public boolean acquireControl(EventQueue<E> eventQueue) {
    if (atomicControl.compareAndSet(null, eventQueue.getController())) {
        notEmpty = false;
        return true;
    }
    return false;
}

We need to add a faster check before the if statement:

public boolean acquireControl(EventQueue<E> eventQueue) {
    if (atomicConttrol.get() != null) || 
            atomicControl.compareAndSet(null, eventQueue.getController()) {
        notEmpty = false;
        return true;
    }
    return false;
}

Proposal for Actor and JLPCActor

We may be able to simplify things...

public interface Actor {
Mailbox mailbox();
Actor parent();
}

public class JLPCActor extends Actor {
public final Mailbox mailbox;
public final Actor parent;

public Mailbox mailbox() {
    return mailbox;
}

public Actor parent() {
    return parent;
}

public JLPCActor(Mailbox mailbox, Actor parent) {
    this.mailbox = mailbox;
    this.parent = parent;
}

}

Benchmark tests needed

The project contains a lot of unit tests, but no benchmarks supplied. As a result, it is hard to make sure the library is as fast as claimed.

Timeout for request

Hi,

Looks to me we could be able to reject request after timeout?

Thanks

Julius

Non-blocking Locks

The NBLock component will have two requests, Begin and End. Begin requests are added to a queue; End requests pop the queue.

If the queue is empty when a Begin request is received, it gets an immediate response. Otherwise it receives a response when the queue is popped and the Begin request is now on top.

To use the NBLock component, you send a Begin request (with a callback). Once the callback is invoked you have exclusive access to some resource, but when done you need to send an End request to free up the resource. Note that no threads are blocked while the response to a begin request is pending.

Examples

There is no link to examples using this library in the main page. Wiki with some code samples would be very helpful.

how to use jactor

hi,laforge49
I'm new to Jactor,I got code,and run the test ,It is fast.I read your document,but can not find a right way to use in my web app.
my web app is very simple,user input a task,every task run 10-100 second.I write a unit test such as blow
public class TaskTest {
//queuque to save taskids
LinkedBlockingQueue taskqueque=new LinkedBlockingQueue();
//flag,stop taskserver
boolean stop=false;

private ExecutorService taskExecutor= Executors.newFixedThreadPool(5);

@Before
public void setUp() throws Exception {
    //create 5 taks server
    for (int i = 0; i < 5; i++) {
        taskExecutor.submit( new Taskserver());         
    }
}

@Test
public void test() {
    int times=new Random().nextInt(50);
    System.out.println("run "+times+" tasks");
    for (int i = 0; i <times; i++) {
        //add new task to queque
        taskqueque.add(String.valueOf(i));
    }
    while(!taskqueque.isEmpty());
    stop=true;
    System.out.println("test over");
}
class Taskserver implements Runnable{


    @Override
    public void run() {
        while(!stop){
            try {
                String taskid=taskqueque.take();
                //sleep some times,simulate db read write 
                Thread.sleep(1000*new Random().nextInt(10));
                System.out.println("work over task "+taskid+" at thread"+Thread.currentThread().getName() );
            } catch (InterruptedException e) {

            }
        }

    }
}

}

can you give me a sample how to use jactor in this class? thank you very much.

Move JLPCActor.processRequest to Request

The moved method on Request<RETURN_RESULT, TARGET_ACTOR> would be

public abstract void processRequest(TARGET_ACTOR targetActor, RP<RETURN_RESULT> rp) throws Exception;

By moving this method, we no longer need to examine the class of the Request.

Exposing an ExecutorService

JACTOR api presently doesn't have an executor service. Pivotal point of present architecture is the JAThreadManager class. This can be refactored and converted into a high performance executor service. On the other hand end users should be able to plug and play their own executor service too.

Comparing classes with == is slow and incorrect

At a number of places in the codebase == is used to compare classes for equality, which is both slow and incorrect. It is incorrect because it wouldn't work with proxies where a new proxy sub-class is created at runtime. Examples: CGLIB proxy, JVM proxy, Spring-AOP integration etc.

A possible fix is to use instanceof where the exact reference class is known beforehand, or to use class1.isAssignableFrom(class2). In a single-threaded experiment I did on a quad-core Intel i7 based Macbook Pro, I got the following mean numbers with a warmed JVM:

class1 == class2                        | 2.747921 us
obj instanceof class1                   | 2.743640 us
class1.isAssignableFrom(class2)         | 2.741118 us
obj.getClass().isAssignableFrom(class2) | 2.781485 us

Release binaries and sources Maven central

Not really a big deal in the short term, but it would be great if the binaries and sources could be found in Maven central.

Another suggestion is to change the groupId to a fqn (org.jactor, etc) and have it lower-case, which seems to be a common Maven practice nowadays.

PS: Quite pleased to have come across this project.

How to send a request to an actor without blocking?

Hi...
I'm new to JActor2. Is there any way to send a request to an actor without blocking? I don't need any return value and I don't want to wait till the processing ends. Something like kilim's Mailbox.putnb(...);
Thank you!

Factory => FactoryRegistry

Factory is really a registry of ActorFactory's.

Factory => FactoryRegistry
JAFactory => JAFactoryRegistry
JAFactoryFactory => JAFactoryRegistryFactory.

Exception handling bug

In the JFile project, Deserializer throws an exception when an unrecognized transaction is encountered. The exception is lost and all you see is an obscure null pointer exception in JActor.

I think the problem is because of the use of 3 mailboxes, the first and third being async and the second being commandeered by the first. Deserializer is the third and, when the exception is passed back is when the error occurs.

Binding classes should constrain the request type

By adding bounds to the request types of the binding classes we can constrain the types to what are reasonable. For example,

abstract public class InitializationMethodBinding<REQUEST_TYPE, RESPONSE_TYPE>
extends MethodBinding<REQUEST_TYPE, RESPONSE_TYPE> {

becomes

abstract public class InitializationMethodBinding
<REQUEST_TYPE extends InitializationRequest<RESPONSE_TYPE>, RESPONSE_TYPE>
extends MethodBinding<REQUEST_TYPE, RESPONSE_TYPE> {

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.