In Shenandoah 1.0 every single Object had an additional header - called forwarding pointer. Why was that needed and what is the reason that lead to its elimination in Shenandoah 2.0?
First of all, every single java Object has two headers: klass and mark. They have been there in each instance since forever (they can slightly change how a JVM handles their flags internally with recent JVMs, for example) and are used for various reasons (will go into detail about only one of them a bit further in the answer).
The need for a forwarding pointer is literally in the second part of this answer. The forwarding pointer is needed in both read barrier and write barrier in Shenandoah 1.0 (though the read could skip the barrier for some field types - will not go into detail). In very simple words it simplifies concurrent copy very much. As said in that answer, it allows to atomically switch the forwarding pointer to the new copy of the Object and then concurrently update all references to point to that new Object.
Things have changed a bit in Shenandoah 2.0 where the "to-space invariant" is in place : meaning all the writes and reads are done via the to-space.This means one interesting thing : once the to-space copy is established, the from-copy is never used. Imagine a situation like this:
refA refB
| |
fwdPointer1 ---- fwdPointer2
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
In Shenandoah 1.0 there were cases when reading via the refA could bypass the barrier (not use it at all) and still read via the from-copy. This was allowed for final fields, for example (via a special flag). This means that even if to-space copy already existed and there were already references to it, there could still be reads (via refA) that would go to the from-space copy. In Shenandoah 2.0 this is prohibited.
This information was used in a rather interesting way. Every object in Java is aligned to 64 bits - meaning the last 3 bits are always zero. So, they dropped the forwarding pointer and said that : if the last two bits of the mark word are 11 (this is allowed since no else uses it in this manner) -> this is a forwarding pointer, otherwise the to-space copy does yet exists and this is a plain header. You can see it in action right here and you can trace the masking here and here.
It used to look like this:
| -------------------|
| forwarding Pointer |
| -------------------|
| -------------------|
| mark |
| -------------------|
| -------------------|
| class |
| -------------------|
And has transformed to:
| -------------------|
| mark or forwarding | // depending on the last two bits
| -------------------|
| -------------------|
| class |
| -------------------|
So here is a possible scenario (I'll skip class header for simplicity):
refA, refB
|
mark (last two bits are 00)
|
---------
| i = 0 |
| j = 0 |
---------
GC kicks in. The object referenced by refA/refB is alive, thus must be evacuated (it is said to be in the "collection set"). First a copy is created and atomically mark is made to reference that copy (also the last two bits are marked as 11 to now make it a forwardee and not a mark word):
refA, refB
|
mark (11) ------ mark (00)
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
Now one of the mark words has a bit pattern (ends in 11) that indicates that it is a forwardee and not a mark word anymore.
refA refB
| |
mark (11) ------ mark (00)
|
--------- ---------
| i = 0 | | i = 0 |
| j = 0 | | j = 0 |
--------- ---------
refB can move concurrently, so then refA, ultimately there are not references to the from-space object and it is garbage. This is how mark word acts as a forwarding pointer, if needed.
Related
I've read that The elements of an array are stored in a contiguous memory location . Is it always the case ? I understand this is the case with array of primitives. I'm a bit confused about array of objects. An array of objects basically contains reference of the real objects right? references must be stored in contiguous locations but what about the real objects are they really stored in contiguous locations?
Is it always the case ?
Yes, but keep reading.
I'm a bit confused about array of objects. An array of objects basically contains reference of the real objects right? references must be stored in contiguous locations but what about the real objects are they really stored in contiguous locations?
Exactly, what the array contains is object references, not the objects themselves. Think of object references as being similar to long values that tell the JVM where the object is elsewhere in memory (it's more complicated than that, but that's a useful mental model). The object references are stored in the array's contiguous memory block. The objects are elsewhere, and may or may not be stored in contiguous memory (probably not).
So for instance, say we have:
int[] a = new int[] { 1, 2, 3 };
In memory we'll get something like:
+−−−−−−−+
a: Ref51234−−−>| int[] |
+−−−−−−−+
| 1 |
| 2 |
| 3 |
+−−−−−−−+
a contains a reference to the array, which is elsewhere in memory and has a contiguous data block containing 1, 2, and 3.
Now let's look at an object array (where the Example class stores the given constructor parameter as a private x field):
Example[] a = new Example[] { new Example(1), new Example(2), new Example(3) };
That might give us something like this:
+−−−−−−−−−−−+ +−−−−−−−−−+
a: Ref51234−−−>| Example[] | +−−−>| Example |
+−−−−−−−−−−−+ | +−−−−−−−−−+
| Ref81372 |−−−−−+ | x: 1 |
| Ref96315 |−−−−+ +−−−−−−−−−+
| Ref12975 |−−+ | +−−−−−−−−−+
+−−−−−−−−−−−+ | +−−−−−−−−−−−−−−−−−−>| Example |
| +−−−−−−−−−+
| | x: 2 |
| +−−−−−−−−−+
| +−−−−−−−−−+
+−−>| Example |
+−−−−−−−−−+
| x: 3 |
+−−−−−−−−−+
Some environments have packed arrays as an adjunct. For instance, IBM documents packed arrays for its environment here.
this is quite long, and I am sorry about this.
I have been trying to implement the Minhash LSH algorithm discussed in chapter 3 by using Spark (Java). I am using a toy problem like this:
+--------+------+------+------+------+
|element | doc0 | doc1 | doc2 | doc3 |
+--------+------+------+------+------+
| d | 1 | 0 | 1 | 1 |
| c | 0 | 1 | 0 | 1 |
| a | 1 | 0 | 0 | 1 |
| b | 0 | 0 | 1 | 0 |
| e | 0 | 0 | 1 | 0 |
+--------+------+------+------+------+
the goal is to identify, among these four documents (doc0,doc1,doc2 and doc3), which documents are similar to each other. And obviously, the only possible candidate pair would be doc0 and doc3.
Using Spark's support, generating the following "characteristic matrix" is as far as I can reach at this point:
+----+---------+-------------------------+
|key |value |vector |
+----+---------+-------------------------+
|key0|[a, d] |(5,[0,2],[1.0,1.0]) |
|key1|[c] |(5,[1],[1.0]) |
|key2|[b, d, e]|(5,[0,3,4],[1.0,1.0,1.0])|
|key3|[a, c, d]|(5,[0,1,2],[1.0,1.0,1.0])|
+----+---------+-------------------------+
and here is the code snippets:
CountVectorizer vectorizer = new CountVectorizer().setInputCol("value").setOutputCol("vector").setBinary(false);
Dataset<Row> matrixDoc = vectorizer.fit(df).transform(df);
MinHashLSH mh = new MinHashLSH()
.setNumHashTables(5)
.setInputCol("vector")
.setOutputCol("hashes");
MinHashLSHModel model = mh.fit(matrixDoc);
Now, there seems to be two main calls on the MinHashLSHModel model that one can use: model.approxSimilarityJoin(...) and model.approxNearestNeighbors(...). Examples about using these two calls are here: https://spark.apache.org/docs/latest/ml-features.html#lsh-algorithms
On the other hand, model.approxSimilarityJoin(...) requires us to join two datasets, and I have only one dataset which has 4 documents and I would like to figure out which ones in these four are similar to each other, so I don't have a second dataset to join... Just to try it out, I actually joined my only dataset with itself. Based on the result, seems like model.approxSimilarityJoin(...) just did a pair-wise Jaccard calculation, and I don't see any impact by changing the number of Hash functions etc, left me wondering about where exactly the minhash signature was calculated and where the band/row partition has happened...
The other call, model.approxNearestNeighbors(...), actually asks a comparison point, and then the model will identify the nearest neighbor(s) to this given point... Obviously, this is not what I wanted either, since I have four toy documents, and I don't have an extra reference point.
I am running out of ideas, so I went ahead implemented my own version of the algorithm, using Spark APIs, but not much support from MinHashLSHModel model, which really made me feel bad. I am thinking I must have missed something... ??
I would love to hear any thoughts, really wish to solve the mystery.
Thank you guys in advance!
The minHash signatures calculation happens in
model.approxSimilarityJoin(...) itself where model.transform(...)
function is called on each of the input datasets and hash signatures
are calculated before joining them and doing a pair-wise jaccard
distance calculation. So, the impact of changing the number of hash
functions can be seen here.
In model.approxNearestNeighbors(...),
the impact of the same can be seen while creating the model using
minHash.fit(...) function in which transform(...) is called on
the input dataset.
when i have
Object a;
Object b;
i have false sharing
this way i dont
#Contended
Object a;
Object b;
but if i have
final AtomicReference<Object> a;
final AtomicReference<Object> b;
do i still have false sharing?
my guess is that i dont need #Contended as although the a,b may be in the same cacheline what they refer to is not...
Instances of AtomicReference usually take 16 bytes (on HotSpot JVM): 12 bytes object header + 4 bytes value field. If two AtomicReferences lie next to each other in Java heap, they may still share the same cache line, which is typically 64 bytes.
Note: even if you allocate some object between two AtomicReferences, Garbage Collection may compact heap so that AtomicReferences are again located next to each other.
There are several ways to avoid false sharing:
Extend AtomicReference class and add at least 6 long fields - this will make your references occupy 64 bytes or more.
-------------------------------------------------------------------------------
| header | value | long1 | ... | long6 | header | value | long1 | ... | long6 |
-------------------------------------------------------------------------------
^ ^
|--------------- 64 bytes -------------|
Use AtomicReferenceArray and place your references at the distance of at least 16 cells, e.g. one reference will be located at the index 16, and the other - at the index 32.
----------------------------------------------------------------------------
| header | len | 0 | 1 | ... | 15 | 16 | 17 | ... | 31 | 32 |
----------------------------------------------------------------------------
^ ^
|-------- 64 bytes -------|
I'm performing performance testing of a computer application (JAVA). The test concerns the response time (t) obtained while testing the application with a certain number of concurrent threads (th) and a certain amount of data (d).
Suppose I have the following results:
+------+-------+-----+
| th | d | t |
+------+-------+-----+
| 2 | 500 | A |
+------+-------+-----+
| 4 | 500 | B |
+------+-------+-----+
| 2 | 1000 | C |
+------+-------+-----+
| 4 | 1000 | D |
+------+-------+-----+
How can i benefit the most of these results such as knowing the limit of my app as well as creating meaningful graphs to represent these results.
I'm not a statistics person so pardon my ignorance. Any suggestions would be really helpful (even related statistics technical keywords I can Google).
Thanks in advance.
EDIT
The tricky part for me was to determine the application's performance evolution taking both the number of threads and the amount of data into consideration in one plot.
Yes there is a way, check the following example I made with paint (the numbers I picked are just random):
I have a set of requirements and I'm looking for the best Java-based strategy / algorthm / software to use. Basically, I want to take a set of recipe ingredients entered by real people in natural english and parse out the meta-data into a structured format (see requirements below to see what I'm trying to do).
I've looked around here and other places, but have found nothing that gives a high-level advice on what direction follow. So, I'll put it to the smart people :-):
What's the best / simplest way to solve this problem? Should I use a natural language parser, dsl, lucene/solr, or some other tool/technology? NLP seems like it may work, but it looks really complex. I'd rather not spend a whole lot of time doing a deep dive just to find out it can't do what I'm looking for or that there is a simpler solution.
Requirements
Given these recipe ingredient descriptions....
"8 cups of mixed greens (about 5 ounces)"
"Eight skinless chicken thighs (about 1¼ lbs)"
"6.5 tablespoons extra-virgin olive oil"
"approximately 6 oz. thinly sliced smoked salmon, cut into strips"
"2 whole chickens (3 .5 pounds each)"
"20 oz each frozen chopped spinach, thawed"
".5 cup parmesan cheese, grated"
"about .5 cup pecans, toasted and finely ground"
".5 cup Dixie Diner Bread Crumb Mix, plain"
"8 garlic cloves, minced (4 tsp)"
"8 green onions, cut into 2 pieces"
I want to turn it into this....
|-----|---------|-------------|-------------------------|--------|-----------|--------------------------------|-------------|
| | Measure | | | weight | weight | | |
| # | value | Measure | ingredient | value | measure | preparation | Brand Name |
|-----|---------|-------------|-------------------------|--------|-----------|--------------------------------|-------------|
| 1. | 8 | cups | mixed greens | 5 | ounces | - | - |
| 2. | 8 | - | skinless chicken thigh | 1.5 | pounds | - | - |
| 3. | 6.5 | tablespoons | extra-virgin olive oil | - | - | - | - |
| 4. | 6 | ounces | smoked salmon | - | - | thinly sliced, cut into strips | - |
| 5. | 2 | - | whole chicken | 3.5 | pounds | - | - |
| 6. | 20 | ounces | forzen chopped spinach | - | | thawed | - |
| 7. | .5 | cup | parmesean cheese | - | - | grated | - |
| 8. | .5 | cup | pecans | - | - | toasted, finely ground | - |
| 9. | .5 | cup | Bread Crumb Mix, plain | - | - | - | Dixie Diner |
| 10. | 8 | - | garlic clove | 4 | teaspoons | minced | - |
| 11. | 8 | - | green onions | - | - | cut into 2 pieces | - |
|-----|---------|-------------|-------------------------|--------|-----------|--------------------------------|-------------|
Note the diversity of the descriptions. Some things are abbreviated, some are not. Some numbers are numbers, some are spelled out.
I would love something that does a perfect parse/translation. But, would settle for something that does reasonably well to start.
Bonus question: after suggesting a strategy / tool, how would you go about it?
Thanks!
Joe
Short answer. Use GATE.
Long answer. You need some tool for pattern recognition in text. Something, that can catch patterns like:
{Number}{Space}{Ingredient}
{Number}{Space}{Measure}{Space}{"of"}{Space}{Ingredient}
{Number}{Space}{Measure}{Space}{"of"}{Space}{Ingredient}{"("}{Value}{")"}
...
Where {Number} is a number, {Ingredient} is taken from dictionary of ingredients, {Measure} - from dictionary measures and so on.
Patterns I described are very similar to GATE's JAPE rules. With them you catch text that matches pattern and assign some label to each part of a pattern (number, ingredient, measure, etc.). Then you extract labeled text and put it into single table.
Dictionaries I mentioned can be represented by Gazetteers in GATE.
So, GATE covers all your needs. It's not the easiest way to start, since you will have to learn at least GATE's basics, JAPE rules and Gazetteers, but with such approach you will be able to get really good results.
It is basically natural language parsing. (You did already stemming chicken[s].)
So basically it is a translation process.
Fortunately the context is very restricted.
You need a supportive translation, where you can add dictionary entries, adapt the grammar rules and retry again.
An easy process/work flow in this case is much more important than the algorithms.
I am interested in both aspects.
If you need a programming hand for an initial prototype, feel free to contact me. I did see, you are already working quite structured.
Unfortunately I do not know of fitting frameworks. You are doing something, that Mathematica wants to do with its Alpha (natural language commands yielding results).
Data mining? But simple natural language parsing with a manual adaption process should give fast and easy results.
You also can try Gexp.
Then you have to write rules as Java class such as
seq(Number, opt(Measure), Ingradient, opt(seq(token("("), Number, Measure, token(")")))
Then you have to add some group to capture (group(String name, Matcher m)) and extrat parts of pattern and store this information into table.
For Number, Measure you should use similar Gexp pattern, or I would recommend some Shallow parsing for noun phrase detection with words from Ingradients.
If you don't want to be exposed to the nitty-gritty of NLP and machine learning, there are a few hosted services that do this for you:
Zestful (disclaimer: I'm the author)
Spoonacular
Edamam
If you are interested in the nitty-gritty, the New York Times wrote about how they parsed their ingredient archive. They open-sourced their code, but abandoned it soon after. I maintain the most up-to-date version of it and I wrote a bit about how I modernized it.
Do you have access to a tagged corpus for training a statistical model? That is probably the most fruitful avenue here. You could build one up using epicurious.com; scrape a lot of their recipe ingredients lists, which are in the kind of prose form you need to parse, and then use their helpful "print a shopping list" feature, which provides the same ingredients in a tabular format. You can use this data to train a statistical language model, since you will have both the raw untagged data, and the expected parse results for a large number of examples.
This might be a bigger project than you have in mind, but I think in the end it will produce better results than a structured top-down parsing approach will.