Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

  • Isomorphic
    replied
    Nothing more is needed from you for now - we're going to try to figure out why that Reflection call is appearing in the middle of your DataSourceLoader processing, as it's probably possible for the framework to avoid it.

    Note that Reflection can be radically more or less expensive in different environments. One factor is a long classpath with duplicates, so you could look at reducing the cost of Reflection calls if you want.

    Leave a comment:


  • claudiobosticco
    replied
    Hello, are you investigating this problem, or do you need more debugging by my side?

    Leave a comment:


  • claudiobosticco
    replied
    Originally posted by claudiobosticco View Post
    which so far seems relative to fields with validators using <applyWhen>, or to fields with custom simple types which I have defined, ie like:
    actually they're relative to fields with validators using <applyWhen>, and to the loading of my custom Simple Types xml definitions

    Leave a comment:


  • claudiobosticco
    replied
    as a side note, only on first load I've got a bunch of logs like these:

    Code:
    WARN DefaultValidators Field 'name' not found in data source 'ServerObject'
    WARN DefaultValidators Field 'name' not found in data source 'AdvancedCriteria'
    WARN DefaultValidators Field 'name' not found in data source 'Criterion'
    which so far seems relative to fields with validators using <applyWhen>, or to fields with custom simple types which I have defined, ie like:

    Code:
    <SimpleType name="trimText" inheritsFrom="text" editorType="TextItem">
        <validators>
            <validator type="serverCustom">
                <serverObject lookupStyle="new" className="com.my.types.TrimDMI"/>
            </validator>
        </validators>
    </SimpleType>

    Leave a comment:


  • claudiobosticco
    replied
    Nope to both questions.

    Actually I see many calls to Reflection.findMethod, as in this debugger screenshot:

    Click image for larger version

Name:	2024-01-02 22.35.22.jpg
Views:	64
Size:	52.0 KB
ID:	271474

    smartClient version is 'v13.0p_2023-12-08/Enterprise Deployment'

    Leave a comment:


  • Isomorphic
    replied
    Hmm, there normally should not be a Reflection call in that codepath. Do you have any custom (non-framework) properties in your .ds.xml definitions - anything that isn't just a simple String value? Or do you do anything like use DSField.put() to put custom objects into your fields or DataSource definition (note this wouldn't be valid, due to pooling).

    Leave a comment:


  • claudiobosticco
    replied
    Hello, about dataSource pooling, what I see is a log like this, for every dataSource, on first load:

    Code:
    DEBUG PoolableDataSourceFactory Created DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712' and assigned it to thread https-jsse-nio-8443-exec-8
    DEBUG PoolableDataSourceFactory Created DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712' in the pooling flow
    DEBUG PoolableDataSourceFactory Activated DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712'
    DEBUG PoolableDataSourceFactory Cleared and passivated DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712'
    on the second load I see this, for the same dataSources:

    Code:
    DEBUG PoolableDataSourceFactory Activated DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712'
    DEBUG PoolableDataSourceFactory Cleared and passivated DataSource 52 of type 'ANAG_GRAFICI_MATCH_ANALYSIS' with hashCode '145547712'
    does this seem correct?

    About the java profiler, unfortunately I'm not an expert, at a first glance it seems that a lot of time is spent in that _cloneConfigForSecurityAnnotations method, does this even make sense?


    Click image for larger version

Name:	2024-01-02 17.39.06.jpg
Views:	58
Size:	73.3 KB
ID:	271471
    Attached Files

    Leave a comment:


  • Isomorphic
    replied
    Pooling is on by default, with certain exceptions (like DynamicDSGenerator). As we mentioned, if you temporarily turn on pooling-related logs, you will see log messages about DataSources being borrowed and returned. Background here:

    https://smartclient.com/smartclient-...Implementation

    If you confirm that pooling has not been disabled, we would recommend using a Java profiler to see where the bottlenecks are. It's probably going to be something weird that no one could have guessed would be the culprit in advance.

    Leave a comment:


  • claudiobosticco
    replied
    about DataSource pooling: isn't it enabled by default?
    I've tried to add in server.properties file:
    datasources.pool.enabled = true
    but I don't see a difference. There's something else which may disable pooling? How can I verify if it's actually enabled and working?

    Leave a comment:


  • Isomorphic
    replied
    We're not sure how you're measuring the difference - seems like it would have to be with a stopwatch, where it's tough to measure a half-second difference - but there is a possible reason for it, since the number of DataSources being loaded is huge.

    Basically, with the DataSources generated into the JSP, it's likely your browser doesn't see the first byte of the HTML file until the JSP is completely finished executing on the server.

    When instead DataSources are loaded via a <script> tag, the JSP processing finishes quite quickly, and then the browser will load the SmartClient runtime (from cache) and execute it before execution is then blocked by waiting for the DataSourceLoader response.

    Technically, this shouldn't be faster, because you've just reordered the phases, and in the HTML spec, the browser must load and execute a <script> block before looking at any DOM past that script block, since the script block might modify that DOM.

    In practice, modern browsers do speculative execution much like modern CPUs. So if you were to compare timestamps, you would probably see that the browser speculatively kicked off the request to the DataSourceLoader while SmartClient was initializing. That effectively parallelizes SmartClient resource loading and initialization, as well as the loading and execution of anything else that appears before the DataSourceLoader <script> tag - that all happens concurrently with the long wait for the DataSourceLoader response. And there's your half-second.

    Some points to cover again though:

    1) your DataSourceLoader times are still abnormally high

    2) you can remove the entire server-side processing of DataSourceLoader if you cache the generated DataSources (it's just JS logic). This does require that either your DataSources are the same for every type of user (that is, they don't vary by role or tenantId) or that you pre-generate and cache all variants by role

    3) with 500 DataSources, there may be some natural ways to split up the loaded DataSources into sets so that some that aren't often used are only loaded on demand. But again, we would only look into this if your application has some clearly-defined "modules", because maintaining dynamic loading across a complex dependency tree usually isn't worth the hassle.

    Leave a comment:


  • claudiobosticco
    replied
    Thanks for the heads up, using the browser dev tools I see a similar round-trip time for the DataSourceLoader.

    I confirm that I'm not using a debugger, and that I'm measuring after many page refresh. I'll check on the DataSource pooling, but actually the application is always the same, I'm just switching the two types of loading in my index.jsp.

    I see a reload half a second faster with the DataSourceLoader. I'm testing with more than 500 DataSources.

    Leave a comment:


  • Isomorphic
    replied
    This sounds as though you are measuring the DataSourceLoader by looking at the amount of time that the JSP takes to write out the <script> tag. You would need to instead look at the network round-trip time for the DataSourceLoader URL using the browser's built-in Developer Tools.

    Also, 40ms for a large DataSource is abnormal. As previously mentioned, you should make sure you are measuring the 3rd - 5th attempt to load DataSources in order to allow various kinds of caching and pooling to occur. You should also:

    1) not run under a debugger when testing performance

    2) make sure you do not have excessive logging turned on

    3) make sure you haven't done something like disabled DataSource pooling entirely (you should see log messages related to DataSources being borrowed from pools, on the second and later load attempts)

    Leave a comment:


  • claudiobosticco
    replied
    Hello, I'm actually seeing a faster first render.

    I'm trying to measure the time needed to load DataSources using the loadDS tag, I hope this makes sense, my compilated JSP become something like:

    Code:
    long start = System.currentTimeMillis();
    
          out.write('\n');
          out.write('\n');
          out.write('\n');
          if (_jspx_meth_isomorphic_005floadDS_005f0(_jspx_page_context))
            return;
          out.write('\n');
    
        long end = System.currentTimeMillis();
        System.out.println("loadDS : " + (end - start));
        start = System.currentTimeMillis();
    
          out.write('\n');
          if (_jspx_meth_isomorphic_005floadDS_005f1(_jspx_page_context))
            return;
          out.write('\n');
    
        end = System.currentTimeMillis();
        System.out.println("loadDS : " + (end - start));
        start = System.currentTimeMillis();
    
          out.write("\n");
    where the methods like _jspx_meth_isomorphic_005floadDS_005f0 are like this:

    Code:
    private boolean _jspx_meth_isomorphic_005floadDS_005f0(javax.servlet.jsp.PageContext _jspx_page_context)
              throws java.lang.Throwable {
        javax.servlet.jsp.PageContext pageContext = _jspx_page_context;
        javax.servlet.jsp.JspWriter out = _jspx_page_context.getOut();
        // isomorphic:loadDS
        com.isomorphic.taglib.LoadDSTag _jspx_th_isomorphic_005floadDS_005f0 = (com.isomorphic.taglib.LoadDSTag) _005fjspx_005ftagPool_005fisomorphic_005floadDS_0026_005flocale_005fID_005fnobody.get(com.isomorphic.taglib.LoadDSTag.class);
        boolean _jspx_th_isomorphic_005floadDS_005f0_reused = false;
        try {
          _jspx_th_isomorphic_005floadDS_005f0.setPageContext(_jspx_page_context);
          _jspx_th_isomorphic_005floadDS_005f0.setParent(null);
          // /index.jsp(1282,0) name = ID type = null reqTime = true required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
          _jspx_th_isomorphic_005floadDS_005f0.setID("JASV_BI_xxxx_yyyyyyy");
          // /index.jsp(1282,0) name = locale type = null reqTime = true required = false fragment = false deferredValue = false expectedTypeName = null deferredMethod = false methodSignature = null
          _jspx_th_isomorphic_005floadDS_005f0.setLocale((java.lang.String) org.apache.jasper.runtime.PageContextImpl.proprietaryEvaluate("${param.locale}", java.lang.String.class, (javax.servlet.jsp.PageContext)_jspx_page_context, null));
          int _jspx_eval_isomorphic_005floadDS_005f0 = _jspx_th_isomorphic_005floadDS_005f0.doStartTag();
          if (_jspx_th_isomorphic_005floadDS_005f0.doEndTag() == javax.servlet.jsp.tagext.Tag.SKIP_PAGE) {
            return true;
          }
          _005fjspx_005ftagPool_005fisomorphic_005floadDS_0026_005flocale_005fID_005fnobody.reuse(_jspx_th_isomorphic_005floadDS_005f0);
          _jspx_th_isomorphic_005floadDS_005f0_reused = true;
        } finally {
          org.apache.jasper.runtime.JspRuntimeLibrary.releaseTag(_jspx_th_isomorphic_005floadDS_005f0, _jsp_getInstanceManager(), _jspx_th_isomorphic_005floadDS_005f0_reused);
        }
        return false;
      }
    and what I see is times in the order of 40+ milliseconds for the bigger dataSources (more than a hundred fields), and 2-4 milliseconds with dataSources small as:

    Code:
    <DataSource xmlns:fmt="WEB-INF/" xmlns="http://www.smartclient.com/schema"
                schema="mySchema"
                dbName="myDB"
                tableName="JASV_BI_xxxx_yyyyyyy"
                ID="JASV_BI_xxxx_yyyyyyy"
                dataSourceVersion="1"
                serverType="sql"
                requiresAuthentication="true"
                dropExtraFields="false"
    >
        <fmt:bundle basename="i18nMessages" encoding="utf-8"/>
        <fields>
            <field name="ID_SQUADRA" type="integer" hidden="true"/>
            <field name="NOME" type="text"/>
            <field name="NOME_INTERNAZIONALE" type="text"/>
            <field name="CATEGORIA" type="text"/>
        </fields>
    </DataSource>
    which seems to much considering that with DataSourceLoader I see 1ms to load *all* dataSources.

    Does this way of measuring makes sense? Is there something else I can investigate?
    Last edited by claudiobosticco; 22 Dec 2023, 13:31.

    Leave a comment:


  • Isomorphic
    replied
    We would not expect the JSP tag to be slower than a call to DataSourceLoader servlet, as the two codepaths are 95% identical. What you may be seeing is that the HTML of the page is returned more quickly to the browser, since the processing has shifted from JSP execution to a separate servlet call.

    However, in terms of how quickly the page actually appears (as in, rendered widgets) we would expect that to be basically identical, since none of your JavaScript code to create widgets and such will start to execute until after the DataSourceLoader call completes.

    Are you actually seeing a faster first render? That could possibly indicate some other core servlets or JVM problem, like not having enough threads.

    Leave a comment:


  • claudiobosticco
    replied
    Thanks for the throughout reply, for me there's definitely food for thought.
    Regarding point 4, we are currently authenticating using microsoftonline login, so I don't think it's feasible.

    Regarding the fact that I'm using this pattern:
    Code:
    <%@taglib uri="/WEB-INF/iscTaglib.xml" prefix="isomorphic" %>
    <%@taglib uri="/WEB-INF/fmt.tld" prefix="fmt" %>
    
    <script type="text/javascript" charset="UTF-8">
    <isomorphic:loadDS ID="myDS"/>
    ...
    </script>
    I've just tried to use the DataSourceLoader, instead, and it seems way faster. Does this make sense? I wasn't expecting it.

    Leave a comment:

Working...
X