Soft async enforcement for locking methods (discussion)

Discussion in 'Plugin Development' started by RawCode, Apr 16, 2014.

Thread Status:
Not open for further replies.
  1. Offline

    RawCode

    With UUID hysteria i noticed one "bad" thing - users, do not understand what locking methods are and how they effect performance. (also nobody read annoncements from front page of bukkit.org)

    I decided to post one more thread nobody will ever bother to read about perfomance effects of locking methods:

    sample code with code running in sync and async to main thread (standalone source)
    Code:
    	static private Thread mainref = null;
    
    	static public void RandomLockingMethodAPI(final boolean Forced) throws Throwable
    	{
    		
    		if (Thread.currentThread() == mainref && Forced)
    			new Thread()
    		{
    			public void run()
    			{
    				try
    				{
    					RandomLockingMethodAPI(Forced);
    				} catch (Throwable e){}
    			}
    		}.start();
    		else
    			RandomLockingMethodImpl();
    	}
    	
    	static public void RandomLockingMethodImpl() throws Throwable
    	{
    		Thread.sleep(1000);
    		System.out.println("Message second later from " + Thread.currentThread());
    	}
    	
    	static public void main(String[] args) throws Throwable {
    		
    		//main thread lockguard sample for bukkit discussion thread
    		
    		mainref = Thread.currentThread();
    		RandomLockingMethodAPI(false);
    		System.out.println("Message now");
    		
    	}
    
    RandomLockingMethodAPI(false) will execute locking action inside main thread;
    RandomLockingMethodAPI(true) will execute method in separate new thread, but only if this action actually required;

    Same code can be used to detect invocations of locking API methods from Bukkit, comments and annotations mostly ignored, but "crashing" exception will be usefull and helpfull.
    If some server admins still want to use plugin - they can disable this feature from config.
     
  2. Offline

    Rocoty

    RawCode Don't you mean blocking method? Never heard of locking method before. The closest I can imagine to a locking method is a method that takes hold of an object's intristic lock, i.e. a synchronized method. But that's not really called a locking method. So, according to how you explain and put the code you are talking about a blocking method. Am I right?
     
  3. Offline

    RawCode

    try executing code provided
     
  4. Offline

    Rocoty

    RawCode I am talking semantics. I know what happens when executing the above code. The thread executing it will block thus can't do further operations for at least 1000 milliseconds. I was just prompting to use the correct terminology. Read my previous post thoroughly please.
     
  5. Offline

    TheHandfish

    Isn't async evil?
     
  6. Offline

    Garris0n

    Not sure what you mean by that. Most of Bukkit is not thread safe, but that doesn't make it "evil".
     
  7. Offline

    Rocoty

    TheHandfish Why do you think that? Any code is dangerous if you don't utilise it correctly. So if you build a concurrent application/plugin in a way in which problems are prone to arise, then yes, it is dangerous business. But I wouldn't call it evil...
     
  8. TheHandfish Like statics, they're evil if you're a beginner.
     
  9. Offline

    Rocoty

    AdamQpzm Yet most beginners seem to use them as if nothing else exists. *sigh*
     
    AdamQpzm likes this.
  10. Offline

    TheHandfish

    ?

    OOH I'm thinking about .sleep()'ing threads. My bad.
     
  11. TheHandfish Again, not evil. Just not recommended when using Bukkit. Sleeping in the main thread, however, is evil.
     
  12. Offline

    NathanWolf

    RawCode Can't you do the same thing with the Bukkit scheduler? As in, make an async task and then use a sync task inside of it to do any API work you need to do... standard practice?

    And what does this have to do with UUIDs.. ? I know we have to call out to a Mojang server for legacy name lookups, but Bukkit does that for us. I don't expect plugin devs are suddenly going to have to start writing async code- what I am missing?

    Could you link to the post you're talking about? If you really want people to read it, that'd help- I may be looking at the wrong one.

    Rocoty Yeah, I think this is more "blocking" than "locking" - when I think "locking" I think synchronization, as in one thread blocking another (via locking a mutex or whatever underlying mechanic) while it finishes work.
     
  13. NathanWolf I would imagine he was referring to the UUID PSA
     
  14. Offline

    NathanWolf


    I imagined that as well, and read through that post. I could be daft, but I don't see anything in there that says "devs will now need to regularly use aysnc tasks", or otherwise how this relates.

    I mean, I'm guessing it's this:

    But, ok, so you can use BukkitScheduler for that if you need it, and probably shouldn't be architecting something complex around a temporary solution anyway. Am I still missing something?
     
  15. Offline

    Rocoty

    NathanWolf No, I think you're right. I haven't experienced any blocking when working with UUIDs in any way (I have never used getOfflinePlayer(UUID)), so I think Bukkit caches the players' UUIDs when they join.
     
  16. NathanWolf I believe it's not actually about UUIDs per se, it was just about how he'd noticed it because of the changes. I personally have noticed that, since the UUID stuff, questions regarding querying databases and similar have increased, which is then recommended to do it async, etc. I'm not overly surprised that UUIDs lead to external database querying questions.
     
  17. Offline

    ZerothAngel

    As of 1.7.8? 1.7.9? Server#getOfflinePlayer(UUID) no longer blocks. It's the other method now, Server#getOfflinePlayer(String) that potentially blocks.

    While the CraftBukkit-side of Server#getOfflinePlayer(String) looks reasonably thread-safe, it ends up calling Mojang's UserCache class for UUID resolution/caching (this class is also responsible for the usercache.json). Unfortunately, at first glance, this class does not appear to be thread-safe... someone please correct me, if I'm wrong.

    Therefore calling it from any other thread besides the main thread may cause problems.

    So if you need to get the UUID of an offline player and you don't want to block the main thread, your best bet is to probably use something like evilmidget38's UUIDFetcher class in an async thread. Once you get the results back, you then use BukkitScheduler to execute the rest of the command or whatever in the main thread.
     
  18. Because i did not write such, in order to focus on other aspects (Edit: :p). In my opinion asynchronous command handling will "explode" in comparison, because looking up offline players names and/or uuids is not always acceptable to do with a local cache, e.g. thinking of new players not knowing the old players - would you expect them to ask "who is Gandalf on this server?"? So such lookups will have to be asynchronous rather, which also means other things, like delaying or even denying actions until lookup is done, which can take seconds easily. Single-threaded servers with several plugins using asynchronous lookups will also "profit" from those plugins likely not using the same thread for lookup.
     
  19. Offline

    RawCode

    not only UUID stuff is blocking, i read random plugins from time to time, many developers do not understand how disk\net IO works and execute it in main thread - this result in generic server slowdown.

    NathanWolf
    you shoud open bukkit tasks source code before posting something like that.


    since nobody understands - i implemented code that does not require bukkit server to run in order to show how sync and async tasks works.
     
Thread Status:
Not open for further replies.

Share This Page