Yet Another New PC (3)

A few days ago, I pretty much finished setting up my new computer. I still don’t have a SATA cable with a right-angled plug, so I can’t close the case yet, but that’s just cosmetics. There are also still a few kinks with access rights and different users, I’m having trouble printing from my non-administrator accounts, and the mouse button settings aren’t exactly as I would like them, for example, but I just didn’t care enough to fix that. I have already made a Ghost backup, though, so reinstalling everything will be much easier in the future. I’ll probably make another backup soon when I’ve fixed those minor problems, and then I’ll also put the Ghost images on an external hard drive or perhaps even on DVDs. That would be 14 DVDs, but even though my two external hard drives seem pretty rugged and DVDs actually get unreadable after a few years, I like the idea of having something that I can’t accidentally delete.

The new machine now runs the DrJava unit testing suite in 5 minutes and 22 seconds. Corky always wants to know how fast the unit tests run, so that is basically our JavaPLT group-internal benchmark. Unfortunately, I don’t remember how fast it ran on the Athlon 64 3500+.

I’ll also still have to put a 160 GB PATA hard drive from the gutted machine (the old “scalar”) computer into my trusted old Pentium 3 (“vector”). I’ll have to remove one of my CD/DVD drives, but then I’ll have a 160 GB, a 120 GB, and an 80 GB hard drive in that machine, for a total of 360 GB. I don’t exactly know what I’ll use all of that storage for… or the 730 GB in “scalar”. I’m delighted I’ve broken the 1 TB barrier, though. To make backups more convenient, I got two external USB 2.0 hard drives that don’t require a power supply, a 120 GB Passport Portable and an 80 GB GigaBank Premier. And I still have a by now puny 20 GB PATA (my first hard drive was 20 MB) hard drive sitting around, so I’m at 1.31 TB now, and 732 MB are still free…

By the way, now that I have mentioned the names of two of my computers, perhaps I should mention that there’s a pattern in the way I name my machines. My primary machine is always named “scalar”, because that is my “development nickname”. I picked it when I first read about the Pentium and its superscalar architecture. “Superscalar” sounded cool, but it was too long and too… super, so I truncated it to “scalar”. All other machines then have something to do with mathematics:

  1. scalar: primary desktop
  2. vector: second desktop; web and media server, IRC and IM client
  3. tensor: third desktop; usually an old machine that’s not powered up (right now, tensor doesn’t exist, I just have two broken and gutted old machines — the Athlon 64 and a Pentium 3 700)
  4. manifold: MacBook notebook
  5. gradient: Windows tablet PC

The two desktops that I may use at the office don’t really follow my pattern:

  1. quantum: Windows desktop at the office (compromise between Dr. Wong’s physics scheme and my mathematics scheme)
  2. finland: Linux desktop at the office (complete departure from my scheme, using the JavaPLT group’s geography scheme

I once had a list of even more machine names, but I lost it. I don’t think I’ll move beyond the number of machines I have live right now any time soon, though. A lot of people would have expected the name “matrix” after “scalar” and “vector”, but the “Matrix” trilogy of crappy movies made it impossible for me to choose that name.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Yet Another New PC (2)

After 1.5 days of installation marathon, I’m almost done setting up my new computer. At first, there were a few problems again after I had moved all SATA hard drives into the Dell and when I was trying to install Windows Server 2003: a nice BSOD right after the text phase of the installation. I think it was the same issue as 1.5 years ago. But this time, I had a slipstreamed CD of Windows Server 2003 ready that included SATA drivers and Service Pack 2.

After that, it has been a pretty smooth ride. One small moment of panic arose when I tried to access my password-protected sensitive data: Somehow, it wouldn’t let me access them anymore (and no, I did have the right password). The volume must have gotten damaged when I transferred it. Fortunately, I had a backup from “last year” (12/27), and I could pretty much reconstruct the data.

What’s still missing? Mainly IntelliJ IDEA and a few utilities. My build environment for DrJava is already set up again, as are the JDKs and Perforce. A few other utilities need to be installed, and then that’s it. After that, I’m definitely going to create Ghost images of the hard drives so I can easily revert to this stage.

Now I’m pretty tired, but I’m already at the office. There’s a new policy at the department that PhD students have to attend the Friday lectures. But I’m happy — the new computer seems pretty fast, the install was pretty smooth, and I’m pretty much done.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

Yet Another New PC

On Sunday, I finally gave up trying to fix my “old” PC (purchased in June 2005). I just can’t afford to spend more time to find the problem, and I can’t just blindly buy new components in the hope that it’ll fix the problem. So I bought a new computer, and since this time I want to have a decent warranty, I got a Dell… dude!

I was impressed by the Dell Dimension E510 that Corky got me at the office, and the Dell Dimension 9200 that I bought for my home office and that just got delivered (free one day shipping — living so close to Dell rocks!) is very nicely set up too. I’ve already taken some pictures. Here are the specs:

  • Intel Core 2 Duo E6600 (4 MB L2 cache, 2.4 GHz, 1066 MHz FSB)
  • 2 GB DDR2 dual channel SDRAM
  • 256 MB nVidia Geforce 7300LE TurboCache
  • 320 GB, 250 GB, and 160 GB SATA hard drives
  • 16x CD/DVD burner

That already includes the two SATA hard drives from the old computer. Of course I was thinking about partially cannibalizing the old Athlon 64 machine, but I haven’t decided how much I’ll actually put in. I was surprised to find out that there’s no PATA in this machine anymore; even the DVD drive is SATA. I’m glad I decided to buy a pre-installed DVD drive from Dell. I did that because my old DVD writer, a Benq DW1640, was pretty flaky: Lots of bad burns and noisy vibration of the DVDs.

Now I almost wish I had bought a second DVD drive for an extra $30 since I don’t have any SATA DVD drives around. But I’m not even sure I’d want to put in a second DVD drive anyway; I hardly ever had to use two drives at the same time.

I may add the additional PCI USB 2.0 controller that I have, with three front and four back USB ports, but the Dell has six USB ports in the back and two in the front, so I don’t think I’ll need the additional ports either. I guess it’s just going to be the two SATA hard drives (320 GB and 160 GB). The remaining 160 GB PATA drive will go into my trusted old Pentium 3 733 MHz, which still works great after 6.5 years. I guess I’ll move the DVD drives and the USB 2.0 controller too. No point in letting them go to waste.

I’ve booted the Dell up once, just to check things out. It’s got Windows XP Home on it, but I’ll replace it with Windows Server 2003. Right now, I’m making Ghost images of my old system partition of the Athlon 64, so just in case things go really wrong with the new Dell, I’ll be able to easily restore my Athlon 64 system, as broken as it was. Once the Ghost images are done, I’ll move the drives, and then the installation marathon will begin. This time, I’ll be sure to make a Ghost image of the fresh system too, so if I ever need to reinstall Windows, I won’t have to install and configure all the applications again.

All of this is bound to take some time. At the moment, as the progress bar of Norton Ghost creeps forward, I’m thinking about popping in a movie. I’ll report back soon.

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

New Year and Trouble

Well, I haven’t posted in a while. I also haven’t been able to do very much. My world is pretty much in disarray again. Just when I thought I had made peace with my “family life” (or what is left of it), my mom and I get disappointed again. Bravo. The man that fathered me is the most egotistical pig I have ever met. I feel ashamed just to be related to him.

I feel like I’ve been set back over half a year. I’ll try to use what I’ve learned during my therapy, but I’m not sure that is enough. I think I may need some guidance again, but right now I don’t even know what I feel. I’m just worried that the last semester will repeat itself. I can’t really afford that.

I’ve also had major problems with my main computer. It won’t boot. Or more correctly, it will boot all the way just past the Windows login prompt, and then 9 out of 10 times it will just do an “instant reset”, all the way to the POST again. There’s no bluescreen, no error beeps, no error messages, and no entries in the event log. The weirdest thing, though, is that if the computer stays alive for a few more seconds, then my computer is pretty stable. I just can’t figure this one out.

At first I thought it was a faulty hard drive because for a while, my computer wouldn’t boot at all, so I rush-ordered a new hard drive so I could fix everything before Diana and I went to Kansas City over New Year’s. I got the new drive installed, but that didn’t get rid of the “instant reset” problem. I’ve got a feeling that it’s actually getting worse.

I’ve unplugged some unnecessary components, but that didn’t help. I’ve measured the temperatures of CPU, motherboard, RAM, graphics card, and drives, and everything seems to be within range. I ran an extensive RAM test, so I don’t think that’s it. It could still be a faulty motherboard, graphics card, or power supply.

There’s really only more thing I can try: Hook up another power supply, even though that’s a major hassle. I can’t really go to a store and say “Give me a motherboard and a graphics card, I just wanna see if they fix the problem, if not, I’ll return them!” I don’t have the right kind of graphics card, RAM or motherboards on hand, and I can’t randomly buy something and hope that it will work. I have neither the money for that nor the time. If the power supply doesn’t do the trick, I’ll have to buy a new computer…

Share
Posted in Uncategorized | Leave a comment

Print This Post Print This Post  

About Air Travel

Today, my girlfriend and I returned from a two-day trip to Kansas City, to attend a friend’s wedding and celebrate New Year there. We decided not to check bags, because we were only going for two days and did not need a lot. I usually try to do that, if possible: I’ve never lost my bag, but airlines have on several occasions.

I had heard about the new restrictions about carrying liquids. Continental Airlines sent me an email stating (emphasis mine):

Bring your bag onboard and save time. Trial size liquids, gels and aerosol items (3.4 oz./100ml or less) that fit in one, quart-size (1 liter), clear plastic zip-top bag are allowed beyond security.

The TSA website goes even further and says (again, emphasis mine):

All liquids, gels and aerosols must be in three-ounce or smaller containers. Larger containers that are half-full or toothpaste tubes rolled up are not allowed. Each container must be three ounces or smaller.

All liquids, gels and aerosols must be placed in a single, quart-size, zip-top, clear plastic bag. Gallon size bags or bags that are not zip-top such as fold-over sandwich bags are not allowed. Each traveler can use only one, quart-size, zip-top, clear plastic bag.

I already decided not to bring a bottle of water, like I normally do. This was a big sacrifice already; I easily get dehydrated on planes. But of course, I had to bring a few liquid or aerosol products: Toothpaste, shampoo, contact lens cleaner, deodorant. So I went to CVS the morning before we left and tried to buy the smallest items I could find. I pretty much failed: The smallest amounts of toothpaste and contact lens cleaner I could find were 4 oz. I managed to find a 1 oz. deodorant spray, and I had small sample bottles of shampoo from previous hotel stays. I put everything in a quart-sized clear zip-lock bag, as instructed. To be safe, I took a deodorant stick with me, just in case they don’t want to have aerosol sprays on the plane.

Departing from IAH in Houston, we had no problem at all. I took the zip-lock bag out of my duffel bag, it got inspected, but I was let through and had the pleasure of dressing myself and reassembling my belongings: Belt back on, shoes back on. Wallet back in pocket, travel wallet for tickets and passport back around neck. Notebook back in notebook case, notebook case back into backpack, zip-lock bag of liquids back into duffel bag. I don’t enjoy this procedure, and it was more intense than ever before, but I didn’t complain. This is just air travel as we know it these days.

On the way back, however, leaving Kansas City, we experienced a completely new level of personal service: We did exactly the same as in Houston before, had exactly the same stuff, plus one sealed 5 oz. bottle of a Kansas City brand of barbecue sauce. First we were told that we should have put our liquids in quart-sized bags; so the security personnel removed our little bottles from our quart-sized bags and put them in sandwich-size zip-lock bags. I find the Imperial unit system with quarts and ounces confusing too, but if you’re checking for quart-sized bags, shouldn’t you know how large they actually are?

Then the TSA employees took all items out of our bags and looked at them one at a time. I know they have a right to do that, but when the friendly man began to examine and smell my camera, I began to think that they were overdoing it just a little bit.

We were then forced to abandon some of the items larger than 3 oz. — the 4 oz. tube of toothpaste I had bought just two days ago, and the 5 oz. bottle of barbecue sauce, still sealed-for-our-protection, we had received as a gift from the newlyweds. For some reason I was allowed to keep the 4 oz. of contact lens cleaner, perhaps because it was clear liquid. The expert told me “it’s all about binary explosives these days…”

I was then reprimanded for not putting the deodorant stick into the bag of liquids. I asked why, because I thought the rule was only for liquids and the deodorant stick was a solid, and I was told the TSA screeners “can’t always tell exactly” what different things are on the X-ray machines.

I’m sure studying the screens of the scanners and determining the contents of the bags is difficult. The TSA set up concrete rules, rules that are incredibly strict, so strict that I wasn’t able to buy items that fit them. I think it’s silly that I had to abandon my 4 oz. of toothpaste, but if the regulations require that, I accept it. But a liquid is a liquid and a solid is a solid, and the rules didn’t say anything about having to put solids into clear zip-lock bags. I sympathize with the TSA employees for having to figure out what is soap and what is a bomb, but where will this end?

In 1996, when I arrived in Springfield, Missouri, as a high school exchange student, my host father complained about the security measures that were in place at that time. He said: “They treat all people as if they were criminals.” I replied they were only trying to make it safer for all of us, and we should be eager to help them; abandoning some personal rights and limiting our privacy was in our very own interest. Now I can see my host father’s point. We are all being treated as if we were criminals, and I would not be surprised if soon we have to carry all our belongings in plastic bags, and while we’re in airports, we may only wear transparent garments.

I think the TSA personnel at the Kansas City airport just had too much time on their hands. They were bored, and inspecting every item in our bags, exactly following the regulations and sometimes even going beyond their requirements made the dullness easier to bear. But if this is actually the quality of check the TSA intends to force upon travelers, then I believe they are going too far.

I still think most of the controls are reasonable. I’m cooperative, I’m friendly; I do my best to help the screeners do their jobs. But I have realized that giving up freedom will not make us safe, and I have serious doubts about their efficacy. And be honest: Have the controls at the airports really made you feel safer, or have they perhaps done the opposite, made you more anxious, instilled fear?

Share
Posted in Ramblings, Uncategorized | Leave a comment

Print This Post Print This Post  

Set Constants, Options for Delay and Yield

This morning — silently typing in bed ;) — I wrapped up some work on the SetConstantsStrategy. There are still a few limitations, but for what I’m using it, I think it’s reasonable: It only works on static fields, so I only have to deal with the one <clinit> method, not with a varying number of constructors. It works both for final and non-final fields, but they have to be initialized with a simple value. It cannot be a method call, and it shouldn’t be in a static initializer block with some complicated if-then-else stuff. I only scan through the <clinit> code for the first putstatic referring to the field. Then I check that the preceeding instruction is one that simply loads a value, not one that makes a method call or performs arithmetic. Then I remove that instruction and replace it with one that loads the new data. For setting the probability of a yield to different values from 0.0 to 1.0 or enabling and disabling things by changing a boolean, this is good enough.

I also added boolean flags to control if the yields and delays at different places are actually enabled: Now I can independently control them at

  • before a Thread.start
  • before a Thread.exit
  • before a Thread.run
  • before a Thread.join
  • before an Object.notify
  • after an Object.notify
  • before an Object.wait
  • after an Object.wait
  • before a monitorenter
  • after a monitorenter or monitorexit

I did this because Corky and I agreed that I was placing random delays in too many places, and at least I believe there is some kind of balance between delays at different synchronization points. Switching these on and off could give me a chance of exploring the interactions and finding that balance.

When I finished adding the flags, it occurred to me that maybe I shouldn’t have used one probability for all of the yields and then boolean flags for kind of insertion point; maybe I should have used probabilities for each of them. But for now, I’ll go with this implementation. Just to show some useless detail again, here are the command line arguments that I currently have in the instr.setconstants.xml file:

<args line="-force -nobackup
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_PROB:=1
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_THREAD_START:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_THREAD_EXIT:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_THREAD_RUN:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_THREAD_JOIN:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_PRE_NOTIFY:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_POST_NOTIFY:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_PRE_WAIT:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_POST_WAIT:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_PRE_MONITOR:=false
-X set-const=edu.rice.cs.cunit.SyncPointBuffer::RANDOM_YIELD_POST_MONITOR:=false"/>

It overrides all the yield flags and the probability. The -force flag is there to allow instrumentation of already instrumented files.

Now we’re off to a Christmas party at Dr. Nguyen’s house. Thanks for the invitation!

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Lots of Things

Ok, so I haven’t blogged in a week, but that doesn’t mean I haven’t done anything in that time. Although my activities have been a bit different. First of all, about 10 days ago, I somehow hurt my shoulder (Doc says strained rotator cuff muscle, which was my diagnosis as well; I don’t really need a doctor, just a DEA number, really), so I haven’t been biking since. Rotating my arm to hold the handlebar and supporting part of my weight on it hurts, so I’ve mostly worked from home, and twice my girlfriend has been absolutely wonderful by giving me rides to the office and back.

Second, my mom arrived on December 13 and is staying with me for two weeks over Christmas. We haven’t seen each other in a year, so this is long overdue. I didn’t have the time to go back to Germany during the summer, and if you know anything about my personal life, then you also know that this was a good thing. I’m taking some time to talk to her, about our family or what is left of it, philosophy, and about life in general. It’s good. I think it’s soothing for both of us. My girlfriend and my mom are getting along well too. I expected that, and they already met last year during Christmas, but I’m nonetheless very happy about this, for the present and the future.

I’ve spent a few days grading for COMP 311, the last time I have to do that as a TA at Rice. I had to fix the auto-grading templates for assignment 7 in OCaml and do some of the auto-grading itself, even though it wasn’t my turn, but fortunately we have a very reliable group of TAs this time, and I don’t have to take over other people’s work this time. Tomorrow we plan to discuss the final grades for the course. People have also been picking up their final exams now, and some have been haggling over grades. I wish there were a better, more automated way of returning the exams.

I’ve been adding more to the documentation of the Thread Checker, and I also started implementing the new “random yield” strategy that Corky has suggested. It works, but I haven’t evaluated how well it does. I also improved the build script and the custom instrumenting class loader.

I’m now dealing with a small but interesting side problem: Changing the probability constant of the yield strategy without having to recompile, and therefore reinstrument the entire rt.jar. The constant has to be in the rt.jar (at the beginning of the boot classpath), otherwise VM initialization will fail, and basing it on some kind of command line flag or value in a configuration file is impossible if I want it to affect Java programs from the very beginning, so it has to go into the rt.jar. If it’s final, however, the Java compiler may propagate the constant, and it can’t just be changed in one place anymore, so it has to be a non-final static variable that is initialized in the <clinit> method. Now I’m writing a strategy that can change the value that gets assigned to such variables. It’ll save a lot of time later, especially when instrumenting on-the-fly.

Share
Posted in Concurrent Unit Testing, Uncategorized | Leave a comment

Print This Post Print This Post  

More Documentation

I spent virtually this entire weekend horizontally in bed, but at least today I managed to write quite a bit of introductory documentation for the Thread Checker. The description of @Combine-style annotations and invariant inheritance is still missing, though, as is a description of how to invoke the bytecode rewriting process for offline instrumentation or the custom class loader for on-the-fly instrumentation.

Most of today was spent grading the 311 exams, though. With one man short, it took us from about 1:30 PM to 8:30 PM. I also hand-graded my share of the assignment 6 submissions, which means the only major task left as part of my TA requirement is hand-grade a few assignment 7 submissions, and then I’m done. Unless I am forced to pick up someone else’s slack…

Share
Posted in Concurrent Unit Testing, Uncategorized | Leave a comment

Print This Post Print This Post  

Reflection Works, Documentation Still Missing

This week, I’ve successfully tackled the problem with the parameter lists in the reflection-based Thread Checker. Ironically, the parameter names are available when I do my own thing, but when I’m using Java’s convenient, built-in reflection API, the names are pieces of information I cannot get.

So my first step was to enhance the @PredicateLink‘s method attribute. It is now possible to specify the order of the parameters by listing the parameter names in parentheses, e.g. method="myMethod(param1,param2,param3)". The first parameter of type Object, used to pass the value of this if possible, is ignored in this list.

After that was done, I could have rewritten all the method attributes for the annotations. But I realized that I do have the required information when I’m processing the class files, and I need to do that briefly even for the reflection-based Thread Checker. So after the manual process worked, I added an automatic updating function that changed a method attribute without parameters (old format) to a method attribute with parameters (new format). Now all the old annotations work with both Thread Checkers. One problem solved, quite elegantly I think; I just still think it’s ironic that I can’t get the parameter names using reflection…

After that, I added a few more common annotation, e.g. the @Not... flavors for all the @Only... annotations I have, and I added @Any and @None annotations for all of those common annotations, which are @Combine-style annotations that combine using or and and, respectively.

I also separated out the classes that belong just to the annotations, and not to the framework involved in rewriting the bytecode, and put those classes in a separate tclib.jar file. When compiling, only those files are necessary. The full tcrt.lib is only necessary to do the bytecode rewriting and run the Thread Checker. I think separating the two sets of classes was a good idea, because now it is possible to ship a much lighter 34 kB tclib.jar (47 class files) with applications that use it, like DrJava, and only distribute the 734 kB tcrt.jar (617 class files) when the debugging capability is needed.

Mea culpa, though: I still haven’t written more documentation, I still haven’t extended Concutest-JUnit, I still haven’t collected more performance data, and I feel I’m a little behind on my grading (even though the other TAs haven’t done more either). Tomorrow (read: today) I’ll probably hold my last regularly scheduled office hours. Things are moving ahead, albeit slowly.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Wrapping Up Continues

During the last couple of days I added what thought were the last major features missing in the Thread Checker: It can now import <predicate>– and <combine>-style annotations from XML files, and I’m getting subtyping warnings for predicate annotations, both offline and on-the-fly.

However… Now I’m noticing a problem that I was aware of, but just didn’t consider serious: In the reflection-based Thread Checker, I can’t associate arguments with parameter names, and the order in which the parameters are reported is undefined. Using the code that I’ve written, the @OnlyThreadWithName(value="foo", regex=false) annotation requires a predicate public static boolean check(Object thisO, boolean regex, String value). I wrote it the other way around, with the String in the middle.

With the offline instrumentor, I have the variable names, so I can still match the values correctly, even if the order isn’t right. But using reflection, I don’t have the names… At least not using the normal API. I guess I could get them somehow, but that would mix the blend of my code to inspect class files and reflection. But that’s probably what I need to do.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Does Contravariant Propagation and Combining Using or Make Sense?

I’m still trying to figure out if some invariant annotations should be inherited from subclass to superclass, i.e. in the opposite direction of regular inheritance and the way annotations are inherited now.

Let’s assume that I do this. @NotThreadWithName is an invariant that makes a precondition stricter, so it will be inherited in the regular way; its behavior is covariant, even though I’m not sure if that’s the right word for it.

@OnlyThreadWithName, I believe, is an invariant that should make the precondition less strict, at least when there are several of them, because my intuition is that users want to combine them using or: It just doesn’t make sense to combine them using and. So let’s assume that I inherit @OnlyThreadWithName from subclass to superclass, i.e. in the opposite direction, or contravariantly.

What does that mean? And does it make sense? Consider the following program with annotations:
class Super {
void foo() { }

void bar() { }

void wibble() { }
}

class Mid extends Super {
@NotThreadWithName("main")
void foo() { }

@OnlyThreadWithName("aux")
void bar() { }

@NotThreadWithName("main")
@OnlyThreadWithName("aux")
void wibble() { }
}

class Sub extends Mid {
void foo() { }

void bar() { }

void wibble() { }
}

Here are the invariants end up getting applied for each method:

  • Super:
    • foo(): None.
    • fee(): May only be run by threads with name “aux”.
    • wibble(): May only be run by threads with name “aux”.
  • Mid:
    • foo(): May not be run by threads with name “main”.
    • fee(): May only be run by threads with name “aux”.
    • wibble(): May not be run by threads with name “main”. May only be run by threads with name “aux”.
  • Sub:
    • foo(): May not be run by threads with name “main”.
    • fee(): None.
    • wibble(): May not be run by threads with name “main”.

The biggest question here is probably how the invariants for Mid.wibble() should be combined. If they are combined using and, then the only thread allowed to run has the name “aux” (not “main” and “aux”); if they are combined using or, then all thread names except for “main” are allowed (not “main” or “aux”). If the names “main” and “aux” are changed so that they are identical, then the possible results are even more nonsensical: No threads at all, or all threads allowed.

I think my intuition about combining annotations that relax the invariants using or was wrong. It should always be and. If a programmer wants to use or, that can be achieved with a little bit more code using a @Combine-style annotation.

Perhaps another idea to investigate would be that of allowing necessary and sufficient predicates: A necessary predicate must be fulfilled for a method to be executed without warnings, but it is not enough by itself; if another predicate fails, a warning is generated. On the other hand, when a sufficient predicate is fulfilled, other predicates may fail, and still no warning is generated. That is a similar notion than combining using and and or, but perhaps more precise. Right now, I don’t see a need for this, though.

The covariant and contravariant inheritance of annotations could be interesting and I have a better idea of how to implement it, but without a connection to the idea of restricting or relaxing preconditions, I don’t quite see a consistent, compelling theory developing. The custom predicates make the theory a little bit wobbly anyway. Also, right now I can’t come up with a situation in software engineering that would require contravariant propagation of annotations.

So, right now it seems like I’ll just add subtyping warnings for predicate annotations, and I noticed I have to do XML import for predicate annotations, and that’s it.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

@OnlyRunBy Subtyping

I just looked at the subtyping warnings generated from the normal @OnlyRunBy (before-predicate) annotations, and they definitely a bit weird. Not necessarily wrong, but perhaps not what I really want.

Let’s assume there are three classes, Super, which is extended by Mid, which is extended by Sub. Super has an @OnlyRunBy annotation, which affects all methods in all three classes. Sub has an @OnlyRunBy that affects only its own new method, fum(). The method Sub.bar() also has a @OnlyRunBy annotation.

@OnlyRunBy(@ThreadDesc(name="main"))
class Super {
public void foo() { }
}

class Mid extends Super {
public void bar() { }
}

@OnlyRunBy(@ThreadDesc(name="another"))
class Sub extends Mid {
public void fum() { }
@OnlyRunBy(@ThreadDesc(name="auxiliary"))
public void bar() { }
}

Super.foo() may only be run by the “main” thread. The same applied to Mid.bar(): It may only be run by the “main” thread.

Now it gets weird: Sub.fum() may only be run by a thread whose name is both “main” and “another”. That’s probably not what the programmer intended… The programmer might have wanted to relax the requirement and allow the threads “main” or “another”.

And now we currently get a subtyping warning: Sub.bar() may only be run by a thread whose name is both “main” and “auxiliary”, and here the method in the subclass has stricter prerequisites than the method in the superclass, so a subtyping warning is generated.

Technically, with my current implementation of combining the annotations using and, the warning is correct. However, my contention is that someone using @OnlyRunBy probably wants to relax the prerequisites, and that would mean adding @OnlyRunBy in subclasses is ok. What should generate a warning is if an @OnlyRunBy annotation in a subclass is present, but it is somehow removed in a superclass. That’s not how my current system works. Subclasses and methods in subclasses get annotations from superclasses and methods in superclasses, but not the other way around.

What would probably be the right thing is this:

  • Annotations that restrict preconditions should be passed on from superclass to subclass, and if a subclass introduces a stricter precondition that the superclass doesn’t have, a warning should be generated.
  • Annotatons that relax preconditions should be passed from subclass to superclass, and if a superclass has such a relaxed precondition that the subclass does not have, a warning should be generated.

That means that restricting annotations should be covariant, and relaxing annotations should be contravariant. If the annotations are found in a different way, that’s an error in the threading discipline.

Unfortunately, I don’t really know how to write this. How do I decide what gets combined using and (restricting) and what using or (relaxing)? With the user-written predicate annotations, I can’t assume which behavior is wanted because I can’t possibly figure out if a user-written Java method serving as predicate makes the preconditions stricter or more relaxed, so the user would have to pick covariant or contravariant behavior when writing the annotation. That’s not hard, but again, right now I don’t know how to combine them.

I’ll have to talk to Corky if my intuition here is right and if that should go into my current code (which would cause quite a delay), if that should just go as theory into my thesis, or if I’m completely on the wrong path here.

I don’t think I am, though, because these warnings provide static checks for the maintenance of a threading discipline in the use of extensible libraries, something that I consider one of the greatest, if not the greatest, current challenge in software engineering.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

What’s Left to Do?

So, what’s left to do? Lots, of course. Mainly, I have to run benchmarks and prepare different versions of DrJava for comparison. But on a shorter term, what’s left to develop?

Yesterday I noticed that I actually do not perform any subtyping warnings on predicate checks (@PredicateLink– and @Combine-style annotations). I probably did this because it’s not exactly clear which predicates are equivalent and which aren’t, so there may be a lot of false positives. I also noticed that I’m doing subtyping warnings on @OnlyRunBy annotations, even though I’ve really only worked out a subtyping relation for @NotRunBy annotations.

I think I am going to reexamine the behavior of @OnlyRunBy annotation subtyping, and then provide a way to choose either one (or neither) for the predicate annotations. I really believe the static subtyping warnings are important, as they statically point out misunderstandings in the threading discipline.

I also need to provide a way to set timeouts for Concutest-JUnit and to relax the threads that have to have died by the end of the test. In some (many?) cases, my current checks are too stringent.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

@Combine-Style Using Reflection Too

@Combine-style annotations now also work using reflection. That means the process of processing the class files is a lot less costly (in one example 16.5 seconds for reflection and 26.1 seconds for my original approach of rewritten bytecode), but the runtime performance might be degraded due to the use of reflection. However, at least so far I don’t see this degradation: With reflection one particular test takes 1.5 seconds, and with rewritten bytecode it takes 1.4 seconds. The reflection-based code was also a lot easier to write and offers better diagnostics, so maybe I was wrong about how heavy reflection really is. I’ll still need to run more tests that last longer, though.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

@PredicateLink-Style Using Reflection

I corrected a bug in the source code and uncorrected a bug in my mind (see last post). Then I write a lot more code that allows me to treat @PredicateLink– and @Combine-style annotations using reflection. Some things are actually REALLY nice: If I want to print out the annotation class and all the member-value pairs, I simply call the annotations’s ToString method.

It looks like it can now do @PredicateLink-style annotations. The strategy, however, is a lot more limited than the one I am using with bytecode rewriting. When rewriting bytecode, I have both the names of the name and types of the parameters in the predicate method, but all I have here at runtime, using Java’s reflection API, is two lists of types. As soon as one type does not match the type in the other list, I give up and tell the programmer how to change the annotation or predicate method.

That stuff seems to work now. May the Sugar Plum Fairy take me back to my bed across the Lemonade Sea now.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

On Closer Inspection, Reflection More Complicated

I’ve been wanting to write a reflection-based Thread Checker for a while already, mainly because I think many people will ask me: “Java provides a reflection API. Why didn’t you use it? It’s so much simpler than rewriting bytecode!”

I originally concurred that it would be easier to write, but I still think it will not perform as well as rewritten bytecode. But the proof is in the pudding, of course, as they say, so I had to write this reflection-based version. I’ve been laboring on this now for most of today, and I did start already a few days back, and it turns out to be pretty hard. It’s not trivial to find out where a method was first introduced. I’ve decided to follow the general outline of what I did with the bytecode-rewriting strategy.

I think I should have the code for the @PredicateLink-style annotations now, even though it is much more limited than the code I wrote for rewriting class files: Here, the parameters in the predicate method have to have the same order as the members of the annotation, and that order seems to be undefined. Yes. One of my favorite words. I also haven’t tested the reflection-based code for @PredicateLink-style annotations yet.

The code for @Combine-style annotations should actually be easier and faster than the rewritten bytecode (or at least faster than the first run, when the rewriting happens; I predict caching of the rewritten class files will again kill reflection on subsequent runs).

I fixed a bug that dealt with determining if class-level annotations should apply to a method. It was rather confusing. If a method was already introduced in an interface, then a class-level annotation on the class that implements that interface should not have any effect, but I did something wrong here.

This has cast some doubt on what I’ve been doing with class-level annotations in general, because when I ask for class-level annotations, I still recur into the superclasses and implemented interfaces, and right now, I don’t think I should be doing that. I’ll examine that closer tonight or tomorrow. (Update: No, what I was doing is right. If a class has an annotation, then all methods introduced in that class or in subclasses get the annotation; therefore, recurring up makes sense.)

Right now, Diana and I are going to the Houston Ballet to see “Nutcracker”. Even though I hate to admit it, I guess the Christmas season actually does begin on the day after Thanksgiving. Why would we watch “Nutcracker” otherwise? ;-)

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Caching Issues

I rewrote a few parts of the Thread Checker, mainly in the areas that instrument classes on-the-fly and in the strategy for automatically generating predicate methods for @Combine-style annotations.

Now making backups and saving annotated class files works as expected. I also require a directory to be on the classpath, but only if @Combine-style annotations are used. The caching works very well if the classes involved in rewriting are all regular files and not in jar files: Running the TCSample4 test the first time with on-the-fly instrumentation takes about 33 seconds, the second time it doesn’t even take 2 seconds.

Unfortunately, when the files are in a jar file, caching the rewritten class files is not very effective: The first run takes about 31 seconds, and the second still 30 seconds. The problem obviously is that generating the code isn’t the expensive part, but examining the class files to figure out what code to generate or check if it has already been generated.

I could write some kind of caching for jar files or write out the information obtained into some kind of file, and then on the second run first consult that file, in the hopes of being able to skip the expensive examination phase, but it just doesn’t seem like that is so essential to the project. There are other, more important things to figure out, so my suggestion right now is just this: Keep the files that are involved in rewriting outside of jars.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Thread Checker Release

Yesterday, I made the first version of the Thread Checker available on the Concutest website. It is just one jar file, tcrt.jar, that contains both the classes for the annotations and the classes for rewriting class files (on-the-fly and offline) to check the invariants. I think in the future, I will separate this into two archives in order to keep the jar file with the annotations, the one that will have to be linked with user programs, as small as possible.

I also didn’t post any instructions yet. There are many examples available in this blog (e.g. here, here, here, here, here, and here), but no description on how to invoke the Thread Checker for on-the-fly instrumentation or how to rewrite the class files offline. I still have to do that.

I also realized that I need to check how the features of making backups, saving the instrumented version of a class, and writing auto-generated class files for @Combine-style annotations behave when the source class file is in a jar file. I think for the first two, backups and writing to disk, I will simply not perform these tasks if the class came from a jar file. I don’t want to rewrite the entire jar file; if caching or backups are important, then the jar file should be instrumented offline.

The auto-generated class files are more difficult to handle: I think I will have to stipulate that there needs to be at least one directory on the class path, and auto-generated class files will be placed there unless some other directory is specified. Another, perhaps better, possibility would be to try to load the automatically generated class files immediately from a byte array instead of first writing it to disk. That would allow classpaths that do not have any directories in them, but of course, it also disables caching.

I also need to continue the work on the reflection-based predicate Thread Checker. My intuition tells me that it will in general be slower than the thread checks done by rewriting bytecode, but the delay of auto-generating the class files may go away. I definitely need to have this as a comparison.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Not So Bad

I’ve thought about my problem from the last post a bit, and I have decided that the current situation actually isn’t so bad. I went with an approach that’s similar to the 2nd option that I have described, but a bit more permissive.

The class containing a predicate method should be public if it is a top-level class, and public static if it is a nested class. If it is a nested class, then all of its enclosing classes must also fulfill these criteria. This makes a method accessible from any static context, anywhere. However, when a violation is detected, I only issue a detailed warning. I opted for a warning instead of aborting the instrumentation process because in many cases, the programs still work for some reason if the instrumentation is done offline. Only in on-the-fly instrumentation are these warnings important.

I have now implemented the code for issuing these warnings and have also created a simpler TCRun class that makes it very easy for the user to run programs with on-the-fly Thread Checker instrumentation.

Now I should do some more tests with @Combine-style annotations, and then I need to package the Thread Checker conveniently, write documentation and release it. Yay!

Update

Another thing I should do is check if classes have already been auto-generated during previous on-the-fly runs. The auto-generation for @Combine-style annotations can take a while, so it would be highly desirable to reuse already existing classes.

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post  

Not Happy

After some experimentation, I have realized that while I can access all the classes in any package, regardless of whether they are private or package-private using reflection, I cannot do that using regular calls. There doesn’t seem to be a central feature that disables that check all together.

Now, I wanted to write a purely reflection-based checker anyway, but I also wanted to get the bytecode-based version to work. Now I have to think hard what to do. One option, of course, would be to detect the use of a predicate method that cannot be called from the call site. Whether that is possible or not can only be found out once I examine the call site, so in the case of on-the-fly instrumentation, that would boil down to an exception, just like now.

A second approach would be to stipulate that the predicate method must be in a class that’s accessible from anywhere, i.e. either in a public top-level class, or in a public static nested class. The classes containing the predicates cannot be private, protected, package-private or non-static inner classes. Assuming this stance would allow me to do a robust analysis at the time I’m checking the annotations, and I can reject annotations that might lead to problems at call sites later.

The third and most complicated way is to add relay methods in a place that has access to and can call the original predicate method that should be called. These relay methods must then satisfy the criteria from the second approach. Where exactly I would put these methods, I don’t know… I think I’ll try to sleep over it, even though I just got up again at 2 AM to work on this…

Share
Posted in Concurrent Unit Testing | Leave a comment

Print This Post Print This Post