Malloc()/free() performance in JNI C code 9-10x slower than C application

I posted this as a bug report, but thought it might be worth also seeking advice here.
I'm working on a product under Windows which is integrated using JNI to a 3rd party file format conversion C++ library which uses a lot of new/delete (malloc/free) calls. I found the performance to be dramatically slower when running under Java compared to a standalone executable.
After many steps, I eventually wrote a small C program which simply loops over many malloc/free calls for 16 bytes, and took an average time. I found when I run this C program in a cmd.exe window, it runs about 9-10 times faster than if it is executed via JNI (Java calls the routine just once).
I can only guess that the JVM is somehow over-riding malloc/free, but this is an extremely high performance penalty. I found under Java 6, the JNI code runs about 5x slower, which is an improvement, but still very slow.
Does anyone know if this behaviour is expected?
Cheers,
David
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
I would have expected that the performance of malloc/free to be the same regardless of whether my native code is executing inside a JNI call, or as an ordinary program.
ACTUAL -
For Java 1.5.0_0-b03, some example timings in milliseconds (Pentium 4 1.8GHz):
0.004461
0.004494
0.004498
For Java 1.6.0-b105:
0.002367
0.002375
0.002366
When run as a process in a cmd.exe window:
0.000487
0.000497
0.000489
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
Java code is just:
package com.nuix;
public class Test
    private static native void doit();
    public static void main(String[] args)
        System.loadLibrary("test.dll");
        doit();
}C code is as follows (#define JAVA when building test.dll).
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#define COUNT 10000000
void doit()
    DWORD t1 = GetTickCount();
    for (int i = 0; i < COUNT; i++)
        int *data = (int *)malloc(16);
        data[0] = i;
        free(data);
    DWORD t2 = GetTickCount();
    fprintf(stderr, "Malloc average time msec == %f\r\n", (double)(t2 - t1) / (double)(COUNT));
    fflush(stderr);
#ifdef JAVA
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT void JNICALL Java_com_nuix_Test_doit
  (JNIEnv *env, jclass klass)
    doit();
#ifdef __cplusplus
#endif
#endif
int main()
    doit();
}

The speed of which Java executes is highly dependent on what device you are running it on. For example we have noted that a number of our J2ME programs run very slowly on many Motorola implementations, however that exact same code runs increadible fast on Nokia phones.
You can't really make a broad sweeping statment like C# is faster than Java and vice versa. All you can really say is that on this specific device with this version of the VM running this application, C# is faster. Changing any of those parameters may result in a significantly different result.
Really it comes down to what does the device manufacturer really want to support. Nokia has put a lot of effort into their J2ME platforms. As a result, their VM implementations are getting better (and faster) with every release. Other manufacturers are not making this same kind of commitment and as a result, their handsets are less optimal for running J2ME applications.
So I guess the short answer is. Your question cannot be answered until you identify the version of the device, and the specific version of the VM you ran your test on.
By the way, if you ran it on an Emulator, all bets are off. Performance on the Emulator and performance are usually different and can be significantly different.
Cheers,
Angus

Similar Messages

  • Is the performance of iOS 6 on iPhone 4 slower than iOS 5?

    Is the performance of iOS 6 slower than iOS 5 on iPhone 4 (GSM) ?

    I haven't upgraded after a visit to my local Apple store. On playing with the iPhone 5, I found Safari to be very slow so I logged on to their wifi on my 4s running 5.1.1 and loaded the same uncashed webpage on both. iPhone 5 18 seconds and my 4s 8.5!
    Hmm, I then tried the same with 2 other 5s, exactly the same. Next I tried a demo 4s running 5.1.1 and it was he same as mine.
    Lastly, today I tried a friend's 4s  running ios6 and it was way slower than the iPhone 5s in the Apple store.
    Conclusion? Keep away from ios 6 for now.

  • Erratic hotspot performance -- sometimes the same code is 60% slower

    I'm one of the developers on Apache Lucene, trying to run performance
    tests of Lucene's new near real-time search feature...
    But, I'm getting erratic behaviour out of the hotspot compiler,
    whereby the compiled code can run up to ~60% slower depending on what
    code has run before it, which really makes my testing hard!
    Somehow, hotspot seems to get tricked into compiling the code very
    badly, and then never recompiles it.
    I'm running with JDK 1.6.0_17-b04, on a CentOS 5.4 (Linux) box. I run
    java like this:
    java -server -Xms1g -Xmx1g
    I've tried various advanced -XX options to try to workaround this,
    to no avail.
    After whittling down my test, I managed to get a very simple
    standalone test (depends only on the Lucene 3.0 JAR) that shows the
    problem. The test first runs unrelated "warmup" code, then runs a
    fixed search test multiple times, printing the fastest run.
    There are 4 options for "warmup", and when I run the test with each of
    these 4, it runs as fast as 726 msec and as slow as 1160. The numbers
    are very stable (low noise) so I'm pretty sure this is accurately
    measuring what hotspot had compiled.
    I turned on -XX:+PrintOptoAssembly (downloaded the fastdebug JDK), and
    it's really weird -- even very low level methods like readVInt (reads
    a variable-length encoded integer, a serious hot spot in Lucene) was
    compiled differently, depending on what code ran during "warmup".
    Any ideas? For my testing I really just want consistency, but, going
    forward I also would like to somehow "bias" hotspot to not produce the
    60% slower compiled code...

    Thanks!
    The "compilation planning", and whole discussion/referenced papers
    from there, are very interesting. It sounds like I'm indeed running
    up against the complexities in the implicit "performance model" from
    Java.
    I just wish I had a simple way to "manage", or even understand
    the differences. I'll try to study the output of
    -XX:+PrintCompilation to see if I can gain any insight.... but this
    situation pretty much makes it impossible for me to do the performance
    testing I had wanted to do (the 60% perf hit due to different hotspot
    decisions completely obliterates what I'm trying to measure!).

  • Performance ISSUE of JAVA Code

    Hello,
    We are having Delphi application. But as per our requirements we have to migrated the Delphi code to java. We have done this but it is consuming the 3 times more time as compare to Delphi Application.
    We have used simple primitive types and arrays. But there are some loops which runs 4-8lac (800000) times.
    Colud you please suggest me some ways to improve the performance, as it is very critical for me ?
    Thanks,
    Satbir

    We have done this but it is consuming the 3
    times more time as compare to Delphi Application.
    We have used simple primitive types and arrays. But
    there are some loops which runs 4-8lac (800000)
    times.Sometimes trying too hard will make things slower.
    I have some suggestions:
    1) Do not inline functions yourself. This will in the best case have no effect and in the worst case make your code buggy. If your code is written according to good object-oriented methods it is probably not even possible.
    2) Don't flog the garbage collector. If your inner loop creates new objects, don't release them for the collector to clean up. Instead put them in a free list and reuse them. For general coding this isn't such a great idea, because the collector can reclaim objects about as efficiently as you can recycle them yourself. But inside a tight loop it can help a lot.
    2.1) Objects with finalizers are slow to garbage collect. Avoid finalizers in performance-critical code. (You can use classes that have finalizers, you just don't want them to be garbage collected while in tight code). Some of the classes provided by the Java API have finalizers also.
    3) Try using the server VM.
    4) Try different versions of the JDK. Some people have found that 1.4 is slower than 1.3, others find it is faster. Both are much faster than 1.2.
    5) String operations in Java are very slow. Much slower even than they usually are. StringBuffers can be 4-5 times faster than Strings, but even then string handling is just not fast. See if you can minimize the amount of string handling in your tight loops.
    6) Synchronization is quite slow also. It is faster in 1.4, but it is still slow. Don't synchronize unless absolutely necessary. Some synchronized operations can be done instead with volatile variables, unfortunately many things cannot.
    7) Make sure you have enough heap space for everything to fit comfortably. If the garbage collector is running during a tight loop, this will kill your performance.
    8) Some of the calls to the Java API are very slow. Some standard API classes, such as Hashtable, have synchronized methods, which can cause hidden slowing. Other functions are just plain slow in general.
    9) Try using the -Xrunhprof option to profile your code. While it will run much more slowly with the profiler enabled, it will at least indicate where the slowness is. It might not be what you expect.

  • Why do i need to enter the credit card information for downloading free apps and redeem the codes?

    getting a message says apple id has not yet been used with the itunes store while trying to download apps
    why do i need to enter the credit card information for downloading free apps and redeem the codes?

    As a security precaution, Apple verifies your billing credentials with every transaction whether paid or free apps or using the balance of a redeemed code.

  • Performance for the below code

    Can any one help me in improving the performance for the below code.
    FORM RETRIEVE_DATA .
    CLEAR WA_TERRINFO.
    CLEAR WA_KNA1.
    CLEAR WA_ADRC.
    CLEAR SORT2.
    *To retrieve the territory information from ZPSDSALREP
    SELECT ZZTERRMG
           ZZSALESREP
           NAME1
           ZREP_PROFILE
           ZTEAM
         INTO TABLE GT_TERRINFO
         FROM ZPSDSALREP.
    *Preparing Corporate ID from KNA1 & ADRC and storing it in SORT2 field
    LOOP AT GT_TERRINFO INTO WA_TERRINFO.
      SELECT SINGLE * FROM KNA1 INTO WA_KNA1
                      WHERE KUNNR = WA_TERRINFO-SALESREP.
      SELECT SINGLE * FROM ADRC INTO WA_ADRC
                      WHERE ADDRNUMBER = WA_KNA1-ADRNR.
      IF NOT WA_ADRC-SORT2 IS INITIAL.
      CONCATENATE 'U' WA_ADRC-SORT2 INTO SORT2.
      MOVE SORT2 TO WA_TERRINFO-SORT2.
    MODIFY GT_TERRINFO1 FROM WA_TERRINFO.
      APPEND WA_TERRINFO TO GT_TERRINFO1.
      CLEAR WA_TERRINFO.
      ENDIF.
      CLEAR WA_KNA1.
      CLEAR WA_ADRC.
    ENDLOOP.
    ENDFORM.                    " RETRIEVE_DATA

    Hi
    The code is easy so I don't think you can do nothing, only u can try to limit the reading of KNA1:
    FORM RETRIEVE_DATA .
      CLEAR WA_TERRINFO.
      CLEAR WA_KNA1.
      CLEAR WA_ADRC.
      CLEAR SORT2.
    *To retrieve the territory information from ZPSDSALREP
      SELECT ZZTERRMG
      ZZSALESREP
      NAME1
      ZREP_PROFILE
      ZTEAM
      INTO TABLE GT_TERRINFO
      FROM ZPSDSALREP.
      SORT GT_TERRINFO BY SALESREP.
    *Preparing Corporate ID from KNA1 & ADRC and storing it in SORT2 field
      LOOP AT GT_TERRINFO INTO WA_TERRINFO.
        IF KNA1-KUNNR <> WA_KNA1-KUNNR.
          SELECT SINGLE * FROM KNA1 INTO WA_KNA1
               WHERE KUNNR = WA_TERRINFO-SALESREP.
          IF SY-SUBRC <> 0.
            CLEAR: WA_KNA1, WA_ADRC.
          ELSE.
            SELECT SINGLE * FROM ADRC INTO WA_ADRC
                                     WHERE ADDRNUMBER = WA_KNA1-ADRNR.
            IF SY-SUBRC <> 0. WA_ADRC. ENDIF.
          ENDIF.
        ENDIF.
        IF NOT WA_ADRC-SORT2 IS INITIAL.
          CONCATENATE 'U' WA_ADRC-SORT2 INTO SORT2.
          MOVE SORT2 TO WA_TERRINFO-SORT2.
    * MODIFY GT_TERRINFO1 FROM WA_TERRINFO.
          APPEND WA_TERRINFO TO GT_TERRINFO1.
          CLEAR WA_TERRINFO.
        ENDIF.
      ENDLOOP.
    ENDFORM. " RETRIEVE_DATA
    If program takes many times to upload the data from ZPSDSALREP, you can try to split in sevaral packages:
    SELECT ZZTERRMG ZZSALESREP NAME1 ZREP_PROFILE ZTEAM
      INTO TABLE GT_TERRINFO PACKAGE SIZE <...>
      FROM ZPSDSALREP.
      SORT GT_TERRINFO BY SALESREP.
    *Preparing Corporate ID from KNA1 & ADRC and storing it in SORT2 field
      LOOP AT GT_TERRINFO INTO WA_TERRINFO.
        IF KNA1-KUNNR <> WA_KNA1-KUNNR.
          SELECT SINGLE * FROM KNA1 INTO WA_KNA1
               WHERE KUNNR = WA_TERRINFO-SALESREP.
          IF SY-SUBRC <> 0.
            CLEAR: WA_KNA1, WA_ADRC.
          ELSE.
            SELECT SINGLE * FROM ADRC INTO WA_ADRC
                                     WHERE ADDRNUMBER = WA_KNA1-ADRNR.
            IF SY-SUBRC <> 0. WA_ADRC. ENDIF.
          ENDIF.
        ENDIF.
        IF NOT WA_ADRC-SORT2 IS INITIAL.
          CONCATENATE 'U' WA_ADRC-SORT2 INTO SORT2.
          MOVE SORT2 TO WA_TERRINFO-SORT2.
    * MODIFY GT_TERRINFO1 FROM WA_TERRINFO.
          APPEND WA_TERRINFO TO GT_TERRINFO1.
          CLEAR WA_TERRINFO.
        ENDIF.
      ENDLOOP.
    ENDSELECT.
    Max

  • Performance issue in this code

    public int[][] init(int[][] a, int m, int n){
      for(int j=0; j<n; j++){
        for(int i=0; i<m; i++){
          a[i][j] = i+j;
      return a;
    }Just a technical quest faced in one of the interview...
    There is a performance issue in this code. Can you identify, correct and justify your answer?
    Edited by: EJP on 17/10/2011 20:29

    mithu wrote:
    public int[][] init(int[][] a, int m, int n){
    for(int j=0; j<n; j++){
    for(int i=0; i<m; i++){
    a[i][j] = i+j;
    return a;
    }Just a technical quest faced in one of the interview...
    There is a performance issue in this code. Can you identify, correct and justify your answer?Not a good question at all. There's no performance issue here that can be positively identified by inspection. The only potentially significant one is, as EJP pointed out, loss of locality of reference because of the order of the loops. But even that's not a guarantee, since I don't think array layouts are defined by the spec. We could only determine for sure that that's a performance problem by profiling.

  • When I try to download a app even for free it says my security code is wrong on my credit card but it is not wrong why is it doing that?

    When I try to download a app even for free it says my security code is wrong on my credit card but it is not wrong why is it doing that?

    Is the address on your iTunes account exactly the same (format and spacing etc) as on your credit card bill : http://support.apple.com/kb/TS1646 ? If it is then you could try what it says at the bottom of that page :
    If the issue persists, contact your credit card company and verify that they and any company they use to process credit card authorisations have the correct information on file.
    And/or try contacting iTunes support : http://www.apple.com/support/itunes/contact/ - click on Contact iTunes Store Support on the right-hand side of the page

  • Malloc: *** mmap(size=16777216) failed (error code=12)

    Hi All,
    I am writing a small game for iphone. It has about 18 levels. After running 8 levels or so It is giving following error
    malloc: * mmap(size=16777216) failed (error code=12)
    * error: can't allocate region
    * set a breakpoint in mallocerrorbreak to debug
    I have googled it but no luck at all. Any helper pointers will be greatly appreciated.
    Thanks in Advance
    - Ravi

    ooftish.com wrote:
    I have googled it but no luck at all.
    When you search on these topics, you should delete the number strings/errors such as 16777216 - those are specific to you.
    As an example, googling: malloc: mmap(size=
    ...seems to find more than one thread that discusses this back in 2008.

  • Trying to download free photoshop and received error code 148:3 can you help

    Need help tying to download free photoshop and receiving error code 148:3

    Something is preventing the licensing from working. Make sure to run with sufficient user privileges and file permissions.
    Mylenium

  • JVM dies when JNI native code causes a SIGABRT from assertions

    Hi,
    I am wondering whether there is a way to prevent the JVM from dying when the JNI native code hits an assertion.
    #include "NativeTest.h"
    #include <assert.h>
    JNIEXPORT jstring JNICALL Java_NativeTest_sayHello (JNIEnv *env, jobject thisobject, jstring js)
    assert(0);
    return js;
    Calling this code from Java through JNI causes a SIGABRT when assert(0) is hit. This causes the java program to terminate. Is there a way for the JVM to recover from the SIGABRT from the native code?

    929919 wrote:
    I am wondering whether there is a way to prevent the JVM from dying when the JNI native code hits an assertion.There is no way to prevent the VM from exiting if native code does anything that causes an exit.
    An assertion is only one way that can happen.
    So to prevent the VM from exiting - don't run native code. The safe way to execute OS native library is to do the following.
    1. Wrap the library in an executable.
    2. Create a communications API for the executable.
    3. Manage the executable via Java Runtime.exec/ProcessBuilder.
    4. Talk to the executable using the communications API from 2 in the java code.
    The above is safe because if the library exits it exits the executable, not the VM.

  • Free performance-profile tool ?

    Hi Folks,
    Might anyone know of a good and free performance profile tool ?
    I am looking for something like Candle, Intrascope or Mercury 'Deep Diagnostics'.
    I've just seen a list on http://www.javaperformancetuning.com/resources.shtml
    anyone used these ?
    thanks!
    JM

    "Marmelstein" <[email protected]> wrote in message news:40bd9e54$1@mktnews1...
    I should add that I'm more interested in application-level stuff than the JVM.
    The kind of thing I'd really like to see is (for example) lots of time is spent
    in a particular ejb 'find' method.
    Hi Folks,
    Might anyone know of a good and free performance profile tool ?
    I am looking for something like Candle, Intrascope or Mercury 'Deep Diagnostics'.
    I've just seen a list on http://www.javaperformancetuning.com/resources.shtml
    anyone used these ?
    I'd get a commercial one. Usually such tools pay off after the first use.
    Regards,
    Slava Imeshev

  • Performance of Java math code vs. Python

    Hello,
    Not to spark a religious war, but I'm curious: The November 2008 issue of Linux Journal has an article about Scientific Computing. In it, the author demonstrates how to use Python for doing number crunching. He compared Python to C. So I want to compare Python to Java.
    I did this: created a file called matrix.py . Its contents are:
    import numpy
    a1=numpy.empty((500,500))
    a2=numpy.empty((500,500))
    a3=a1*a2Then I ran it, by doing:
    time python matrix.py...on multiple occasions. I'm doing this on a Fedora 9 machine and figure it will buffer the disk read of the python interpreter. Anyway, it finishes in about 0.18 seconds (realtime).
    Subsequently, I created a similar piece of Java code:
    public class Test {
         public static void main(String args[]) {
              long start=System.currentTimeMillis();
              double a1[][]=new double[500][500];
              double a2[][]=new double[500][500];
              double a3[][]=new double[500][500];
              int i, j, k;
              for (i=0; i<500; i++) {
                   for (j=0; j<500; j++) {
                        a3[i][j]=0;
                        for (k=0; k<500; k++) {
                             a3[i][j] += a1[i][k] * a2[k][j];
              long end=System.currentTimeMillis();
              end = end - start;
              System.out.println("Duration: " + end);
    }...For Java, I didn't use time(1) to time the run, rather I used System.out.println from within the code. This is because I don't use Python so I didn't want to spend the time to learn how to do the time math as I did above, and also I figure that in everyday use the load time of the JVM would incur a startup penalty which I didn't want to measure. In short, I deliberately put Python at a disadvantage because I'm lazy. I figured I could learn a little Python and correct the issue if necessary.
    Turns out, it's not necessary, because the Java code takes 1.5 seconds! That's 8-9 times slower than Python on this multiplication problem. What gives? Is Java just that slow? I thought that by this day and age it would be fairly optimized...
    Thanks for the cluestick, in advance... :-)
    -Hushpuppy

    Thanks mlk and sabre150. It turns out, numpy is an optimized math package. To really run a test, I'd have to compare numpy to say JScience (http://jscience.org/). So I'm comparing apples to oranges.
    Anyway. Just for fun, I ran the code a few times so the JIT could do its thing. Doesn't seem to be doing a lot of optimization; my guess is there's not a lot more it could do. Here's what I got:
    Output:
    Duration: 1123
    Duration: 1107
    Duration: 1086
    Duration: 1087
    Duration: 1081
    Duration: 1083
    Duration: 1079
    Duration: 1087
    Duration: 1079
    Duration: 1081Program:
    public class Test {
         //double a1[][]=new double[500][500];
         //double a2[][]=new double[500][500];
         //double a3[][]=new double[500][500];
         static int a1[][]=new int[500][500];
         static int a2[][]=new int[500][500];
         static int a3[][]=new int[500][500];
         static long start;
         static long end;
         static int i, j, k;
         public static void multiply() {
              start=System.currentTimeMillis();
              for (i=0; i<500; i++) {
                   for (j=0; j<500; j++) {
                        a3[i][j]=0;
                        for (k=0; k<500; k++) {
                             a3[i][j] += a1[i][k] * a2[k][j];
              end=System.currentTimeMillis();
              end = end - start;
              System.out.println("Duration: " + end);
         public static void main(String args[]) {
              int l;
              for (l=0; l<10; l++) {
                   multiply();
    }

  • Flickr API and cflickr - performance issue with my code.

    I using cflickr to access the Flickr api and display photos in a lightbox. My code is working, but incredibly slow. I'm assuming that I'm going about it in an incorrect way and hoping someone can point out a better way to do what I'm trying to accomplish. My speed issues develop when I'm trying to extract the image descriptions within a loop that is outputing the images to the page.
    Here is an example of the code that I'm using:
    using the following to grab the photos:
    <cfset photos = cflickr.photosets_getPhotos(photoset_id=72157624340881708 , auth_token=token) />
    I am then using the following to loop through the array of photos and and also retrieve the description for each image.
    <div style="width:423px; margin: auto;" id="gallery">
            <cfloop from="1" to="#arraylen(photos.photoset.photo)#" index="i">
                <cfset p = photos.photoset.photo[i] />
                <cfset img_desc = cflickr.photos_getInfo(photo_id=p.id).photo.description />
                <cfset img_desc = replace(img_desc, 'TRIP', '<br />TRIP') />
                <cfset title = photos.photoset.photo[i].title />
                <cfset title = title & "<br />" & img_desc />
                <cfoutput>
                <a href="#cflickr.getPhotoUrl(p, '')#" title="#title#"><img src="#cflickr.getPhotoUrl(p, 's')#"  /></a>
                </cfoutput>
            </cfloop>
        </div>
    The problem with the code is when it is making the request for img_desc inside of the loop to the Flickr api. Each instance of that call is taking on average 300 to 400ms and the array has over 300 items so it times out. Should I be retrieveing all of the image descritpions at once before the loop and if so how would I best link these with image data that they belong with? It seems like I'm going about this in a rather inefficient manner.
    I was hoping that I could call a function that retrieved all of the data that I need in one call, but so far I've been unable to find that.

    ( Grrr... this forum trashes emails better than any application I have ever seen.  Here is what my previous response actually said ...)
    <cfset photos = cflickr.photosets_getPhotos(photoset_id=72157624340881708 , auth_token=token)>
    I cannot say I have used it. But the cfc usage seems to follow the API pretty closely. So I took a quick look at the flickr forums, and one person suggests you can grab the descriptions too by adding the "extras" parameter.
    http://www.flickr.com/groups/api/discuss/72157594456853637/#comment72157623785775034
    So try using:
        <cflickr.photosets_getPhotos(photoset_id=72157624340881708 ,
             auth_token=token, extras="description")>

  • Performance issues. Took out EVENT.ADDED_TO_STAGE, Slower!?

    I don't understand. I went through all my code doing the following:
    init() {
         this.addEventListener(Event.ADDED_TO_STAGE, stageReady);
         this.addEventListener("creationComplete", creationComplete);
    public function creationComplete(event:Event=null):void {
         this.removeEventListener("creationComplete", creationComplete);
    public function stageReady(event:Event=null):void {
         this.removeEventListener(Event.ADDED_TO_STAGE, stageReady);
    Now my app runs super slow! Even slower than before. This isn't making any since ... I read this was supposed to help free up memory!!

    I have gone in and checked the box next to Perform Grouping on Server. The check box next to Use Index or Servers for Speed was already checked. The Links for the subreport are set up as follows.
    For subreport: Supported vs. Unsupported (This one comes from the ComputerSystem table)
    Container Report fields to link to: AST_AssetPeople.Asset_ID
    AS_AssetPeople.Asset_ID field link-
    Subreport parameter field to use: ?Pm-AST_AssetPeople.Asset_ID_
    Select data in subreport based on field: AST_ComputerSystem.Asset_ID_
    Asset ID is the only field that I found that the two tables have in common. I believe that I have the links set up correctly, but I could be wrong.
    Either way, I am still having the same problems.

Maybe you are looking for