#!/bin/bash # This line is for starting from mac os icon double click cd "$( dirname "$0" )" ## V1.3: The -XX:SoftRefLRUPolicyMSPerMB=0 flag got lost! Back in now. ## This flag defaults to 1000, and can cause memory leaks. ## V1.2: We now play with -XX:TargetSurvivorRatio=n to reduce waste in new, permitting more ## space to be used # Configurables: # -d32 is for heap size up to 2.5gb. # Change to "-d64 XX:+UseCompressedOops" if you use more. # ** Mention that flag specifically, do not rely on it being autoset. # ** Known and documented JVM bug -- https://forums.oracle.com/forums/thread.jspa?messageID=10017916 # CMSInitiatingOccupancyFraction: Determine how frequently to do a full CMS # sweep. Lines like: # 1308.811: [Full GC (System) ... # indicate "CMS failure". This means a full "pause the app and full GC". # Too many: Lower the percentage. # Too low a percentage: More CMS full sweeps (looks like:) # 171.808: [GC [1 CMS-initial-mark: 212329K(367040K)] ... # and usually many, many more lines after that, ending with # 173.156: [CMS-concurrent-reset: 0.003/0.003 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] # Note the time stamps between those. # -XX:+UseAdaptiveGCBoundary -- apparently, adjust the boundary between new and tenured as needed. # Nice to see; did not know about it before. # Sadly, it seems to have no effect. # -XX:+CMSIncrementalMode: Tells the garbage collector to break the job into many small parts. # May result in better performance. Essential on systems with few cores. # Memory tuning: # Command line controls total heap, and "new". "Tenured" is the difference. # Bigger "new": Less frequent collections. # These numbers are in "Megabytes", the java "m" suffix. # The rule of memory tuning: # SurvivorSpace * (SurvivorRatio + 2) = New # ("SurvivorSpace" is twice the actual surviving threshold.) # SurvivorSpace * SurvivorRatio = Eden. # Two additional survivor spaces are used to copy surviving objects across minor collections. # MAX: Maximum heap space used. # Does not include permanent (byte/compiled code) # Does not include JVM overhead MAX=800 # Tenured: Desired long-term storage space # Will vary based on mods, and "loaded chunks" # -- how many parties of players close to each other. # # Starting assumption: 250 for 1 person, plus 50 per group # of players near each other. # # That is a guess. Please report what numbers work for your server. Tenured=350 # Most important tuning number. Survivor. # Making this higher: Fewer full collections, but more wasted space. # During startup, expect this to overflow frequently. # Dynamic maps wants this at least 100, preferrably 125. # Actual space allocated is 2 spaces, each one twice this size. # "waste/overhead" will be two about to three times this number. # *** Maximum of 1/6rd of "new" # Pay attention to the tenuring distribution logs. # *** This should be enough for generation 3 95%+ of the time. *** # ** TOO SMALL WILL KILL YOUR GARBAGE COLLECTION ** # ** TOO BIG WILL WASTE SPACE ** SurvivorCopySize=12 # Survivor target ratio. Java defaults to 50%, which wastes a lot of space. If you know how much # you need (see below), you can set this value higher; this gives less waste and "better performance". TargetSurvivorRatio=90 ## Notes on "SurvivorCopySize": # Flying around in creative mode, in already generated chunks will want # at least 30-35, preferrably 40 meg. # Standing around, single player, can be happy with less than 1. # Even in Mystcraft, with massive amounts of decay everywhere, 95% of the time 1 meg suffices. # Moving around a little, doing basic building/digging, about 3. # # The rule: You want to see "new threshold 4 (max 4)" most of the time. # The total value at age three -- # - age 3: 36712 bytes, 5897520 total # should be less than this 95% of the time. # 12 meg is more than enough for one person with EBXL, Mystcraft, Twilight Forest, # and Custom Ore Gen. Even in EBXL's extreme jungle with Mystcraft's decay littering the ground. # # The single biggest factor is chunks loaded; that will depend more on parties than on players, # and the speed at which they move. Adjust to your server, and your mods. # # Single player won't need that much. Really. # Second most important tuning. Eden. # Making this bigger means less frequent small collections. # General rule: Make this as big as your memory can handle. # Must be at least 2x SurvivorCopySize. Java requires it to be # an integer multiple of that value. desiredEden=100 # Summary: Approximately desiredEden, plus 2 times Survivor, # plus 100, will be used by java to start the heap. Up to a max of MAX. # Script will attempt to ensure at least Tenured space exist; # should exit with a message if it cannot. # # In theory, Java will allocate extra space to new or tenured as needed. # In practice, I've never seen it increase "new". # ** Update! Just found a config flag conflict, and updated. # I suspect I've now gotten it to increase "new" as demand goes up. # # See the bottom of the config section for more. # If your shell cannot do math, replace these with an appropriate constant MaxNew=$(($MAX - $Tenured)) ## Survivor=$((2 * $SurvivorCopySize)) ## Working with survivor target. "2" is for 50%. For 90%, it's much closer to 1. ## What we want is 100 / target percentage, as the ratio instead of 2. ## For integer only shell math, we re-write as (100 * survivor) / target, which gives us ## close integer to the desired result -- as close as we can get in the shell. Survivor=$(( ($SurvivorCopySize * 100 ) / $TargetSurvivorRatio )) ## Equally, the "3" in sanity test is from 3 bins -- two survivors, one eden. ## But that does NOT change here -- it's still the sanity test lower limit. sanityTest=$((3 * $Survivor)) if [ $sanityTest -gt $MaxNew ] then echo Memory config error >& 2 exit 1 fi # We cannot use more than MaxNew. # The idea: # 1. Find the multiple of Survivor that is bigger than S and less than MN. # 2. Determine survivor ratio from that. Subtract 2 (java.) # 3. Specify -Xmn for new, and survivor ratio, to set eden and new. # "New" will be Eden plus 2* Survivor. # MaxRatio -- what the ratio is if we use all of maxnew. MaxRatio=$(( ($MaxNew / $Survivor) - 2 )) # DesiredRatio -- what the ratio is based on declared eden space # There is no "-2" here -- this will allocate eden plus 2* survivor. desiredRatio=$(( ($desiredEden / $Survivor) )) # SurvivorSpace * (SurvivorRatio + 2) = New # Now check for "desired Eden". If survivor is not an exact multiple of DE, # then we have just rounded down. Test for this, and if so, see if we can # raise it up (watch out for maxnew) ## TODO! FIXME! This is a cheap approximation if ( [ $(( $desiredRatio + 1 )) -le $MaxRatio ] ) then desiredRatio=$(( $desiredRatio + 1 )) fi desiredNew=$(($Survivor * ($desiredRatio + 2) )) biggerNew=$(($Survivor * ($MaxRatio + 2) )) echo Debug: Max ratio $MaxRatio, desiredRatio $desiredRatio echo Debug: biggerNew $biggerNew, should be less than MaxNew $MaxNew echo Debug: desired eden $desiredEden, survivor $Survivor, actual new $desiredNew # desiredNew: Gives an eden up to, not bigger, than desiredEden. # biggerNew: Gives an eden at least as big as desiredEden. # FIXME: DesiredNew / ratio should be smallest at least as big as desiredEden # This means, if less, then add 1 to ratio and add to new. # # "Bigger" assigns ALL non-tenured memory to new. # Q: Desired numbers? Bigger/Max numbers? # Choose one of these pairs # New space is small -- specified eden. NEW=$desiredNew RATIO=$desiredRatio # Tenured is small -- specified tenured space. ## Should Not Be Needed -- "NewSize" and "MaxNewSize" specified separately. # In theory, Java should now adjust new as neeed. #NEW=$biggerNew #RATIO=$MaxRatio START=$(($NEW + 100)) ## TESTME: Does "MaxNewSize" matter if we have adaptive GC boundary? Does it hurt? exec java \ -d32 -server \ -Xms${START}m -Xmx${MAX}m \ -XX:NewSize=${NEW}m -XX:MaxNewSize=${MaxNew}m \ -XX:+UseAdaptiveGCBoundary \ -XX:SurvivorRatio=$RATIO \ -XX:TargetSurvivorRatio=$TargetSurvivorRatio \ -XX:CompileThreshold=3000 \ -XX:CMSInitiatingOccupancyFraction=95 \ \ -XX:SoftRefLRUPolicyMSPerMB=0 \ -XX:MaxPermSize=150m \ -XX:+UseConcMarkSweepGC -XX:+UseParNewGC \ -XX:MaxHeapFreeRatio=20 \ -XX:MinHeapFreeRatio=15 \ -XX:MaxTenuringThreshold=4 \ -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution \ -XX:+PrintCommandLineFlags -XX:+PrintGCDetails -Xloggc:GC.log \ -jar new_server.jar nogui 147test # The last word of that exec statement -- '147test' -- is just something that shows up in # the process list, so I can tell which process is which server (each copy of this script # has a different name in that field).