2

I have a node with 450-500 fields which I have already splitted in small forms that are being load via ajax.

Anyway, when I get the node form before splitting it, the function _field_invoke (at field.attach.inc) is taking such a long time that makes the server return a timeout. I'm working in a 1 core 2.2MHz 3.5 GB

Is there any way to speed on this function? Otherwise, what alternatives do I have to speed on the load of a form with 450-500 fields?

EDIT (@Neograph734 comment)

We have a main form with 30 fields, most of them y-n that are used to select sub-forms. The form started to grow as the project was going on, and ended with 10 sub-forms form 30 to 50 fields each one.

We tried to split into different nodes and content types, but we could not find any viable solution: it must be a single document with digital signatures on each form that must be sync one each other, and the whole document follows a status that enables signatures to certain users (when a user has signed every signature field in all sub-forms, then the next user can start to sign). But in fact this is not the question here, as even if there were a better solution, we have no budget now to refactor the whole project, so we have to deal with a form of ~450 fields.

Right now we have rewritten drupal_build_form functionality to store every prepared sub-form in the cache and load them via ajax. So when a user requests the complete node, we give them the whole node but just the first 30 fields are rendered. We provide empty hidden <div>'s that will be filled via javascript with corresponding sub-forms, on demand.

Basically we keep the forms obtained after drupal_retrieve_form, drupal_prepare_form and drupal_process_form on the cache, but we assign a known cid and we store it via cache_set, so later on we can recover them, remove the fields that we don't want to render, render it and deliver it via ajax. In this way we do not render the whole form at once, but we do it on demand.

At first time we tried to remove the fields that were not going to be used by the user, but we found that we could not submit the form: Drupal said that there were missing fields (when a node is saved, the form must be submitted with all fields, even if they are with an empty value, otherwise it raises an error on node save).

So basically what we are doing is:

  • Node load (get via browser or ajax) -> look in cache_form table if we find pre-cached form or sub-form, their cid are like form_form-petra_node_form-p0, form_form-petra_node_form-pa, etc... and form_state_form-petra_node_form-p0 and so on.

  • If we find the pre-cached form, we load it and pass it through drupal_prepare_form, we remove not caching keys (form_state_keys_no_cache()) and then drupal_process_form. This is mostly the same as drupal_build_form does. Then we save the new form to cache_form (with cache_set, an expire time of 3 hours and a random generated cid as it would do drupal_build_form) in order to recover it later in post phase. If this is a sub-form, we merge the rendered sub-form with the parent one obtained via browser get (ajax is in charge of doing so).

  • If the form is not there, we prepare it from scratch and save it to cache_form as pre-prepared form with expire = 0. Then we follow the same way described just before. This will nearly never happen, as we have installed a cron task that runs once a day and checks if the pre-prepared forms are there or not, and if not, the job prepares them.

  • If it is a post, we recover the cached form with form_get_cache and we process it with drupal_process_form

So basically we have rewritten drupal_build_form in order to have "static pre-cached forms". This increased speed significatively but right now we are trying to achieve F1 speed with this system.

5
  • 1
    I'm not sure if I've ever had such a massive form. So I can't speak from experience. Could you try profiling your drupal with XHProf. That might tell you exactly where the bottleneck is. _field_invoke does a lot of things, and it calls a lot of other functions too.
    – Beebee
    Commented Jan 27, 2017 at 11:22
  • 2
    I have a node with 450-500 fields SAY WHAT??? :O. A node should never have this amount of fields. Whoever built this site definitely took the wrong approach.
    – No Sssweat
    Commented Jan 27, 2017 at 12:57
  • 1
    There is a distinction between fields and field values. Drupal 7 creates a new database table for every field, in which is stores the various values of that field. If you truly have 500 fields, SQL must join over 500 tables with the node table. I can imagine that kills your server... If you edit the question and explain the use-case we might be able to offer alternative solutions. Commented Jan 27, 2017 at 15:47
  • @Neograph734 see updated question
    – Miquel
    Commented Jan 30, 2017 at 8:20
  • 1
    Thanks Miquel, but this appears to be way over my head. I would probably create each subform as an Entityform and then tie them together in some multi-step form using entity reference. It would be more writes in the end, but the chunks would be smaller increasing the perception of speed. If you must deal with the situation as it is, I have no valuable advice. Commented Jan 30, 2017 at 11:43

1 Answer 1

2

I doubt that with some many fields for a single node you'll be able to "speed up that function". However, whenever time (and budget?) permits, you should consider what's mentioned in the (illuminating) article titled "Relativity Model for Drupal". This is an introduction to it (quoted from this linked page):

The Relativity Data Model for Drupal is a zero-custom-code, collection of steps, procedures and methods that strive to help site builders, users and site visitors interact with Drupal in a far easier and more efficient way. This is done by:

  • Data architecture and data modeling merging as a single step through a documentation procedure.
  • Customized user interfaces that cater to individual workflows throughout permission roles.
  • Multi-level relational data structures that relate to other multi-level relational structures.
  • Mimicking the concept of database joins within Drupal's UI's.
  • Vastly reducing the size of Drupal sites by a small handful of modules that provide greater power, speed and expansion capabilities.

Note the speed in the last item above ...

The small handful of modules (cfr. the last bullet) is like so (apart from Drupal core):

This same topic is also presented in the video "Revolutionary DRUPAL Data Modeling Concept!! (This will change your Drupal life!)".

1
  • The link does not work :(
    – Miquel
    Commented Jan 29, 2017 at 20:15

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.