As $node is based upon the EntityInterface now, let's leverage $node->label() instead of going with the hard-coded title property when linking to a node.

In conjunction with #1616952: Add a langcode parameter to EntityInterface::label(), this is going to help make the title appear properly translated. Also it brings in possible alterability of the node's label via changing the label key/property.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

fago’s picture

Issue tags: +Entity system, +D8MI, +sprint

adding tags

rvilar’s picture

Assigned: Unassigned » rvilar

I'm working on this.

rvilar’s picture

Status: Active » Needs review
FileSize
96.09 KB

I attach a patch that solves this

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-3.patch, failed testing.

rvilar’s picture

Status: Needs work » Needs review
FileSize
96.2 KB

Patch that solves the test bot error

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-5.patch, failed testing.

rvilar’s picture

Status: Needs work » Needs review
FileSize
96.3 KB

This will be the correct one? ;)

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-7.patch, failed testing.

rvilar’s picture

Status: Needs work » Needs review
FileSize
96.3 KB
Gábor Hojtsy’s picture

Huge patch :) Looks good tough on a quick look-through.

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-9.patch, failed testing.

fago’s picture

I don't think we should convert *every* use of $node->title, but just those where we use $node->title to refer to the entity somewhere (e.g. linking to it). Places that explicitely work with the title should stay with the title property (which will need its own multi-lingual accessor as well), in particular if the title value is used during editing or querying.

E.g.:

+++ b/core/modules/book/book.admin.inc
@@ -135,15 +135,15 @@ function book_admin_edit_submit($form, &$form_state) {
-        $node->log = t('Title changed from %original to %current.', array('%original' => $node->title, '%current' => $values['title']));
+        $node->log = t('Title changed from %original to %current.', array('%original' => $node->label(), '%current' => $values['title']));

This speaks directly about the title changing, so should stay with the title. If label() would not point to the title anymore (can be altered) this would break.

+++ b/core/modules/comment/lib/Drupal/comment/Tests/CommentTokenReplaceTest.php
@@ -64,7 +64,7 @@ class CommentTokenReplaceTest extends CommentTestBase {
-    $tests['[comment:node:title]'] = check_plain($node->title);
+    $tests['[comment:node:title]'] = check_plain($node->label());

node:title should stay with the title as well.

+++ b/core/modules/field/field.api.php
@@ -2147,7 +2147,7 @@ function hook_field_storage_pre_insert($entity_type, $entity, &$skip_fields) {
-          'title' => $entity->title,
+          'title' => $entity->label(),

Same here. Everything that queries for the title should receive really title, the label might be altered.

+++ b/core/modules/comment/comment.pages.inc
@@ -36,7 +36,7 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
-  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->title, 'node/' . $node->nid)));
+  drupal_set_breadcrumb(array(l(t('Home'), NULL), l($node->label(), 'node/' . $node->nid)));

In breadcrumbs and page titles the label should be used as well, as it refers to the node. So that conversion is fine.

+++ b/core/modules/forum/forum.module
@@ -1165,12 +1166,12 @@ function template_preprocess_forum_topic_list(&$variables) {
-        $variables['topics'][$id]->title = check_plain($topic->title);
+        $variables['topics'][$id]->title = check_plain($topic->label());

I think $title in templates should remain pointing to the title though.
We might want to think about moving this to the label as well, but if we do so we should probably rename the variable too. So let's leave that out of scope for now.

rvilar’s picture

Status: Needs work » Needs review
FileSize
86.23 KB

I attach a patch that pass the tests and have the corrections made by fago.

@fago, can you check my new patch and make me some suggestions about the use of $node->title or $node->label()? I don't understand very well your previuos comment

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-13.patch, failed testing.

rvilar’s picture

Status: Needs work » Needs review
FileSize
84.67 KB

Fixed problems when applying the patch

aspilicious’s picture

Your patch conflicted with the system.test file. These tests are moved to another location and you forgot to fix those files. Thats why your new patch is smaller.

Gábor Hojtsy’s picture

Status: Needs review » Needs work

Still needs wok then?

fubhy’s picture

I found a few more usages of the title property (mostly in l() invocations and rdf). I did a regex against "node" and "title" in the same line and added everything (apart from the token stuff) that made sense I believe. I might have missed usages of the title attribute in loops where $item is used or in other cases though.

fubhy’s picture

Status: Needs work » Needs review

Status: Needs review » Needs work

The last submitted patch, node-title-replace-1616962-16.patch, failed testing.

rvilar’s picture

@fubhy There are some usages of $node->title that refers to the result of a query. In this cases we can't replace $node->title with $node->label() because it's a query result object instead of an entity object. I'm fixing this little problems. In short I'll attach a new patch

fubhy’s picture

Okay, I didn't think of that - It was more or less a blind regex. :)

I hope that it helped to identify a few leftover occurrences of the title property anyhow.

fgm’s picture

Status: Needs work » Needs review
FileSize
1.38 KB

Rerolled to take into account data coming from the DB.

aspilicious’s picture

I think you uploaded some kind of strange interdif :)

fgm’s picture

Indeed, here is the correct patch.

/me crosses fingers.

Status: Needs review » Needs work

The last submitted patch, node-title-label-1616962-24.patch, failed testing.

gaspaio’s picture

On #1616972: Replace $term->name with $term->label(), the latest patch leaves the term token "name" with the $term->name value, whereas the patch on #25 replaces the node "title" token with the $node->label() value.
We should probably make the same choice everywhere.
We can :
1) leave the old tokens and do not create new ones for $term->label() and $node->label().
2) leave the old tokens and create new ones for $term->label() and $node->label().
3) keep the old token names but replace their value with $term->label() and $node->label().

I created a follow-up on label() related tokens for $term and $node to continue this discussion : #1632720: Create tokens for entity labels.

In the meantime i think we should take the token changes out of the current patch for this issue.

fgm’s picture

Status: Needs work » Needs review

#25: node-title-label-1616962-24.patch queued for re-testing.

fgm’s picture

The test in #25 passes locally and the error happens in setUp() which the change didn't touch, so it looks like it could be a qa bot fluke, so retesting...

Rerolled without the term->label() change in forum admin.

fago’s picture

Status: Needs review » Needs work
+++ b/core/modules/field/field.api.php
@@ -2195,7 +2195,7 @@ function hook_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
-            'title' => $entity->title,
+            'title' => $entity->label(),

That's specifically querying for title, so it should go with the title.

+++ b/core/modules/forum/forum.module
@@ -529,7 +529,7 @@ function forum_field_storage_pre_insert($entity_type, $entity, &$skip_fields) {
           'nid' => $entity->nid,
-          'title' => $entity->title,
+          'title' => $entity->label(),

Same here.

+++ b/core/modules/forum/forum.module
@@ -565,7 +565,7 @@ function forum_field_storage_pre_update($entity_type, $entity, &$skip_fields) {
             'nid' => $entity->nid,
-            'title' => $entity->title,
+            'title' => $entity->label(),

Same here.

+++ b/core/modules/forum/forum.module
@@ -724,10 +724,11 @@ function forum_block_view_pre_render($elements) {
-    '#default_value' => !empty($node->title) ? $node->title : '',
+    '#default_value' => !empty($title) ? $title : '',

That's editing the node title, right? So it should load the node title as value as well, not possibly something else.

Then, in order to proof our approach I think it would make sense to run the tests with a small modifcation to the node class as well, i.e. modify the label method to return something else, not the title. That ensures we check for the label when the label is there and for the title when the title is there.

case 'title':
- $replacements[$original] = $sanitize ? check_plain($node->title) : $node->title;
+ $replacements[$original] = $sanitize ? check_plain($node->label()) : $node->label();

We shouldn't do that as this specifically refers to the title. We have now #1632720: Create tokens for entity labels for that.

fgm’s picture

Status: Needs work » Needs review
FileSize
85.65 KB

Here is for the rerolled patch.

fgm’s picture

Rerolled after yesternight's commits, just in case they broke something

Berdir’s picture

Status: Needs review » Needs work
+++ b/core/includes/database.incundefined
@@ -44,7 +44,7 @@ use Drupal\Core\Database\Query\Condition;
  * foreach ($result as $record) {
- *   // Perform operations on $node->title, etc. here.
+ *   // Perform operations on $node->label(), etc. here.

The context here is hard to see, but this might actually be wrong. Because it talks about performing operations, which implies changing something and you can't change title().

+++ b/core/modules/book/lib/Drupal/book/Tests/BookTest.phpundefined
@@ -142,7 +142,7 @@ class BookTest extends WebTestBase {
-      $this->assertRaw(l('<b>‹</b> ' . $previous->title, 'node/' . $previous->nid, array('html'=> TRUE, 'attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page')))), t('Previous page link found.'));
+      $this->assertRaw(l('<b>‹</b> ' . $previous->label(), 'node/' . $previous->nid, array('html'=> TRUE, 'attributes' => array('rel' => array('prev'), 'title' => t('Go to previous page')))), t('Previous page link found.'));

Usually, the rule is to fix CS on changed lines. We probably don't want to do this on a page of this size. Just wanted to note that there is a space missing after html.

+++ b/core/modules/forum/forum.moduleundefined
@@ -714,7 +714,11 @@ function forum_block_view_pre_render($elements) {
-    $elements['forum_more'] = array('#theme' => 'more_link', '#url' => 'forum', '#title' => t('Read the latest forum topics.'));
+    $elements['forum_more'] = array(
+      '#theme' => 'more_link',
+      '#url' => 'forum',
+      '#title' => t('Read the latest forum topics.'),

How is this change related?

+++ b/core/modules/poll/poll.pages.incundefined
@@ -1,4 +1,4 @@
-<?php
+  <?php

Accidental space in here.

+++ b/core/modules/poll/poll.pages.incundefined
@@ -37,6 +37,7 @@ function poll_page() {
   $output = '<ul>';
+  // We cannot use $node->label() here because $node comes straight from the DB.
   foreach ($queried_nodes as $node) {
     $output .= '<li>' . l($node->title, "node/$node->nid") . ' - ' . format_plural($node->votes, '1 vote', '@count votes') . ' - ' . ($node->active ? t('open') : t('closed')) . '</li>';

Can we open a follow-up for this? Loading nodes directly through queries is wrong, can lead to errors (trying to pass it to functions that now require a class) and should be fixed. Also for those below.

Berdir’s picture

Also, as pointed out in #1616972: Replace $term->name with $term->label() #13 and #19, we need to make sure that we only use label when we intend to print it out somehow. If we for example compare it (e.g. some test hooks), we should probably stick with node->title.

fgm’s picture

Follow up done at #1637358: poll.module should not query the node table directly.

Rerolled for #33. forum_block_view_pre_render() was mentioned in the #30 diff, but is indeed out of scope for this.

Berdir’s picture

Status: Needs work » Needs review
Berdir’s picture

Status: Needs review » Needs work
+++ b/core/modules/node/node.tokens.incundefined
@@ -130,7 +130,7 @@ function node_tokens($type, $tokens, array $data = array(), array $options = arr
         case 'title':
-          $replacements[$original] = $sanitize ? check_plain($node->title) : $node->title;
+          $replacements[$original] = $sanitize ? check_plain($node->label()) : $node->label();

According to #30, this shouldn't be changed. It makes sense for comment:node, because we can safely assume that we want the label there.

+++ b/core/modules/node/tests/modules/node_test/node_test.moduleundefined
@@ -126,15 +126,15 @@ function node_test_node_grants_alter(&$grants, $account, $op) {
 function node_test_node_presave(Node $node) {
-  if ($node->title == 'testing_node_presave') {
+  if ($node->label() == 'testing_node_presave') {

I think this one should still reference to the title, as mentioned above.

+++ b/core/modules/node/tests/modules/node_test/node_test.moduleundefined
@@ -126,15 +126,15 @@ function node_test_node_grants_alter(&$grants, $account, $op) {
   // Determine changes.
-  if (!empty($node->original) && $node->original->title == 'test_changes') {
-    if ($node->original->title != $node->title) {
+  if (!empty($node->original) && $node->original->label() == 'test_changes') {
+    if ($node->original->label() != $node->label()) {
       $node->title .= '_presave';

@@ -145,8 +145,8 @@ function node_test_node_presave(Node $node) {
   // Determine changes on update.
-  if (!empty($node->original) && $node->original->title == 'test_changes') {
-    if ($node->original->title != $node->title) {
+  if (!empty($node->original) && $node->original->label() == 'test_changes') {
+    if ($node->original->label() != $node->label()) {
       $node->title .= '_update';

+++ b/core/modules/node/tests/modules/node_test_exception/node_test_exception.moduleundefined
@@ -12,7 +12,7 @@ use Drupal\node\Node;
 function node_test_exception_node_insert(Node $node) {
-  if ($node->title == 'testing_transaction_exception') {
+  if ($node->label() == 'testing_transaction_exception') {
     throw new Exception('Test exception for rollback.');

Same.

+++ b/core/modules/tracker/tracker.pages.incundefined
@@ -70,6 +70,7 @@ function tracker_page($account = NULL, $set_title = FALSE) {
+         // Do not use $node->label(), $node comes straight from the DB.

We usually don't abbreviate, so this should be database.

We should keep track of all these cases, not just poll. Not sure if we want to open separate issues or a single meta issue that just lists all cases for now. As far as I can see, there is one in statistics, search and tracker (+ poll).

fgm’s picture

Status: Needs work » Needs review
FileSize
81.57 KB

Added the note about the other node queries in the other issue.

Patch rerolled.

webflo’s picture

Assigned: rvilar » Unassigned
Status: Needs review » Reviewed & tested by the community
+++ b/core/modules/node/node.moduleundefined
@@ -2010,7 +2011,7 @@ function node_type_page_title($type) {
 function node_page_title(Node $node) {
-  return $node->title;
+  return $node->label();

Lets get rid of node_page_title() and use it with entity_page_label() in a follow-up issue. Otherwise its good.

fago’s picture

Status: Reviewed & tested by the community » Needs work
+++ b/core/modules/node/node.api.php
@@ -1098,11 +1098,12 @@ function hook_prepare(Drupal\node\Node $node) {
+  $title = $node->label();
 
   $form['title'] = array(
     '#type' => 'textfield',
     '#title' => check_plain($type->title_label),
-    '#default_value' => !empty($node->title) ? $node->title : '',
+    '#default_value' => !empty($title) ? $title : '',

That's a bad example as it would overwrite the title with the label.

+++ b/core/modules/node/node.module
@@ -1330,7 +1331,7 @@ function template_preprocess_node(&$variables) {
-  $variables['title']     = check_plain($node->title);
+  $variables['title']     = check_plain($node->label());

That would make $title contain the label, would is confusing in case the label is altered to something else. Let's better leave introducing the label to a template to a follow-up.

+++ b/core/modules/node/node.module
@@ -3525,7 +3526,7 @@ function node_content_form(Node $node, $form_state) {
+      '#default_value' => $node->label(),

+++ b/core/modules/system/system.api.php
@@ -3819,7 +3819,7 @@ function hook_tokens($type, $tokens, array $data = array(), array $options = arr
         case 'title':
-          $replacements[$original] = $sanitize ? check_plain($node->title) : $node->title;
+          $replacements[$original] = $sanitize ? check_plain($node->label()) : $node->label();

That would break the node:title token once the label is something else.

+++ b/core/modules/translation/translation.module
@@ -287,7 +287,7 @@ function translation_node_prepare(Node $node) {
-    $node->title = $source_node->title;
+    $node->title = $source_node->label();

Same here,

Schnitzel’s picture

Assigned: Unassigned » Schnitzel

will fix this

fgm’s picture

Status: Needs work » Needs review
FileSize
79.63 KB

Followup to label()-based tokens in addition to title is #1632720: Create tokens for entity labels.

Rerolled patch. (Tests pass locally for node and translation).

Schnitzel’s picture

looks good for me, as we found out it has still some missing things like in the forum, where not $node->title is used

But as @Berdir said in #1616972: Replace $term->name with $term->label() I would create a follow up, how we handle these changes in template files.

fgm’s picture

That would probably be especially true now that we will be rewriting all templates for twig anyway.

Followup in #1642070: Make use of entity labels in templates.

fago’s picture

Assigned: Schnitzel » Unassigned
Status: Needs review » Needs work
+++ b/core/modules/poll/poll.module
+++ b/core/modules/poll/poll.module
@@ -233,7 +233,7 @@ function poll_form(Node $node, &$form_state) {

@@ -233,7 +233,7 @@ function poll_form(Node $node, &$form_state) {
     '#type' => 'textfield',
     '#title' => check_plain($type->title_label),
     '#required' => TRUE,
-    '#default_value' => $node->title,
+    '#default_value' => $node->label(),

This makes the label default value for the node title, but that's wrong. The title needs to keep its value, thus it needs to stay with $node->title.

+++ b/core/modules/poll/poll.module
@@ -789,7 +789,7 @@ function poll_preprocess_block(&$variables) {
-  $variables['title'] = check_plain($form['#node']->title);
+  $variables['title'] = check_plain($form['#node']->label());

Another template issue.

+++ b/core/modules/system/system.api.php
@@ -2003,7 +2003,7 @@ function hook_mail($key, &$message, $params) {
-      '%title' => $node->title,
+      '%title' => $node->label(),

As for tokens, this refers explicitly to the title. So I think we should handle it the same way it keep it as title for now.

fgm’s picture

Status: Needs work » Needs review
FileSize
78.27 KB

Rerolled accordingly.

Maybe we want to introduce a %label in system.api.php#hook_mail() to show that this method can be used when composing mails as an alternative to the raw title ?

fago’s picture

Status: Needs review » Reviewed & tested by the community

@system mail label:
I think we want to create a solution which is inline with the solution of #1632720: Create tokens for entity labels here, so let's postpone that for now.

@patch: Looks good to me now, given bot gives green lights.

chx’s picture

Wow, quite the work! Thanks. Benchmarks? Do we need them?

Gábor Hojtsy’s picture

Gábor Hojtsy’s picture

@chx: Because the label will be multilingual, you either need an accessor method or magic getter/setter for it. Since we are directly using the method here, not even a magic getter, not sure how could we get the same functionality with better performance. Any ideas?

Status: Reviewed & tested by the community » Needs work

The last submitted patch, 0001-Issue-1616962-replace-node-title-with-node-label.patch, failed testing.

kalman.hosszu’s picture

Status: Needs work » Needs review
FileSize
75.45 KB

I attached a newer version of the patch.

Status: Needs review » Needs work

The last submitted patch, 1616962-52.patch, failed testing.

kalman.hosszu’s picture

Status: Needs work » Needs review
FileSize
878 bytes
75.45 KB

Fixing typo.

Gábor Hojtsy’s picture

Status: Needs review » Reviewed & tested by the community

Straight reroll.

webchick’s picture

Just asking, but does this need some benchmarks, since we're going from a straight property reference to a method call?

Berdir’s picture

See Gabor in #50. Directly accessing a property is not an option if we want to allow translated labels. Or actually be able to properly rely on alterable labels, which was introduced in 7.x but is quite pointless there because entity_label() isn't used.

For example, user names currently have a second API (format_username(7.x)/user_format_name(8.x)) that we can get rid of once user entities are converted as well.

For the id() methods, we decided to remove the magic and require an explicit, hard-wired implementation for each entity class that doesn't use the default id property because that is the fastest possible way and we assume that that function is going to be called a lot. I don't think label() is going to be called as often nor is it possible to actually hardcode something there.

So yes, calling a method with some magic in it is slower, but it's unavoidable I think.

Gábor Hojtsy’s picture

#54: 1616962-54.patch queued for re-testing.

kalman.hosszu’s picture

Assigned: Unassigned » kalman.hosszu

If there is any problem, I can dedicate time so solve it.

webchick’s picture

Status: Reviewed & tested by the community » Needs review

Ok, the patch itself is very easy and simply swaps $node->title for $node->label() everywhere. ->label() comes from EntityInterface, and Node is inheriting its logic from Entity::label(). It sounds like there's not a way of doing what we need with pure properties, so we need to eat the performance impact regardless, so I am fine committing this patch. However, I don't think catch would approve of doing so without at least documenting the performance impact, so if someone could please run before/after xhprof numbers, that would be hugely appreciated.

The question I raised in IRC is whether we should remove the $node->title property, since that still exists when you var_dump($node) from, say, node.tpl.php, which raises the likelihood that people will just use that property directly and not go through the API. However, berdir pointed out that this still needs to exist because sometimes (for example on node edit forms) you need to get the "raw" value of the title for presenting to the user. So we're going to keep it for now, but we'll need some sort of holistic answer to this going forward throughout all entity methods, since var_dump($entity) doesn't actually let you know they're there.

So, benchmarks please, and then I'll fast-track this to commit.

webchick’s picture

On IRC it was asked "benchmark what?"

I think if we set the number of nodes on the front page to 50, used devel generate to add 50 nodes, and then added the "Recent Content" block to the sidebar, that would be a pretty decent test. Basically, we want to get a bunch of node titles on the same page, and test before/after the patch.

Berdir’s picture

I very much doubt that there will be a visible change on the whole page load. Loading the front page with 50 nodes involves thousands of function calls and quite some database queries, having 50-100 method calls more is not going to make a difference. But it doesn't hurt to actually do it to have proof.

I believe we can solve the dpm() problem. If we can make the entity property API reality, then we need to make dpm() much more intelligent anyway. I think it should be possible to e.g. extract the methods a class has and list them, just like we list properties. And in the case of the Property API, we can extract the meta information about the existing properties and list them as well, as if they were real properties.

We could actually do rather crazy things with dpm(), like extracting method documentation using reflection and display it somehow or automatically create links to the api.drupal.org documentation based on class/method name.

Gábor Hojtsy’s picture

Are we merely interested in how slower will this patch make Drupal or anybody seeing a way to access language specific versions of a property without introducing either an accessor or yet another array of doom? My understanding of what Drupal 8 is targeting has been accessors instead of more arrays of doom, and that is what the patch does. Not sure what kind of improvement do we hope for then?

Gábor Hojtsy’s picture

Any feedback on my questions?

webchick’s picture

As mentioned in #60 I am interested in a before/after baseline so we know what it is we're dealing with performance-wise. And/or confirmation from catch that he doesn't care about this and to go ahead with commit without this information.

Gábor Hojtsy’s picture

Assigned: kalman.hosszu » Unassigned

Anybody up to help do that?

fgm’s picture

OK, if no one wants to do it in one step, maybe we could just start by defining what

- would be considered a relevant performance test
- at which level the expected slowdown would be too much even in the light of how much something like this is required for our D8MI efforts

Once a test is agreed upon, I can probably perform it.

aspilicious’s picture

I think if we set the number of nodes on the front page to 50, used devel generate to add 50 nodes, and then added the "Recent Content" block to the sidebar, that would be a pretty decent test. Basically, we want to get a bunch of node titles on the same page, and test before/after the patch.

That's all we have to do

Berdir’s picture

Ok, here's what I did.

- Create 100 nodes using devel generate
- Changed front page node number to 50
- Enabled recent content block

$ ab -n 100 -c 1 http://d8/

Before patch:

Requests per second:    8.74 [#/sec] (mean)
Time per request:       114.405 [ms] (mean)

Requests per second:    8.61 [#/sec] (mean)
Time per request:       116.081 [ms] (mean)

Requests per second:    8.66 [#/sec] (mean)
Time per request:       115.416 [ms] (mean)
<code>

After patch:
<code>
Requests per second:    8.73 [#/sec] (mean)
Time per request:       114.525 [ms] (mean)

Requests per second:    8.71 [#/sec] (mean)
Time per request:       114.766 [ms] (mean)

Requests per second:    8.63 [#/sec] (mean)
Time per request:       115.936 [ms] (mean)

As expected, the difference isn't measurable.

I also did some quick profiling with xdebug and the label function was called 110 times, using 0,9% of the request time. Which also explains that there is no measurable difference. What confused me a bit is that we got the expected 50 calls from node_build_content(), 10 from theme_node_recent_content() but also 50 from node_page_title(), through the menu system, not exactly sure why.

I think that's enough to set this back to RTBC, patch still applies. Will also trigger a re-test.

Berdir’s picture

Status: Needs review » Reviewed & tested by the community
Berdir’s picture

#54: 1616962-54.patch queued for re-testing.

fgm’s picture

I think in that test we are essentially testing the page cache after the first page hit, aren't we ? Testing with a logged-in user would possibly be more significant. I think ab can send a cookie, so logging in, catching the current session cookie and passing it to ab should enable authenticated measurement.

webchick’s picture

Title: Replace $node->title with $node->label() » Change Notice: Replace $node->title with $node->label()
Priority: Normal » Critical
Status: Reviewed & tested by the community » Active
Issue tags: +Needs change record

Perfect, thanks a lot Berdir! I'm comfortable committing this now that I know catch won't string me alive (hopefully :)).

Committed and pushed to 8.x. This will need a change notice.

plach’s picture

Great work, guys!

fgm’s picture

More test results (100 nodes, recent content block, ab -c 1 - 100):

Anonymous users

Pre-patch:

Requests per second: 99.81 [#/sec] (mean)
Time per request: 10.019 [ms] (mean)
Requests per second: 71.32 [#/sec] (mean)
Time per request: 14.022 [ms] (mean)
Requests per second: 101.00 [#/sec] (mean)
Time per request: 9.901 [ms] (mean)

Post-patch:

Requests per second: 98.34 [#/sec] (mean)
Time per request: 10.169 [ms] (mean)
Requests per second: 96.08 [#/sec] (mean)
Time per request: 10.408 [ms] (mean)
Requests per second: 74.05 [#/sec] (mean)
Time per request: 13.505 [ms] (mean)

Logged-in users:

Pre-patch;

Requests per second: 3.71 [#/sec] (mean)
Time per request: 269.721 [ms] (mean)
Requests per second: 3.70 [#/sec] (mean)
Time per request: 270.208 [ms] (mean)
Requests per second: 3.67 [#/sec] (mean)
Time per request: 272.115 [ms] (mean)

Post-patch;

Requests per second: 3.75 [#/sec] (mean)
Time per request: 266.838 [ms] (mean)
Requests per second: 3.66 [#/sec] (mean)
Time per request: 273.501 [ms] (mean)
Requests per second: 3.62 [#/sec] (mean)
Time per request: 276.109 [ms] (mean)

So the patch does indeed not seem to have a measurable impact, even for logged-in users: deviation between test series is much higher than between series.

tim.plunkett’s picture

Status: Active » Needs review
j0rd’s picture

From a simple review of the code relating to node->label() vs. node->title, it appears that the performance hit on this patch will come from when someone overrides 'label callback', which currently as far as I can tell isn't done in node. Thus these performance benchmarks don't really apply to the real world use.

Wouldn't it be wise, in a benchmark to test performance impact of this, would be to override 'label callback' with simple O(1) and see what performance impact that has. Although a simple O(1) function is best case, and overrides will only get worse from there.

I'm not 100% sure how testing works in Drupal, but I would hope that tests written in core, could cascade down into contrib modules. Thus if a contrib module would write a slow 'label callback' perhaps a test we write now could catch the performance problem and warn people who will be using / writing contrib modules to keep these calls performant.

Just my two cents.

tim.plunkett’s picture

How would overriding the title callback with a slow function be worsened by this patch?

Gábor Hojtsy’s picture

@j0rd: the motivation of the patch was not however to make title callback more meaningful to override, although that is a side effect. The intention was to pepare the code for multilingual properties. For an example, see #1658712: Refactor test_entity schema to be multilingual. Those overriding the title callback on their custom entities will have a performance impact, but that is not applicable to core.

fgm’s picture

Updated change record at http://drupal.org/node/1697182 with a note about input forms also using property, not label(): I got bit several times by that one when writing the patch.

webchick’s picture

fgm: Could you maybe provide a code example to go alongside your sentence? The sentence alone isn't clear to someone like me who was not involved in rolling the patch and doesn't understand the "gotchas" you ran into.

Gábor Hojtsy’s picture

Also, let's get going again on #1616972: Replace $term->name with $term->label() too :)

Berdir’s picture

Added an example for the form.

fgm’s picture

Title: Replace $node->title with $node->label() » Change Notice: Replace $node->title with $node->label()
Priority: Normal » Critical
Status: Fixed » Needs review
Issue tags: +Needs change record, +sprint

@Berdir: exactly what I meant !

Gábor Hojtsy’s picture

Title: Change Notice: Replace $node->title with $node->label() » Replace $node->title with $node->label()
Priority: Critical » Normal
Status: Needs review » Fixed
Issue tags: -Needs change record, -sprint

Looks like change notice is good :)

Title: Change Notice: Replace $node->title with $node->label() » Replace $node->title with $node->label()
Priority: Critical » Normal
Status: Needs review » Closed (fixed)
Issue tags: -Needs change record, -sprint

Automatically closed -- issue fixed for 2 weeks with no activity.

psynaptic’s picture

Wow, this is a bit confusing. Why are entity titles called labels in the first place?

Berdir’s picture

@psynaptic: There was never such a thing as an "entity title", only "node title". Label is a more generic term and the entity_label() function already existed in 7.x. This does not introduce any new concepts, it just consistently uses one that already exists for quite a long time now.

An entity label can be a node title, a comment subject, a user name, ...

psynaptic’s picture

Thanks for the explanation Berdir.

I ended up here via #1591806: Change block "subject" so that it's called a (admin_)label like everything else on the theme layer in which we tried to change $block->subject to $block->title since that is more consistent from a frontend perpective. I will continue this discussion in http://drupal.org/node/1591806#comment-6623190